14 #if !defined(KRATOS_EDGE_SWAPPING_2D_MODELER_H_INCLUDED )
15 #define KRATOS_EDGE_SWAPPING_2D_MODELER_H_INCLUDED
27 #include "utilities/geometry_utilities.h"
62 for(
int i = 0 ;
i < 3 ;
i++)
64 NeighbourElements[
i] = -1;
65 OppositeNodes[
i] = -1;
69 IsSwapCandidate =
false;
70 IsElementErased =
false;
92 for(
int i = 0 ;
i < 2 ;
i++)
94 CollapseElements[
i] = -1;
99 double MinimumDistance;
165 const int maximum_repeat_number = 10;
167 unsigned int number_of_bad_quality_elements = 1 ;
178 for(
int repeat = 0 ; (repeat < maximum_repeat_number) & (number_of_bad_quality_elements != 0) ; repeat++)
194 std::cout <<
"Edge swapping iteration #" << repeat;
195 SetSwappingData(rThisModelPart);
198 unsigned int swap_counter = 0;
199 for(
int i = 0 ;
i < number_of_elements ;
i++)
201 if(mSwappingData[
i].IsSwapCandidate ==
false)
204 for(
int j = 0 ;
j < 3 ;
j++)
206 const int neighbour_index = mSwappingData[
i].NeighbourElements[
j] - 1;
207 if(neighbour_index >= 0)
209 if(mSwappingData[neighbour_index].IsSwapCandidate ==
false)
212 if(mSwappingData[
i].IsInside[
j])
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;
228 std::cout <<
" number of swaps = " << swap_counter << std::endl;
229 if(swap_counter == 0)
245 for(
int i = 0 ;
i < number_of_elements ;
i++)
247 if(mSwappingData[
i].SwapWith != -1)
251 Swap(*(elements_array[
i]),*(elements_array[mSwappingData[
i].SwapWith]), mSwappingData[
i].SwapEdge, mSwappingData[mSwappingData[
i].SwapWith].SwapEdge);
266 CollapseNodes(rThisModelPart);
288 std::ofstream temp_file(Filename.c_str());
290 temp_file <<
"MESH \"Kratos_Triangle2D3_Mesh\" dimension 2 ElemType Triangle Nnode 3" << std::endl;
292 temp_file <<
"Coordinates" << std::endl;
295 temp_file << i_node->Id() <<
" " << i_node->X() <<
" " << i_node->Y() <<
" " << i_node->Z() << std::endl;
297 temp_file <<
"End Coordinates" << std::endl;
299 temp_file <<
"Elements" << std::endl;
302 temp_file << i_element->Id() <<
" " << i_element->GetGeometry()[0].Id() <<
" " << i_element->GetGeometry()[1].Id() <<
" " << i_element->GetGeometry()[2].Id() <<
" 0"<< std::endl;
305 temp_file <<
"End Elements" << std::endl;
329 virtual std::string
Info()
const override
331 return "EdgeSwapping2DModeler";
335 virtual void PrintInfo(std::ostream& rOStream)
const override
341 virtual void PrintData(std::ostream& rOStream)
const override
361 std::vector<int> mBadQuality;
362 std::vector<std::vector<int> > mNodalNeighbourElements;
363 std::vector<CollapsingData> mCollapsingData;
364 std::vector<SwappingData > mSwappingData;
375 void CollapseNodes(
ModelPart& rThisModelPart)
377 FindNodalNeighbours(rThisModelPart);
378 SetCollapsingData(rThisModelPart);
387 for(
int i = 0 ;
i < number_of_nodes ;
i++)
393 if(r_node.
Is(TO_ERASE))
395 const int node_index = r_node.
Id() - 1;
396 const int nearest_node_id = mCollapsingData[
i].NearestNodeId;
398 if(nearest_node_id != -1)
400 NodeType::Pointer p_node = nodes_array[nearest_node_id - 1];
402 for(std::vector<int>::iterator
i = mNodalNeighbourElements[node_index].begin() ;
i != mNodalNeighbourElements[node_index].end() ;
i++)
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++)
408 int other_node_id = r_neighbour_element_geometry[node_i].
Id();
409 if(other_node_id ==
static_cast<int>(r_node.
Id()))
411 r_neighbour_element_geometry(node_i) = p_node;
413 else if(other_node_id == nearest_node_id)
415 mSwappingData[*
i-1].IsElementErased =
true;
423 r_node.
Set(TO_ERASE,
false);
431 temp_elements_container.
reserve(number_of_elements);
433 temp_elements_container.swap(rThisModelPart.
Elements());
437 for(ModelPart::ElementsContainerType::iterator i_element = temp_elements_container.begin() ; i_element != temp_elements_container.end() ; i_element++)
439 if(
static_cast<bool>(mSwappingData[i_element->Id()-1].IsElementErased) ==
false)
440 (rThisModelPart.
Elements()).push_back(*(i_element.base()));
447 void SetCollapsingData(ModelPart& rThisModelPart)
449 const int number_of_nodes =
static_cast<int>(rThisModelPart.NumberOfNodes());
452 if(
static_cast<int>(mCollapsingData.size()) != number_of_nodes)
453 mCollapsingData.resize(number_of_nodes);
455 for(
int i = 0 ;
i < number_of_nodes ;
i++)
456 mCollapsingData[
i].Reset();
458 for(
int i = 0 ;
i < number_of_nodes ;
i++)
462 if(r_node.
Is(TO_ERASE))
464 SetNodalCollapsingData(r_node, rThisModelPart);
469 void SetNodalCollapsingData(
NodeType& rThisNode, ModelPart& rThisModelPart)
474 const int node_index = rThisNode.
Id() - 1;
476 int next[3] = {1,2,0};
477 int previous[3] = {2,0,1};
480 for(std::vector<int>::iterator
i = mNodalNeighbourElements[node_index].begin() ;
i != mNodalNeighbourElements[node_index].end() ;
i++)
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++)
486 if(r_neighbour_element_geometry[i_node].Is(TO_ERASE) == 0)
488 int other_node_id = r_neighbour_element_geometry[i_node].
Id();
489 if(other_node_id == mCollapsingData[node_index].NearestNodeId)
491 mCollapsingData[node_index].CollapseElements[1] = *
i;
493 else if(r_neighbour_element_geometry[next[i_node]].Id() == rThisNode.
Id())
495 double d=Distance2(r_neighbour_element_geometry[i_node], r_neighbour_element_geometry[next[i_node]]);
497 if((
d < mCollapsingData[node_index].MinimumDistance) || (mCollapsingData[node_index].MinimumDistance < 0.00))
499 mCollapsingData[node_index].MinimumDistance =
d;
500 mCollapsingData[node_index].NearestNodeId = other_node_id;
501 mCollapsingData[node_index].CollapseElements[0] = *
i;
504 else if(r_neighbour_element_geometry[previous[i_node]].Id() == rThisNode.
Id())
506 double d=Distance2(r_neighbour_element_geometry[i_node], r_neighbour_element_geometry[previous[i_node]]);
508 if((
d < mCollapsingData[node_index].MinimumDistance) || (mCollapsingData[node_index].MinimumDistance < 0.00))
510 mCollapsingData[node_index].MinimumDistance =
d;
511 mCollapsingData[node_index].NearestNodeId = other_node_id;
512 mCollapsingData[node_index].CollapseElements[0] = *
i;
526 double dx = rNode1.
X() - rNode2.
X();
527 double dy = rNode1.
Y() - rNode2.
Y();
529 return dx*dx + dy*dy;
532 void Swap(Element& rElement1, Element& rElement2,
int Edge1,
int Edge2)
535 int next2[3] = {2,0,1};
545 rElement1.GetGeometry()(next2[Edge1]) = rElement2.GetGeometry()(Edge2);
546 rElement2.GetGeometry()(next2[Edge2]) = rElement1.GetGeometry()(Edge1);
554 unsigned int MarkBadQualityElements(ModelPart& rThisModelPart)
557 unsigned int marked = 0;
561 if(mBadQuality.size() != rThisModelPart.NumberOfElements())
562 mBadQuality.resize(rThisModelPart.NumberOfElements());
565 const int number_of_elements = rThisModelPart.NumberOfElements();
567 IndexPartition<std::size_t>(number_of_elements).for_each([&](std::size_t
Index){
571 mBadQuality[
Index] =
true;
589 double ElementQuality(Element& rThisElement)
593 double area = rThisElement.GetGeometry().Area();
597 return (area / (h_max*h_max));
600 void FindNodalNeighbours(ModelPart& rThisModelPart)
603 const int number_of_nodes =
static_cast<int>(rThisModelPart.NumberOfNodes());
604 const int number_of_elements =
static_cast<int>(rThisModelPart.NumberOfElements());
606 if(
static_cast<int>(mNodalNeighbourElements.size()) != number_of_nodes)
607 mNodalNeighbourElements.resize(number_of_nodes);
609 for(
int i = 0 ;
i < number_of_nodes ;
i++)
610 mNodalNeighbourElements[
i].clear();
612 for(
int i = 0 ;
i < number_of_elements ;
i++)
615 for(
unsigned int j = 0;
j < r_geometry.size();
j++)
617 mNodalNeighbourElements[r_geometry[
j].Id()-1].push_back(elements_array[
i]->Id());
621 for(
int i = 0 ;
i < number_of_nodes ;
i++)
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());
629 void SetSwappingData(ModelPart& rThisModelPart)
633 const int number_of_elements =
static_cast<int>(rThisModelPart.NumberOfElements());
635 FindNodalNeighbours(rThisModelPart);
637 if(
static_cast<int>(mSwappingData.size()) != number_of_elements)
638 mSwappingData.resize(number_of_elements);
640 IndexPartition<std::size_t>(number_of_elements).for_each([
this](std::size_t
Index){
641 mSwappingData[
Index].Reset();
644 IndexPartition<std::size_t>(number_of_elements).for_each([&](std::size_t
Index){
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++)
652 mSwappingData[
Index].IsInside[
j] = IsInElementSphere(*(elements_array[
Index]), *(nodes_array[mSwappingData[
Index].OppositeNodes[
j]-1]));
660 const int node_index_1 = NodeId1 - 1;
662 rSwappingData.NeighbourElements[EdgeIndex] = -1;
666 for(std::vector<int>::iterator
i = mNodalNeighbourElements[node_index_1].begin() ;
i != mNodalNeighbourElements[node_index_1].end() ;
i++)
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++)
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)))
676 rSwappingData.OppositeNodes[EdgeIndex] = other_node_id;
677 rSwappingData.OppositeEdge[EdgeIndex] = node_i;
680 if (r_neighbour_element_geometry[node_i].Id() == NodeId2)
684 rSwappingData.NeighbourElements[EdgeIndex] = *
i;
688 if(rSwappingData.NeighbourElements[EdgeIndex] != -1)
694 void PrepareForSwapping(ModelPart& rThisModelPart)
696 for(
ModelPart::ElementIterator i_element = rThisModelPart.ElementsBegin() ; i_element != rThisModelPart.ElementsEnd() ; i_element++)
701 bool IsInElementSphere(Element& rThisElement,
NodeType& rThisNode)
706 double ax = r_geometry[0].X();
707 double ay = r_geometry[0].Y();
709 double bx = r_geometry[1].X();
710 double by = r_geometry[1].Y();
712 double cx = r_geometry[2].X();
713 double cy = r_geometry[2].Y();
715 double a2 =
ax*
ax + ay*ay;
716 double b2 = bx*bx + by*by;
717 double c2 = cx*cx + cy*cy;
719 double vx = rThisNode.
X();
720 double vy = rThisNode.
Y();
722 double v2 = vx*vx + vy*vy;
725 double a11 = r_geometry[0].X()-rThisNode.
X();
726 double a12 = r_geometry[0].Y()-rThisNode.
Y();
727 double a13 = a2 - v2;
729 double a21 = r_geometry[1].X()-rThisNode.
X();
730 double a22 = r_geometry[1].Y()-rThisNode.
Y();
731 double a23 = b2 - v2;
733 double a31 = r_geometry[2].X()-rThisNode.
X();
734 double a32 = r_geometry[2].Y()-rThisNode.
Y();
735 double a33 = c2 - v2;
737 return ( ( a11*(a22*a33-a23*a32) + a12*(a23*a31-a21*a33) + a13*(a21*a32-a22*a31) ) > 0.0 );
786 rOStream << std::endl;
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
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