1#ifndef ALUGRID_COMPATIBILITY_CHECK_HH_INCLUDED
2#define ALUGRID_COMPATIBILITY_CHECK_HH_INCLUDED
15struct BisectionCompatibilityParameters
17 static int& variant ()
23 static int& threshold ()
29 static int& useAnnouncedEdge ()
39template <
class VertexVector>
40class BisectionCompatibility
42 typedef BisectionCompatibility< VertexVector > ThisType;
45 typedef VertexVector VertexVectorType;
47 typedef std::array<unsigned int, 3> FaceType;
48 typedef std::vector< unsigned int > ElementType;
49 typedef std::array<unsigned int, 2> EdgeType;
50 typedef std::map< FaceType, EdgeType > FaceMapType;
51 typedef std::pair< FaceType, EdgeType > FaceElementType;
54 const VertexVectorType& vertices_;
57 std::vector<ElementType> elements_;
58 std::vector<bool> elementOrientation_;
60 FaceMapType neighbours_;
62 const size_t nVertices_;
65 std::vector<bool> containedInV0_;
67 std::vector<int> types_;
70 bool stevensonRefinement_;
77 unsigned int type1node_;
79 unsigned int type1face_;
85 const int variant_ = BisectionCompatibilityParameters::variant() ;
86 const int threshold_ = BisectionCompatibilityParameters::threshold() ;
87 const bool useAnnouncedEdge_ = BisectionCompatibilityParameters::useAnnouncedEdge();
92 BisectionCompatibility(
const VertexVectorType& vertices,
93 const std::vector<ElementType>& elements,
95 : vertices_( vertices ),
96 elements_( elements ),
97 elementOrientation_(elements_.size(), true),
98 nVertices_( vertices_.size() ),
99 containedInV0_(nVertices_,true),
100 types_(elements_.size(), 0),
101 stevensonRefinement_(stevenson),
102 type0nodes_( stevensonRefinement_ ? EdgeType{0,3} : EdgeType{0,1} ),
103 type0faces_( stevensonRefinement_ ? EdgeType{3,0} : EdgeType{3,2} ),
104 type1node_( stevensonRefinement_ ? 1 : 2 ),
105 type1face_( 3 - type1node_ )
110 std::cout <<
"Build neighbors took " << timer.
elapsed() <<
" sec." << std::endl;
114 int stronglyCompatibleFaces ()
117 bool verbose =
false;
118 unsigned int bndFaces = 0;
119 std::vector<int> nonCompatFacesAtVertex(nVertices_, 0 );
120 for(
auto&& face : neighbours_)
122 if( face.second[0] == face.second[1] )
126 else if(! checkStrongCompatibility(face, verbose))
129 for(
size_t i =0; i < 3; ++i)
131 ++(nonCompatFacesAtVertex[face.first[i]]);
135 std::cout <<
"NotStrongCompatibleMacroFaces" <<
" InnerFaces " <<
" TotalFaces " <<
"Maximum/Vertex " <<
" Minimum/Vertex " << std::endl;
136 std::cout << result <<
" " << neighbours_.size() - bndFaces <<
" " << neighbours_.size() <<
" " << *(std::max_element(nonCompatFacesAtVertex.begin(), nonCompatFacesAtVertex.end())) <<
" " << *(std::min_element(nonCompatFacesAtVertex.begin(), nonCompatFacesAtVertex.end())) << std::endl << std::endl;
142 bool compatibilityCheck ()
144 for(
auto&& face : neighbours_)
146 if(!checkFaceCompatibility(face))
return false;
151 bool make6CompatibilityCheck()
154 applyStandardOrientation();
155 bool result = compatibilityCheck();
157 applyStandardOrientation();
164 for(
auto&& face : neighbours_)
166 std::cout << face.first[0] <<
"," << face.first[1] <<
"," << face.first[2] <<
" : " << face.second[0] <<
", " << face.second[1] << std::endl;
171 void printElement(
int index)
173 ElementType el = elements_[index];
175 std::cout <<
"[" << el[0] ;
176 for(
int i=1; i < 4; ++i)
177 std::cout <<
","<< el[i] ;
178 std::cout <<
"] Refinement Edges: ";
179 for(
int i=0; i< 4; ++i)
181 getRefinementEdge(el, i, edge, types_[index]);
182 std::cout <<
"[" << edge[0] <<
"," << edge[1] <<
"] ";
184 std::cout <<
" Type: " << types_[ index ] <<
" V1: ";
185 for (
size_t i = 0; i < 4; ++i) {
186 if( ! containedInV0_[ el [ i ] ] )
187 std::cout << el[i] <<
"," ;
189 std::cout << std::endl;
195 bool type0Algorithm( )
201 calculateV0( variant_, threshold_ );
202 const bool useAnnounced = useAnnouncedEdge_;
205 std::fill( types_.begin(), types_.end(), 0 );
207 std::list<std::pair<FaceType, EdgeType> > activeFaceList;
208 std::vector<bool> doneElements(elements_.size(),
false);
210 std::vector< std::pair< double, std::pair< int,int > > > vertexOrder( nVertices_ , std::make_pair(-1.0, std::make_pair(-1,-2) ) );
211 const double eps = std::numeric_limits< double >::epsilon() * double(nVertices_) * 10.0;
214 const unsigned int l1 = -1;
216 const int numberOfElements = elements_.size();
218 for(
int counter = 0; counter < numberOfElements ; ++counter)
220 FaceElementType faceElement = std::make_pair( FaceType{l1,l1,l1}, EdgeType{l1,l1} );
224 const ElementType& el0 = elements_[0];
225 getFace(el0, type0faces_[0], face);
226 faceElement = FaceElementType(std::make_pair( face , EdgeType{0,0} ) );
229 for(
unsigned int i=0 ; i < 4 ; ++i)
232 vertexOrder[ vtx ].first = i+1;
234 vertexOrder[ vtx ].second.first = i > 0 ? el0[ i-1 ] : -1;
235 vertexOrder[ vtx ].second.second = i < 3 ? el0[ i+1 ] : -2;
240 assert( ! activeFaceList.empty() );
242 auto it = activeFaceList.begin();
243 int el1 = it->second[ 0 ];
244 int el2 = it->second[ 1 ];
246 while( doneElements[ el1 ] && doneElements[ el2 ] )
248 activeFaceList.erase( it++ );
269 assert( it != activeFaceList.end() );
270 el1 = it->second[ 0 ];
271 el2 = it->second[ 1 ];
278 int elIndex = faceElement.second[0];
281 int neighIndex = faceElement.second[1];
282 if(!doneElements[elIndex])
284 assert(doneElements[neighIndex] || counter == 0 );
285 std::swap(elIndex, neighIndex);
288 assert(!doneElements[neighIndex] || counter == 0);
289 doneElements[neighIndex] =
true;
290 ElementType el = elements_[elIndex];
291 ElementType & neigh = elements_[neighIndex];
292 unsigned int faceInEl = getFaceIndex(el, faceElement.first);
293 unsigned int nodeInEl = 3 - faceInEl;
294 unsigned int faceInNeigh = getFaceIndex(neigh, faceElement.first);
295 unsigned int nodeInNeigh = 3 - faceInNeigh;
299 ElementType newNeigh(el);
302 if( vertexOrder[ neigh [ nodeInNeigh ] ].first < 0 )
304 int vxIndex = el[ nodeInEl ];
308 if( useAnnounced && (nodeInEl == type0nodes_[0] && nodeInNeigh == type0nodes_[1] ) )
310 auto& vxPair = vertexOrder[ el[ nodeInNeigh ] ];
312 vxIndex = vxPair.second.second;
315 vertexOrder[ neigh [ nodeInNeigh ] ] = std::make_pair( vxPair.first+1.0, std::make_pair( el[ nodeInNeigh ], -2 ) );
316 vxPair.second.second = neigh [ nodeInNeigh ];
323 if ( useAnnounced && ( nodeInEl == type0nodes_[1] && nodeInNeigh == type0nodes_[0] ) )
325 vxIndex = el[ nodeInNeigh ];
328 auto& vxPair = vertexOrder[ vxIndex ];
329 assert( vxPair.first >= 0 );
332 const int prevIdx = vxPair.second.first ;
333 double prevOrder = ( prevIdx == -1 ) ? 0.0 : vertexOrder[ prevIdx ].first;
334 double newOrder = 0.5 * (vxPair.first + prevOrder);
336 vertexOrder[ neigh [ nodeInNeigh ] ] = std::make_pair( newOrder, std::make_pair( prevIdx, vxIndex ) );
338 vertexOrder[ prevIdx ].second.second = neigh [ nodeInNeigh ];
339 vxPair.second.first = neigh [ nodeInNeigh ];
340 assert( vxPair.first > newOrder );
342 if( (vxPair.first - newOrder) < eps )
346 std::cout <<
"Rescale vertex order weights." << std::endl;
348 std::map< double, int > newVertexOrder;
349 const int size = vertexOrder.size();
350 for(
int j=0; j<size; ++j )
352 if( vertexOrder[ j ].first > 0.0 )
354 newVertexOrder.insert( std::make_pair( vertexOrder[ j ].first, j ) );
359 for(
const auto& vx: newVertexOrder )
361 assert( vx.second >=0 && vx.second < size );
362 vertexOrder[ vx.second ].first = count++ ;
365 for(
int j=0; j<size; ++j )
367 if( vertexOrder[ j ].first > 0.0 && vertexOrder[ j ].second.first >= 0 )
369 if( vertexOrder[ j ].first <= vertexOrder[ vertexOrder[ j ].second.first ].first )
374 std::cout <<
"Rescale done, time = " << restimer.
elapsed() << std::endl;
382 std::map< double, int > vx;
383 for(
int j=0; j<4; ++j )
385 assert( vertexOrder[ neigh[ j ] ].first > 0 );
386 vx.insert( std::make_pair( vertexOrder[ neigh[ j ] ].first, j ) );
390 for(
const auto& vxItem : vx )
392 newNeigh[ count++ ] = neigh[ vxItem.second ] ;
397 unsigned int type = 0;
399 for(
unsigned int i =0; i < 4; ++i)
401 contained[i] = containedInV0_[newNeigh[i]];
405 if( ( contained[0] && contained[1] && contained[2] && contained[3] ) || ( !contained[0] && !contained[1] && !contained[2] && !contained[3] ) )
412 ElementType V0Part(newNeigh);
413 ElementType V1Part(newNeigh);
414 for(
unsigned int i = 0 ; i < 4; ++i)
418 auto it = std::find(V1Part.begin(),V1Part.end(),newNeigh[i]);
423 auto it = std::find(V0Part.begin(),V0Part.end(),newNeigh[i]);
428 for(
unsigned int i = 0; i < 4; ++i)
431 newNeigh[ i ] = V0Part[ i ];
433 newNeigh[ i ] = V1Part[ i - 1 ] ;
435 newNeigh[ i ] = V0Part[ i - type];
438 types_[neighIndex] = type % 3;
442 bool neighOrientation = elementOrientation_[neighIndex];
443 for(
unsigned int i =0 ; i < 3; ++i)
445 if( newNeigh[i] != neigh[i] )
447 auto neighIt = std::find(neigh.begin() + i,neigh.end(),newNeigh[i]);
448 std::swap(*neighIt,neigh[i]);
449 neighOrientation = ! neighOrientation;
452 elementOrientation_[neighIndex] = neighOrientation;
454 for(
unsigned int i = 0; i < 4 ; ++i)
456 getFace(neigh, i, faceElement);
458 if(faceElement.second[0] == faceElement.second[1])
462 if(i != type0faces_[0] && i != type0faces_[1] )
463 activeFaceList.push_back(faceElement);
465 activeFaceList.push_front(faceElement);
469 const int onePercent = numberOfElements / 100 ;
470 if( onePercent > 0 && counter % onePercent == 0 )
472 std::cout <<
"Done: element " << counter <<
" of " << numberOfElements <<
" time used = " << timer.
elapsed() << std::endl;
478 return compatibilityCheck();
483 bool type1Algorithm()
489 std::fill( types_.begin(), types_.end(), 1 );
493 FaceMapType activeFaces, freeFaces;
496 std::vector<int> nodePriority;
497 nodePriority.resize(nVertices_ , -1);
498 int currNodePriority =nVertices_;
500 const unsigned int numberOfElements = elements_.size();
502 for(
unsigned int elIndex =0 ; elIndex < numberOfElements; ++elIndex)
505 ElementType & el = elements_[elIndex];
506 int priorityNode = -1;
509 for(
int i = 0; i < 4; ++i)
511 int tmpPrio = nodePriority[el[i]];
515 if( priorityNode < 0 || tmpPrio > nodePriority[el[priorityNode]] )
518 getFace(el,3 - i,face );
520 if(freeFaces.find(face) != freeFaces.end())
523 if(priorityNode > -1)
525 fixNode(el, priorityNode);
527 else if(freeNode > -1)
529 nodePriority[el[freeNode]] = currNodePriority;
530 fixNode(el, freeNode);
535 nodePriority[el[type1node_]] = currNodePriority;
536 fixNode(el, type1node_);
540 FaceElementType faceElement;
543 getFace(el,type1face_, faceElement);
544 getFace(el,type1face_, face);
546 const auto freeFacesEnd = freeFaces.end();
547 const auto freeFaceIt = freeFaces.find(face);
548 if( freeFaceIt != freeFacesEnd)
550 while(!checkFaceCompatibility(faceElement))
554 freeFaceIt->second[1] = elIndex;
556 else if(activeFaces.find(face) != activeFaces.end())
558 while(!checkFaceCompatibility(faceElement))
562 activeFaces.erase(face);
566 freeFaces.insert({{face,{elIndex,elIndex}}});
570 for(
auto&& i : {0,1,2,3})
572 if (i == type1face_)
continue;
575 getFace(el,i,faceElement);
577 unsigned int neighborIndex = faceElement.second[0] == elIndex ? faceElement.second[1] : faceElement.second[0];
578 if(freeFaces.find(face) != freeFacesEnd)
580 while(!checkFaceCompatibility(faceElement))
582 rotate(elements_[neighborIndex]);
585 else if(activeFaces.find(face) != activeFaces.end())
587 if(!checkFaceCompatibility(faceElement))
589 checkFaceCompatibility(faceElement,
true) ;
592 activeFaces.erase(face);
596 activeFaces.insert({{face,{elIndex,elIndex}}});
615 void returnElements(std::vector<ElementType> & elements,
616 std::vector<bool>& elementOrientation,
617 std::vector<int>& types,
618 const bool stevenson =
false )
631 const int nElements = elements_.size();
632 for(
int el = 0; el<nElements; ++el )
635 if( ! elementOrientation_[ el ] )
638 std::swap( elements_[ el ][ 2 ], elements_[ el ][ 3 ] );
642 elements = elements_;
643 elementOrientation = elementOrientation_;
647 void stevenson2Alberta()
649 if( stevensonRefinement_ )
651 swapRefinementType();
655 void alberta2Stevenson()
657 if( ! stevensonRefinement_ )
659 swapRefinementType();
664 void swapRefinementType()
666 const int nElements = elements_.size();
667 for(
int el = 0; el<nElements; ++el )
669 elementOrientation_[ el ] = !elementOrientation_[ el ];
670 std::swap(elements_[ el ][ 1 ], elements_[ el ][ 3 ]);
674 stevensonRefinement_ = ! stevensonRefinement_;
675 type0nodes_ = stevensonRefinement_ ? EdgeType{0,3} : EdgeType{0,1} ;
676 type0faces_ = stevensonRefinement_ ? EdgeType{3,0} : EdgeType{3,2} ;
677 type1node_ = stevensonRefinement_ ? 1 : 2 ;
678 type1face_ = ( 3 - type1node_ );
682 void applyStandardOrientation ()
685 for(
auto & element : elements_ )
689 std::swap(element[2],element[3]);
690 elementOrientation_[i] = ! elementOrientation_[i];
694 types_.resize(elements_.size(), 0);
698 bool checkFaceCompatibility(std::pair<FaceType, EdgeType> face,
bool verbose =
false)
700 EdgeType edge1,edge2;
701 int elIndex = face.second[0];
702 int neighIndex = face.second[1];
703 if(elIndex != neighIndex)
705 getRefinementEdge(elements_[elIndex], face.first, edge1, types_[elIndex]);
706 getRefinementEdge(elements_[neighIndex], face.first, edge2, types_[neighIndex]);
715 printElement(elIndex);
716 printElement(neighIndex);
725 bool checkStrongCompatibility(std::pair<FaceType, EdgeType> face,
bool verbose =
false)
727 int elIndex = face.second[0];
728 int neighIndex = face.second[1];
731 if(elIndex != neighIndex)
733 int elType = types_[elIndex];
734 int neighType = types_[neighIndex];
735 unsigned int elFaceIndex = getFaceIndex(elements_[elIndex], face.first);
736 unsigned int elNodeIndex = 3 - elFaceIndex;
737 unsigned int neighFaceIndex = getFaceIndex(elements_[neighIndex], face.first);
738 unsigned int neighNodeIndex = 3 - neighFaceIndex;
739 if(elType == neighType)
745 if( elNodeIndex == neighNodeIndex ||
746 (elNodeIndex == type0nodes_[0] && neighNodeIndex == type0nodes_[1]) ||
747 (elNodeIndex == type0nodes_[1] && neighNodeIndex == type0nodes_[0]) )
752 if( elType % 3 == (neighType +1) %3 )
754 std::swap(elType, neighType);
755 std::swap(elNodeIndex, neighNodeIndex);
756 std::swap(elFaceIndex, neighFaceIndex);
757 std::swap(elIndex, neighIndex);
761 assert(neighType == 1);
762 if( ( neighNodeIndex == type1node_ ) && ( elNodeIndex == type0nodes_[0] || elNodeIndex == type0nodes_[1] ) )
766 assert(neighType == 2);
767 if( ( neighNodeIndex == type1node_ ) && ( elNodeIndex == type0nodes_[0] || elNodeIndex == type0nodes_[1] ) )
771 assert(neighType == 0);
772 if( ( neighNodeIndex == type1node_ ) && ( elNodeIndex == type0nodes_[0] || elNodeIndex == type0nodes_[1] ) )
776 std::cerr <<
"No other types than 0,1,2 implemented. Aborting" << std::endl;
785 if (verbose && result ==
false )
791 printElement(elIndex);
792 printElement(neighIndex);
797 void fixNode(ElementType& el,
int node)
799 if(!(node == type1node_))
802 std::swap(el[node],el[type1node_]);
805 std::swap(el[(type1node_+1)%4],el[(type1node_+2)%4]);
810 void rotate(ElementType& el)
812 std::swap(el[(type1node_+1)%4],el[(type1node_+2)%4]);
813 std::swap(el[(type1node_+1)%4],el[(type1node_+3)%4]);
818 void getFace(ElementType el,
int faceIndex, FaceType & face )
823 face = {el[1],el[2],el[3]};
826 face = {el[0],el[2],el[3]};
829 face = {el[0],el[1],el[3]};
832 face = {el[0],el[1],el[2]};
835 std::cerr <<
"index " << faceIndex <<
" NOT IMPLEMENTED FOR TETRAHEDRONS" << std::endl;
838 std::sort(face.begin(), face.end());
842 void getFace(ElementType el,
int faceIndex, FaceElementType & faceElement)
845 getFace(el, faceIndex, face);
846 faceElement = *neighbours_.find(face);
852 void getRefinementEdge(ElementType el,
int faceIndex, EdgeType & edge,
int type )
856 if(stevensonRefinement_)
861 edge = {el[0],el[2]};
864 edge = {el[0],el[3]};
867 edge = {el[0],el[3]};
870 edge = {el[1],el[3]};
873 std::cerr <<
"index " << faceIndex <<
" NOT IMPLEMENTED FOR TETRAHEDRONS" << std::endl;
882 edge = {el[0],el[1]};
885 edge = {el[0],el[1]};
888 edge = {el[0],el[2]};
891 edge = {el[1],el[3]};
894 std::cerr <<
"index " << faceIndex <<
" NOT IMPLEMENTED FOR TETRAHEDRONS" << std::endl;
899 else if(type == 1 || type == 2)
901 if(stevensonRefinement_)
906 edge = {el[0],el[2]};
909 edge = {el[0],el[3]};
912 edge = {el[0],el[3]};
915 edge = {el[2],el[3]};
918 std::cerr <<
"index " << faceIndex <<
" NOT IMPLEMENTED FOR TETRAHEDRONS" << std::endl;
927 edge = {el[0],el[1]};
930 edge = {el[0],el[1]};
933 edge = {el[0],el[3]};
936 edge = {el[1],el[3]};
939 std::cerr <<
"index " << faceIndex <<
" NOT IMPLEMENTED FOR TETRAHEDRONS" << std::endl;
946 std::cerr <<
"no other types than 0, 1, 2 implemented." << std::endl;
949 std::sort(edge.begin(),edge.end());
954 void getRefinementEdge(ElementType el, FaceType face, EdgeType & edge,
int type )
956 getRefinementEdge(el, getFaceIndex(el, face), edge, type);
962 int getFaceIndex(ElementType el, FaceType face)
964 for(
int i =0; i<4 ; ++i)
966 if(!( el[i] == face[0] || el[i] == face[1] || el[i] == face[2] ) )
977 void buildNeighbors()
985 unsigned int index = 0;
986 const auto nend = neighbours_.end();
987 for(
auto&& el : elements_)
989 for(
int i = 0; i< 4; ++i)
991 getFace(el, i, face);
992 auto faceInList = neighbours_.find(face);
993 if(faceInList == nend)
995 indexPair = {index, index};
996 neighbours_.insert(std::make_pair (face, indexPair ) );
1000 assert(faceInList != neighbours_.end());
1001 faceInList->second[1] = index;
1016 void calculateV0(
int variante,
int threshold)
1022 std::fill(containedInV0_.begin(),containedInV0_.end(),
false);
1023 std::vector<int> numberOfAdjacentRefEdges(nVertices_, 0);
1026 for(
auto&& el : elements_)
1028 numberOfAdjacentRefEdges [ el [ type0nodes_[ 0 ] ] ] ++;
1029 numberOfAdjacentRefEdges [ el [ type0nodes_[ 1 ] ] ] ++;
1031 for(
unsigned int i = 0; i <nVertices_ ; ++i)
1033 if(numberOfAdjacentRefEdges[ i ] >= threshold )
1035 containedInV0_[ i ] =
true;
1042 std::vector<int> numberOfAdjacentElements(nVertices_, 0);
1043 std::vector<bool> vertexOnBoundary(nVertices_,
false);
1044 for(
auto&& neigh : neighbours_)
1047 if(neigh.second[1] == neigh.second[0])
1049 for(
unsigned int i =0; i < 3 ; ++i)
1051 vertexOnBoundary[ neigh.first [ i ] ] =
true;
1056 for(
auto&& el : elements_)
1058 for(
unsigned int i =0; i < 4; ++i)
1060 numberOfAdjacentElements[ el [ i ] ] ++;
1063 for(
unsigned int i = 0; i <nVertices_ ; ++i)
1065 double bound = vertexOnBoundary[ i ] ? threshold / 2. : threshold ;
1066 if(numberOfAdjacentElements[ i ] < bound )
1068 containedInV0_[ i ] =
false;
1076 std::default_random_engine generator;
1077 std::uniform_int_distribution<int> distribution(1,6);
1078 for(
unsigned int i = 0; i < nVertices_; ++i)
1080 int roll = distribution(generator);
1083 containedInV0_[ i ] =
false;
1092 for(
unsigned int i =0 ; i < nVertices_; ++i)
1094 if( containedInV0_ [ i ] )
1104 std::cout <<
"#V0 #V1" << std::endl << sizeOfV0 <<
" " << sizeOfV1 << std::endl;
A simple stop watch.
Definition: timer.hh:43
void reset() noexcept
Reset timer while keeping the running/stopped state.
Definition: timer.hh:57
double elapsed() const noexcept
Get elapsed user-time from last reset until now/last stop in seconds.
Definition: timer.hh:77