LCOV - code coverage report
Current view: top level - ugbase/lib_grid/refinement - hanging_node_refiner_base.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 691 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 96 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2011-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Sebastian Reiter
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #include <vector>
      34              : #include "hanging_node_refiner_base.h"
      35              : #include "lib_grid/algorithms/geom_obj_util/geom_obj_util.h"
      36              : #include "lib_grid/algorithms/debug_util.h"
      37              : #include "lib_grid/algorithms/subset_util.h"
      38              : #include "lib_grid/file_io/file_io.h"
      39              : #include "ref_mark_adjusters/std_hnode_adjuster.h"
      40              : #include "lib_grid/tools/selector_multi_grid.h"
      41              : #include "lib_grid/tools/periodic_boundary_manager.h"
      42              : 
      43              : #ifdef UG_PARALLEL
      44              :         #include "pcl/pcl_util.h"
      45              : #endif
      46              : 
      47              : //define PROFILE_HANGING_NODE_REFINER if you want to profile
      48              : //the refinement code.
      49              : #define PROFILE_HANGING_NODE_REFINER
      50              : #ifdef PROFILE_HANGING_NODE_REFINER
      51              :         #define HNODE_PROFILE_FUNC()    PROFILE_FUNC()
      52              :         #define HNODE_PROFILE_BEGIN(name)       PROFILE_BEGIN(name)
      53              :         #define HNODE_PROFILE_END()     PROFILE_END()
      54              : #else
      55              :         #define HNODE_PROFILE_FUNC()
      56              :         #define HNODE_PROFILE_BEGIN(name)
      57              :         #define HNODE_PROFILE_END()
      58              : #endif
      59              : 
      60              : 
      61              : using namespace std;
      62              : 
      63              : namespace ug{
      64              : template <class TSelector>
      65            0 : HangingNodeRefinerBase<TSelector>::
      66              : HangingNodeRefinerBase(SPRefinementProjector projector) :
      67              :         IRefiner(projector),
      68            0 :         m_pGrid(NULL),
      69            0 :         m_nodeDependencyOrder1(true),
      70            0 :         m_adjustingRefMarks(false)
      71              :         //,m_automarkHigherDimensionalObjects(false)
      72              : {
      73            0 :         add_ref_mark_adjuster(StdHNodeAdjuster::create());
      74            0 : }
      75              : 
      76              : template <class TSelector>
      77            0 : HangingNodeRefinerBase<TSelector>::
      78            0 : HangingNodeRefinerBase(const HangingNodeRefinerBase&)
      79              : {
      80            0 :         throw(UGError("no copy construction allowed."));
      81            0 : }
      82              : 
      83              : template <class TSelector>
      84            0 : HangingNodeRefinerBase<TSelector>::
      85              : ~HangingNodeRefinerBase()
      86              : {
      87            0 :         if(m_pGrid)
      88              :         {
      89            0 :                 m_pGrid->unregister_observer(this);
      90              :         }
      91            0 : }
      92              : 
      93              : template <class TSelector>
      94            0 : void HangingNodeRefinerBase<TSelector>::
      95              : set_grid(typename TSelector::grid_type* grid)
      96              : {
      97            0 :         if(m_pGrid)
      98              :         {
      99            0 :                 m_pGrid->unregister_observer(this);
     100            0 :                 m_selMarkedElements.assign_grid(NULL);
     101            0 :                 m_pGrid = NULL;
     102              :         }
     103              : 
     104            0 :         if(grid){
     105            0 :                 m_pGrid = grid;
     106            0 :                 grid->register_observer(this, OT_GRID_OBSERVER);
     107            0 :                 m_selMarkedElements.assign_grid(*grid);
     108            0 :                 m_selMarkedElements.enable_autoselection(false);
     109            0 :                 m_selMarkedElements.enable_selection_inheritance(false);
     110            0 :                 set_message_hub(grid->message_hub());
     111              :         }
     112            0 : }
     113              : 
     114              : template <class TSelector> void
     115            0 : HangingNodeRefinerBase<TSelector>::grid_to_be_destroyed(Grid* grid)
     116              : {
     117            0 :         m_pGrid = NULL;
     118            0 : }
     119              : 
     120              : template <class TSelector> void
     121            0 : HangingNodeRefinerBase<TSelector>::clear_marks()
     122              : {
     123            0 :         m_selMarkedElements.clear();
     124              :         m_newlyMarkedRefVrts.clear();
     125              :         m_newlyMarkedRefEdges.clear();
     126              :         m_newlyMarkedRefFaces.clear();
     127              :         m_newlyMarkedRefVols.clear();
     128            0 : }
     129              : 
     130              : template <class TSelector>
     131            0 : bool HangingNodeRefinerBase<TSelector>::
     132              : mark(Vertex* v, RefinementMark refMark)
     133              : {
     134              :         assert(m_pGrid && "ERROR in HangingNodeRefinerBase::mark_for_refinement(...): No grid assigned.");
     135            0 :         if(get_mark(v) != refMark){
     136              :         //      if ref-mark-adjustment is taking place, we'll also allow for the selection
     137              :         //      of non-surface vertices
     138            0 :                 if(refinement_is_allowed(v) || m_adjustingRefMarks){
     139            0 :                         m_selMarkedElements.select(v, refMark);
     140            0 :                         if(m_adjustingRefMarks && (refMark & (RM_FULL | RM_LOCAL | RM_CLOSURE | RM_DUMMY)))
     141            0 :                                 m_newlyMarkedRefVrts.push_back(v);
     142            0 :                         return true;
     143              :                 }
     144              :         }
     145              :         return false;
     146              : }
     147              : 
     148              : template <class TSelector>
     149            0 : bool HangingNodeRefinerBase<TSelector>::mark(Edge* e, RefinementMark refMark)
     150              : {
     151              :         assert(m_pGrid && "ERROR in HangingNodeRefinerBase::mark_for_refinement(...): No grid assigned.");
     152            0 :         if(get_mark(e) != refMark){
     153            0 :                 if(refinement_is_allowed(e)){
     154            0 :                         m_selMarkedElements.select(e, refMark);
     155            0 :                         if(m_adjustingRefMarks && (refMark & (RM_REFINE | RM_LOCAL | RM_CLOSURE | RM_DUMMY)))
     156            0 :                                 m_newlyMarkedRefEdges.push_back(e);
     157            0 :                         return true;
     158              :                 }
     159              :         }
     160              :         return false;
     161              : }
     162              : 
     163              : template <class TSelector>
     164            0 : bool HangingNodeRefinerBase<TSelector>::mark(Face* f, RefinementMark refMark)
     165              : {
     166              :         assert(m_pGrid && "ERROR in HangingNodeRefinerBase::mark_for_refinement(...): No grid assigned.");
     167              : 
     168            0 :         if(get_mark(f) != refMark){
     169            0 :                 if(refinement_is_allowed(f)){
     170            0 :                         m_selMarkedElements.select(f, refMark);
     171            0 :                         if(m_adjustingRefMarks && (refMark & (RM_REFINE | RM_LOCAL | RM_CLOSURE | RM_DUMMY)))
     172            0 :                                 m_newlyMarkedRefFaces.push_back(f);
     173            0 :                         return true;
     174              :                 }
     175              :         }
     176              :         return false;
     177              : }
     178              : 
     179              : template <class TSelector>
     180            0 : bool HangingNodeRefinerBase<TSelector>::mark(Volume* v, RefinementMark refMark)
     181              : {
     182              :         assert(m_pGrid && "ERROR in HangingNodeRefinerBase::mark_for_refinement(...): No grid assigned.");
     183            0 :         if(get_mark(v) != refMark){
     184            0 :                 if(refinement_is_allowed(v)){
     185            0 :                         m_selMarkedElements.select(v, refMark);
     186            0 :                         if(m_adjustingRefMarks && (refMark & (RM_REFINE | RM_LOCAL | RM_CLOSURE | RM_DUMMY)))
     187            0 :                                 m_newlyMarkedRefVols.push_back(v);
     188            0 :                         return true;
     189              :                 }
     190              :         }
     191              :         return false;
     192              : }
     193              : 
     194              : template <class TSelector>
     195            0 : void HangingNodeRefinerBase<TSelector>::
     196              : mark_neighborhood(size_t numIterations, RefinementMark refMark, bool sideNbrsOnly)
     197              : {
     198            0 :         if(!m_pGrid)
     199            0 :                 return;
     200              : 
     201              :         typedef typename TSelector::template traits<Vertex>::iterator     SelVrtIter;
     202              :         typedef typename TSelector::template traits<Edge>::iterator               SelEdgeIter;
     203              :         typedef typename TSelector::template traits<Face>::iterator                       SelFaceIter;
     204              :         typedef typename TSelector::template traits<Volume>::iterator             SelVolIter;
     205              : 
     206              :         Grid::edge_traits::secure_container             edges;
     207              :         Grid::face_traits::secure_container             faces;
     208              :         Grid::volume_traits::secure_container   vols;
     209              : 
     210            0 :         EdgeDescriptor edesc;
     211              : 
     212            0 :         TSelector& sel = m_selMarkedElements;
     213            0 :         Grid& g = *m_pGrid;
     214              : 
     215              :         #ifdef UG_PARALLEL
     216              :                 bool hasVolumes = pcl::OneProcTrue(g.num_volumes() > 0);
     217              :                 bool hasFaces;
     218              :                 if(hasVolumes)
     219              :                         hasFaces = true;
     220              :                 else
     221              :                         hasFaces = pcl::OneProcTrue(g.num_faces() > 0);
     222              :                 bool hasEdges;
     223              :                 if(hasFaces)
     224              :                         hasEdges = true;
     225              :                 else
     226              :                         hasEdges = pcl::OneProcTrue(g.num_edges() > 0);
     227              :         #else
     228              :                 bool hasEdges   = g.num_edges() > 0;
     229              :                 bool hasFaces   = g.num_faces() > 0;
     230              :                 bool hasVolumes = g.num_volumes() > 0;
     231              :         #endif
     232              : 
     233              : //todo: Speed could be improved by only considering newly marked elements after each iteration.
     234            0 :         for(size_t iteration = 0; iteration < numIterations; ++iteration){
     235            0 :                 if(sideNbrsOnly){
     236              :                 //      first we'll select all unselected sides which are connected to marked elements
     237            0 :                         for(SelVolIter iter = sel.template begin<Volume>();
     238            0 :                                 iter != sel.template end<Volume>(); ++iter)
     239              :                         {
     240              :                                 Volume* vol = *iter;
     241            0 :                                 RefinementMark s = get_mark(vol);
     242              :                                 g.associated_elements(faces, vol);
     243            0 :                                 for_each_in_vec(Face* f, faces){
     244            0 :                                         if(!sel.is_selected(f) && this->refinement_is_allowed(f))
     245            0 :                                                 this->mark(f, s);
     246              :                                 }end_for;
     247              :                         }
     248              : 
     249            0 :                         for(SelFaceIter iter = sel.template begin<Face>();
     250            0 :                                 iter != sel.template end<Face>(); ++iter)
     251              :                         {
     252              :                                 Face* f = *iter;
     253            0 :                                 RefinementMark s = get_mark(f);
     254              :                                 g.associated_elements(edges, f);
     255            0 :                                 for_each_in_vec(Edge* e, edges){
     256            0 :                                         if(!sel.is_selected(e) && this->refinement_is_allowed(e))
     257            0 :                                                 this->mark(e, s);
     258              :                                 }end_for;
     259              :                         }
     260              : 
     261            0 :                         for(SelEdgeIter iter = sel.template begin<Edge>();
     262            0 :                                 iter != sel.template end<Edge>(); ++iter)
     263              :                         {
     264              :                                 Edge* e = *iter;
     265            0 :                                 RefinementMark s = get_mark(e);
     266            0 :                                 for(size_t i = 0; i < 2; ++i){
     267            0 :                                         Vertex* vrt = e->vertex(i);
     268            0 :                                         if(!sel.is_selected(vrt) && this->refinement_is_allowed(vrt))
     269            0 :                                                 mark(vrt, s);
     270              :                                 }
     271              :                         }
     272              :                 }
     273              :                 else{
     274              :                 //      first we'll select all vertices which are connected to marked elements
     275            0 :                         for(SelEdgeIter iter = sel.template begin<Edge>();
     276            0 :                                 iter != sel.template end<Edge>(); ++iter)
     277              :                         {
     278              :                                 Edge* e = *iter;
     279            0 :                                 sel.select(e->vertex(0), sel.get_selection_status(e));
     280            0 :                                 sel.select(e->vertex(1), sel.get_selection_status(e));
     281              :                         }
     282              : 
     283            0 :                         for(SelFaceIter iter = sel.template begin<Face>();
     284            0 :                                 iter != sel.template end<Face>(); ++iter)
     285              :                         {
     286              :                                 Face* f = *iter;
     287              :                                 ISelector::status_t s = sel.get_selection_status(f);
     288            0 :                                 Face::ConstVertexArray faceVrts = f->vertices();
     289            0 :                                 for(size_t i = 0; i < f->num_vertices(); ++i)
     290            0 :                                         sel.select(faceVrts[i], s);
     291              :                         }
     292              : 
     293            0 :                         for(SelVolIter iter = sel.template begin<Volume>();
     294            0 :                                 iter != sel.template end<Volume>(); ++iter)
     295              :                         {
     296              :                                 Volume* vol = *iter;
     297              :                                 ISelector::status_t s = sel.get_selection_status(vol);
     298            0 :                                 Volume::ConstVertexArray volVrts = vol->vertices();
     299            0 :                                 for(size_t i = 0; i < vol->num_vertices(); ++i)
     300            0 :                                         sel.select(volVrts[i], s);
     301              :                         }
     302              :                 }
     303              : 
     304              :         //      if we're in a parallel environment, we have to broadcast the current selection
     305            0 :                 sel.broadcast_selection_states();
     306              : 
     307            0 :                 if(sideNbrsOnly){
     308              :                 //      mark those elements which have a marked side
     309            0 :                         if(hasVolumes){
     310              :                                 vector<Edge*> markedDummyEdges;
     311            0 :                                 lg_for_each(Volume, vol, g){
     312            0 :                                         if(this->refinement_is_allowed(vol)){
     313            0 :                                                 RefinementMark s = get_mark(vol);
     314            0 :                                                 if(s < refMark){
     315              :                                                         g.associated_elements(faces, vol);
     316              :                                                         RefinementMark rm = RM_NONE;
     317            0 :                                                         for_each_in_vec(Face* f, faces){
     318            0 :                                                                 RefinementMark sSide = get_mark(f);
     319            0 :                                                                 if(sSide){
     320              :                                                                         rm = refMark;
     321            0 :                                                                         if(rm == RM_NONE){
     322              :                                                                                 switch(sSide){
     323              :                                                                                         case RM_REFINE: rm = RM_REFINE; break;
     324              :                                                                                         case RM_CLOSURE: rm = RM_CLOSURE; break;
     325              :                                                                                         case RM_LOCAL: rm = RM_LOCAL; break;
     326              :                                                                                         case RM_COARSEN: rm = RM_COARSEN; break;
     327              :                                                                                         default: break;
     328              :                                                                                 }
     329              :                                                                         }
     330            0 :                                                                         mark(vol, rm);
     331              :                                                                         break;
     332              :                                                                 }
     333              :                                                         }end_for;
     334              : 
     335            0 :                                                         if(rm == RM_ANISOTROPIC){
     336              :                                                         //      we'll also copy edge-marks to guarantee an anisotropic refinement
     337              :                                                                 bool copying = true;
     338            0 :                                                                 while(copying){
     339              :                                                                         copying = false;
     340            0 :                                                                         for_each_in_vec(Face* f, faces){
     341              :                                                                                 g.associated_elements(edges, f);
     342            0 :                                                                                 for_each_in_vec(Edge* e, edges){
     343            0 :                                                                                         RefinementMark erm = get_mark(e);
     344            0 :                                                                                         if(erm == RM_REFINE){
     345            0 :                                                                                                 if(f->get_opposing_side(e, edesc)){
     346            0 :                                                                                                         Edge* oe = g.get_edge(edesc);
     347            0 :                                                                                                         if(oe && get_mark(oe) < erm){
     348              :                                                                                                                 copying = true;
     349            0 :                                                                                                                 mark(oe, RM_DUMMY);
     350            0 :                                                                                                                 markedDummyEdges.push_back(oe);
     351              :                                                                                                         }
     352              :                                                                                                 }
     353              :                                                                                         }       
     354              :                                                                                 }end_for;
     355              :                                                                         }end_for;
     356              :                                                                 }
     357              :                                                         }
     358              :                                                 }
     359              :                                         }
     360              :                                 }lg_end_for;
     361              : 
     362            0 :                                 for_each_in_vec(Edge* e, markedDummyEdges){
     363            0 :                                         mark(e, RM_REFINE);     
     364              :                                 }end_for;
     365            0 :                         }
     366            0 :                         else if(hasFaces){
     367            0 :                                 lg_for_each(Face, f, g){
     368            0 :                                         if(this->refinement_is_allowed(f)){
     369            0 :                                                 RefinementMark s = get_mark(f);
     370            0 :                                                 if(s < refMark){
     371              :                                                         g.associated_elements(edges, f);
     372              :                                                         RefinementMark rm = RM_NONE;
     373            0 :                                                         for_each_in_vec(Edge* e, edges){
     374            0 :                                                                 RefinementMark sSide = get_mark(e);
     375            0 :                                                                 if(sSide){
     376              :                                                                         rm = refMark;
     377            0 :                                                                         if(rm == RM_NONE){
     378              :                                                                                 switch(sSide){
     379              :                                                                                         case RM_REFINE: rm = RM_REFINE; break;
     380              :                                                                                         case RM_CLOSURE: rm = RM_CLOSURE; break;
     381              :                                                                                         case RM_LOCAL: rm = RM_LOCAL; break;
     382              :                                                                                         case RM_COARSEN: rm = RM_COARSEN; break;
     383              :                                                                                         default: break;
     384              :                                                                                 }
     385              :                                                                         }
     386            0 :                                                                         mark(f, rm);
     387              :                                                                         break;
     388              :                                                                 }
     389              :                                                         }end_for;
     390              : 
     391              :                                                 //      todo: if rm == RM_ANISOTROPIC: mark opposite edges (cf hasVolumes)
     392              :                                                 }
     393              :                                         }
     394              :                                 }lg_end_for;
     395              :                         }
     396            0 :                         else if(hasEdges){
     397            0 :                                 lg_for_each(Edge, e, g){
     398            0 :                                         if(this->refinement_is_allowed(e)){
     399            0 :                                                 RefinementMark s = get_mark(e);
     400            0 :                                                 if(s < refMark){
     401            0 :                                                         Edge::ConstVertexArray vrts = e->vertices();
     402            0 :                                                         for(size_t i = 0; i < 2; ++i){
     403            0 :                                                                 ISelector::status_t sSide = sel.get_selection_status(vrts[i]);
     404            0 :                                                                 if(sSide){
     405              :                                                                         RefinementMark rm = refMark;
     406            0 :                                                                         if(rm == RM_NONE){
     407              :                                                                                 switch(sSide){
     408              :                                                                                         case RM_REFINE: rm = RM_REFINE; break;
     409              :                                                                                         case RM_CLOSURE: rm = RM_CLOSURE; break;
     410              :                                                                                         case RM_LOCAL: rm = RM_LOCAL; break;
     411              :                                                                                         case RM_COARSEN: rm = RM_COARSEN; break;
     412              :                                                                                         default: break;
     413              :                                                                                 }
     414              :                                                                         }
     415            0 :                                                                         mark(e, rm);
     416              :                                                                 }
     417              :                                                         }
     418              :                                                 }
     419              :                                         }
     420              :                                 }lg_end_for;
     421              :                         }
     422              :                 }
     423              :                 else{
     424              :                 //      mark all associated elements of marked vertices
     425            0 :                         for(SelVrtIter iter = sel.template begin<Vertex>();
     426            0 :                                 iter != sel.template end<Vertex>(); ++iter)
     427              :                         {
     428              :                                 ISelector::status_t s = sel.get_selection_status(*iter);
     429              :                                 RefinementMark rm = refMark;
     430            0 :                                 if(rm == RM_NONE){
     431              :                                         switch(s){
     432              :                                                 case RM_REFINE: rm = RM_REFINE; break;
     433              :                                                 case RM_CLOSURE: rm = RM_CLOSURE; break;
     434              :                                                 case RM_LOCAL: rm = RM_LOCAL; break;
     435              :                                                 case RM_COARSEN: rm = RM_COARSEN; break;
     436              :                                                 default: break;
     437              :                                         }
     438              :                                 }
     439              : 
     440              :                                 g.associated_elements(edges, *iter);
     441            0 :                                 for(size_t i = 0; i < edges.size(); ++i)
     442            0 :                                         if(!this->is_marked(edges[i]))
     443            0 :                                                 this->mark(edges[i], rm);
     444              : 
     445              :                                 g.associated_elements(faces, *iter);
     446            0 :                                 for(size_t i = 0; i < faces.size(); ++i)
     447            0 :                                         if(!this->is_marked(faces[i]))
     448            0 :                                                 this->mark(faces[i], rm);
     449              : 
     450              :                                 g.associated_elements(vols, *iter);
     451            0 :                                 for(size_t i = 0; i < vols.size(); ++i)
     452            0 :                                         if(!this->is_marked(vols[i]))
     453            0 :                                                 this->mark(vols[i], rm);
     454              :                         }
     455              : 
     456              :                 //      since we selected vertices which possibly may not be refined, we have to
     457              :                 //      deselect those now.
     458            0 :                         for(SelVrtIter iter = sel.template begin<Vertex>();
     459            0 :                                 iter != sel.template end<Vertex>();)
     460              :                         {
     461              :                                 Vertex* vrt = *iter;
     462              :                                 ++iter;
     463              : 
     464            0 :                                 if(!refinement_is_allowed(vrt))
     465            0 :                                         sel.deselect(vrt);
     466              :                         }
     467              :                 }
     468              :                 
     469              :         }
     470              : }
     471              : 
     472              : template <class TSelector>
     473            0 : RefinementMark HangingNodeRefinerBase<TSelector>::
     474              : get_mark(Vertex* v) const
     475              : {
     476              :         return (RefinementMark)(m_selMarkedElements.get_selection_status(v)
     477            0 :                                                         & (RM_REFINE | RM_LOCAL | RM_CLOSURE | RM_COARSEN | RM_DUMMY));
     478              : }
     479              : 
     480              : template <class TSelector>
     481            0 : RefinementMark HangingNodeRefinerBase<TSelector>::
     482              : get_mark(Edge* e) const
     483              : {
     484              :         return (RefinementMark)(m_selMarkedElements.get_selection_status(e)
     485            0 :                                                         & (RM_REFINE | RM_LOCAL | RM_CLOSURE | RM_COARSEN | RM_DUMMY));
     486              : }
     487              : 
     488              : template <class TSelector>
     489            0 : RefinementMark HangingNodeRefinerBase<TSelector>::
     490              : get_mark(Face* f) const
     491              : {
     492              :         return (RefinementMark)(m_selMarkedElements.get_selection_status(f)
     493            0 :                                                         & (RM_REFINE | RM_LOCAL | RM_CLOSURE | RM_COARSEN | RM_DUMMY));
     494              : }
     495              : 
     496              : template <class TSelector>
     497            0 : RefinementMark HangingNodeRefinerBase<TSelector>::
     498              : get_mark(Volume* v) const
     499              : {
     500              :         return (RefinementMark)(m_selMarkedElements.get_selection_status(v)
     501            0 :                                                         & (RM_REFINE | RM_LOCAL | RM_CLOSURE | RM_COARSEN | RM_DUMMY));
     502              : }
     503              : 
     504              : 
     505              : template <class TSelector>
     506            0 : bool HangingNodeRefinerBase<TSelector>::
     507              : save_marks_to_file(const char* filename)
     508              : {
     509              :         UG_DLOG(LIB_GRID, 1, "  saving marks to file...\n");
     510            0 :         if(!m_pGrid){
     511            0 :                 UG_THROW("ERROR in HangingNodeRefinerBase::save_marks_to_file: No grid assigned!");
     512              :         }
     513              : 
     514              :         Grid& g = *m_pGrid;
     515            0 :         SubsetHandler sh(g);
     516              : 
     517            0 :         AssignGridToSubset(g, sh, 0);
     518              :         selector_t& sel = get_refmark_selector();
     519              : 
     520            0 :         for(VertexIterator iter = g.vertices_begin(); iter != g.vertices_end(); ++iter){
     521              :                 typename selector_t::status_t status = sel.get_selection_status(*iter);
     522            0 :                 sh.assign_subset(*iter, status);
     523              :         }
     524            0 :         for(EdgeIterator iter = g.edges_begin(); iter != g.edges_end(); ++iter){
     525              :                 typename selector_t::status_t status = sel.get_selection_status(*iter);
     526            0 :                 sh.assign_subset(*iter, status);
     527              :         }
     528            0 :         for(FaceIterator iter = g.faces_begin(); iter != g.faces_end(); ++iter){
     529              :                 typename selector_t::status_t status = sel.get_selection_status(*iter);
     530            0 :                 sh.assign_subset(*iter, status);
     531              :         }
     532            0 :         for(VolumeIterator iter = g.volumes_begin(); iter != g.volumes_end(); ++iter){
     533              :                 typename  selector_t::status_t status = sel.get_selection_status(*iter);
     534            0 :                 sh.assign_subset(*iter, status);
     535              :         }
     536              : 
     537            0 :         sh.subset_info(0).name = "_NONE_";
     538            0 :         for (byte si = 1; si > 0; ++si)
     539              :         {
     540            0 :                 sh.subset_info(si).name = "_";
     541            0 :                 for (byte b = 1; b != 0; b = b << 1)
     542            0 :                         if (si & b)
     543            0 :                                 switch (b)
     544              :                                 {
     545            0 :                                         case RM_CLOSURE: sh.subset_info(si).name.append("CLOSURE_"); break;
     546            0 :                                         case RM_LOCAL: sh.subset_info(si).name.append("LOCAL_"); break;
     547            0 :                                         case RM_FULL: sh.subset_info(si).name.append("FULL_"); break;
     548            0 :                                         case RM_COARSEN: sh.subset_info(si).name.append("COARSEN_"); break;
     549            0 :                                         case RM_DUMMY: sh.subset_info(si).name.append("DUMMY_"); break;
     550            0 :                                         case HNRM_TO_NORMAL: sh.subset_info(si).name.append("TONORMAL_"); break;
     551            0 :                                         case HNRM_TO_CONSTRAINED: sh.subset_info(si).name.append("TOCONSTRAINED_"); break;
     552            0 :                                         case HNRM_TO_CONSTRAINING: sh.subset_info(si).name.append("TOCONSTRAINING_"); break;
     553            0 :                                         default: UG_THROW("Invalid status.")
     554              :                                 }
     555              :         }
     556              : #if 0
     557              :         AssignGridToSubset(g, sh, 6);
     558              : 
     559              :         selector_t& sel = get_refmark_selector();
     560              : 
     561              :         for(VertexIterator iter = g.vertices_begin(); iter != g.vertices_end(); ++iter){
     562              :                 typename selector_t::status_t status = sel.get_selection_status(*iter);
     563              :                 switch(status){
     564              :                         case RM_NONE: break;
     565              :                         case RM_REFINE: sh.assign_subset(*iter, 0); break;
     566              :                         case RM_ANISOTROPIC: sh.assign_subset(*iter, 1); break;
     567              :                         case RM_COPY: sh.assign_subset(*iter, 2); break;
     568              :                         case RM_CLOSURE: sh.assign_subset(*iter, 3); break;
     569              :                         case RM_COARSEN: sh.assign_subset(*iter, 4); break;
     570              :                         default: sh.assign_subset(*iter, 5); break;
     571              :                 }
     572              :         }
     573              : 
     574              :         for(EdgeIterator iter = g.edges_begin(); iter != g.edges_end(); ++iter){
     575              :                 typename selector_t::status_t status = sel.get_selection_status(*iter);
     576              :                 switch(status){
     577              :                         case RM_NONE: break;
     578              :                         case RM_REFINE: sh.assign_subset(*iter, 0); break;
     579              :                         case RM_ANISOTROPIC: sh.assign_subset(*iter, 1); break;
     580              :                         case RM_COPY: sh.assign_subset(*iter, 2); break;
     581              :                         case RM_CLOSURE: sh.assign_subset(*iter, 3); break;
     582              :                         case RM_COARSEN: sh.assign_subset(*iter, 4); break;
     583              :                         default: sh.assign_subset(*iter, 5); break;
     584              :                 }
     585              :         }
     586              : 
     587              :         for(FaceIterator iter = g.faces_begin(); iter != g.faces_end(); ++iter){
     588              :                 typename selector_t::status_t status = sel.get_selection_status(*iter);
     589              :                 switch(status){
     590              :                         case RM_NONE: break;
     591              :                         case RM_REFINE: sh.assign_subset(*iter, 0); break;
     592              :                         case RM_ANISOTROPIC: sh.assign_subset(*iter, 1); break;
     593              :                         case RM_COPY: sh.assign_subset(*iter, 2); break;
     594              :                         case RM_CLOSURE: sh.assign_subset(*iter, 3); break;
     595              :                         case RM_COARSEN: sh.assign_subset(*iter, 4); break;
     596              :                         default: sh.assign_subset(*iter, 5); break;
     597              :                 }
     598              :         }
     599              : 
     600              :         for(VolumeIterator iter = g.volumes_begin(); iter != g.volumes_end(); ++iter){
     601              :                 typename  selector_t::status_t status = sel.get_selection_status(*iter);
     602              :                 switch(status){
     603              :                         case RM_NONE: break;
     604              :                         case RM_REFINE: sh.assign_subset(*iter, 0); break;
     605              :                         case RM_ANISOTROPIC: sh.assign_subset(*iter, 1); break;
     606              :                         case RM_COPY: sh.assign_subset(*iter, 2); break;
     607              :                         case RM_CLOSURE: sh.assign_subset(*iter, 3); break;
     608              :                         case RM_COARSEN: sh.assign_subset(*iter, 4); break;
     609              :                         default: sh.assign_subset(*iter, 5); break;
     610              :                 }
     611              :         }
     612              : 
     613              :         sh.subset_info(0).name = "refine regular";
     614              :         sh.subset_info(1).name = "refine anisotropic";
     615              :         sh.subset_info(2).name = "refine copy";
     616              :         sh.subset_info(3).name = "refine closure";
     617              :         sh.subset_info(4).name = "coarsen";
     618              :         sh.subset_info(5).name = "combi-mark";
     619              :         sh.subset_info(6).name = "no marks";
     620              : 
     621              : #endif
     622              : 
     623            0 :         AssignSubsetColors(sh);
     624            0 :         EraseEmptySubsets(sh);
     625              : 
     626            0 :         if(MultiGrid* pmg = dynamic_cast<MultiGrid*>(&g))
     627            0 :                 return SaveGridHierarchyTransformed(*pmg, sh, filename, 0.1);
     628              :         else
     629            0 :                 return SaveGridToFile(g, sh, filename);
     630            0 : }
     631              : 
     632              : template <class TSelector>
     633            0 : void HangingNodeRefinerBase<TSelector>::
     634              : enable_node_dependency_order_1(bool bEnable)
     635              : {
     636            0 :         m_nodeDependencyOrder1 = bEnable;
     637            0 :         for(size_t i = 0; i < m_refMarkAdjusters.size(); ++i){
     638              :                 m_refMarkAdjusters[i]->enable_node_dependency_order_1(bEnable);
     639              :         }
     640            0 : }
     641              : 
     642              : template <class TSelector>
     643            0 : void HangingNodeRefinerBase<TSelector>::perform_refinement()
     644              : {
     645              :         HNODE_PROFILE_BEGIN(perform_hnode_refinement);
     646              :         UG_DLOG(LIB_GRID, 1, "performing hanging-node-refine:\n");
     647              : 
     648            0 :         if(!m_pGrid)
     649            0 :                 throw(UGError("ERROR in HangingNodeRefinerBase::refine(...): No grid assigned."));
     650              : 
     651            0 :         if(m_selMarkedElements.grid() != m_pGrid)
     652            0 :                 throw(UGError("selector not initialized properly. Use HangingNodeRefinerBase::set_grid."));
     653              : 
     654              :         Grid& grid = *m_pGrid;
     655              : 
     656              : //      check grid options.
     657            0 :         if(!grid.option_is_enabled(GRIDOPT_AUTOGENERATE_SIDES))
     658              :         {
     659              :                 LOG("WARNING in HangingNodeRefiner::refine(): grid option GRIDOPT_AUTOGENERATE_SIDES auto-enabled." << endl);
     660            0 :                 grid.enable_options(GRIDOPT_AUTOGENERATE_SIDES);
     661              :         }
     662              : 
     663              : //      containers used for temporary results
     664              :         vector<Edge*>     vEdges;
     665              :         vector<Face*>             vFaces;
     666              :         vector<Volume*>           vVols;
     667              : 
     668              :         HNODE_PROFILE_BEGIN(href_AdjustingMarks);
     669              : //      fills the queues with the elements that have to be refined.
     670            0 :         collect_objects_for_refine();
     671              : 
     672              : //      assigns hnode marks
     673            0 :         assign_hnode_marks();
     674              :         HNODE_PROFILE_END();
     675              : 
     676              : //      {
     677              : //              UG_LOG("DEBUG SAVE...\n");
     678              : //              static int refselCount = 0;
     679              : //              stringstream ss;
     680              : //              ss << "refselbefore_" << refselCount << ".ugx";
     681              : //              save_marks_to_file(ss.str().c_str());
     682              : //              ++refselCount;
     683              : //      }
     684              : 
     685              : //      if a debug file was specified, we'll now save the marks to that file
     686            0 :         if(!m_adjustedMarksDebugFilename.empty())
     687            0 :                 save_marks_to_file(m_adjustedMarksDebugFilename.c_str());
     688              : 
     689            0 :         m_messageHub->post_message(GridMessage_Adaption(GMAT_HNODE_REFINEMENT_BEGINS,
     690              :                                                                                 m_selMarkedElements.get_grid_objects()));
     691            0 :         if(projector()->refinement_begins_requires_subgrid()){
     692            0 :                 SubGrid<IsSelected> sg(m_selMarkedElements.get_grid_objects(),
     693            0 :                                                                 IsSelected(m_selMarkedElements));
     694            0 :                 projector()->refinement_begins(&sg);
     695              :         }
     696              :         else
     697            0 :                 projector()->refinement_begins(NULL);
     698              : 
     699              : //      call pre_refine to allow derived classes to perform some actions
     700              :         HNODE_PROFILE_BEGIN(href_PreRefine);
     701            0 :         pre_refine();
     702              :         HNODE_PROFILE_END();
     703              : 
     704              : ////////////////////////////////
     705              : //      ConstrainedVertices
     706              :         UG_DLOG(LIB_GRID, 1, "  constrained vertices.\n");
     707              :         HNODE_PROFILE_BEGIN(href_ConstrainedVertices);
     708              :         for(typename selector_t::template traits<ConstrainedVertex>::iterator
     709            0 :                         iter = m_selMarkedElements.template begin<ConstrainedVertex>();
     710            0 :                 iter != m_selMarkedElements.template end<ConstrainedVertex>();)
     711              :         {
     712              :                 ConstrainedVertex* cdv = *iter;
     713              :                 ++iter;
     714            0 :                 process_constrained_vertex(cdv);
     715              :         }
     716              :         HNODE_PROFILE_END();
     717              : 
     718              : ////////////////////////////////
     719              : //      ConstrainedEdges
     720              :         UG_DLOG(LIB_GRID, 1, "  constrained edges.\n");
     721              :         HNODE_PROFILE_BEGIN(href_ConstrainedEdges);
     722            0 :         for(typename selector_t::template traits<ConstrainedEdge>::iterator iter =
     723              :                         m_selMarkedElements.template begin<ConstrainedEdge>();
     724            0 :                 iter != m_selMarkedElements.template end<ConstrainedEdge>();)
     725              :         {
     726              :                 ConstrainedEdge* cde = *iter;
     727              :                 ++iter;
     728            0 :                 if(marked_to_normal(cde))
     729            0 :                         remove_hmark(cde, RM_REFINE);
     730            0 :                 process_constrained_edge(cde);
     731              :         }
     732              :         HNODE_PROFILE_END();
     733              : 
     734              : ////////////////////////////////
     735              : //      ConstrainingEdges
     736              : //      iterate through scheduled cg-edges
     737              :         UG_DLOG(LIB_GRID, 1, "  constraining edges.\n");
     738              :         HNODE_PROFILE_BEGIN(href_ConstrainingEdges);
     739              :         {
     740            0 :                 typename selector_t::template traits<ConstrainingEdge>::iterator iter =
     741              :                         m_selMarkedElements.template begin<ConstrainingEdge>();
     742              : 
     743            0 :                 while(iter != m_selMarkedElements.template end<ConstrainingEdge>()){
     744              :                         ConstrainingEdge* cge = *iter;
     745              :                         ++iter;
     746            0 :                         if(marked_to_normal(cge))
     747            0 :                                 remove_hmark(cge, RM_REFINE);
     748              :                 //      if a constraining edge was previously created through replacement of
     749              :                 //      a constrained edge, we won't process it here
     750            0 :                         if(!marked_to_constraining(cge))
     751            0 :                                 process_constraining_edge(cge);
     752              :                 }
     753              :         }
     754              :         HNODE_PROFILE_END();
     755              : 
     756              : ////////////////////////////////
     757              : //      Normal Edges
     758              : //      iterate through scheduled edges
     759              :         UG_DLOG(LIB_GRID, 1, "  normal edges.\n");
     760              :         HNODE_PROFILE_BEGIN(href_NormalEdges);
     761              :         {
     762              :                 typename selector_t::template traits<RegularEdge>::iterator
     763            0 :                         iter = m_selMarkedElements.template begin<RegularEdge>();
     764            0 :                 while(iter != m_selMarkedElements.template end<RegularEdge>())
     765              :                 {
     766              :                         RegularEdge* e = *iter;
     767              :                         ++iter;
     768              : 
     769              :                 //      a normal edge may have previously been created by replacing a
     770              :                 //      constrained or constraining edge. Those edges won't be considered here
     771            0 :                         if(!refinement_is_allowed(e)){
     772            0 :                                 continue;
     773              :                         }
     774              : 
     775            0 :                         if(marked_to_constraining(e)){
     776            0 :                                 refine_edge_with_hanging_vertex(e);
     777              :                         }
     778            0 :                         else if(marked_refine(e)){
     779            0 :                                 refine_edge_with_normal_vertex(e);
     780              :                         }
     781              :                 }
     782              :         }
     783              :         HNODE_PROFILE_END();
     784              : 
     785              : ////////////////////////////////
     786              : //      Faces
     787              :         HNODE_PROFILE_BEGIN(href_ConstrainedFaces);
     788              :         UG_DLOG(LIB_GRID, 1, "  constrained triangles.\n");
     789              :         for(typename selector_t::template traits<ConstrainedTriangle>::iterator
     790            0 :                         iter = m_selMarkedElements.template begin<ConstrainedTriangle>();
     791            0 :                 iter != m_selMarkedElements.template end<ConstrainedTriangle>();)
     792              :         {
     793              :                 ConstrainedTriangle* cdf = *iter;
     794              :                 ++iter;
     795            0 :                 if(marked_to_normal(cdf))
     796            0 :                         remove_hmark(cdf, RM_REFINE);
     797            0 :                 process_constrained_face(cdf);
     798              :         }
     799              : 
     800              :         UG_DLOG(LIB_GRID, 1, "  constrained quadrilaterals.\n");
     801              :         for(typename selector_t::template traits<ConstrainedQuadrilateral>::iterator
     802            0 :                         iter = m_selMarkedElements.template begin<ConstrainedQuadrilateral>();
     803            0 :                 iter != m_selMarkedElements.template end<ConstrainedQuadrilateral>();)
     804              :         {
     805              :                 ConstrainedQuadrilateral* cdf = *iter;
     806              :                 ++iter;
     807            0 :                 if(marked_to_normal(cdf))
     808            0 :                         remove_hmark(cdf, RM_REFINE);
     809            0 :                 process_constrained_face(cdf);
     810              :         }
     811              :         HNODE_PROFILE_END();
     812              : 
     813              :         HNODE_PROFILE_BEGIN(href_ConstrainingFaces);
     814              :         UG_DLOG(LIB_GRID, 1, "  constraining triangles.\n");
     815              : //      constraining triangles
     816              :         {
     817              :                 typename selector_t::template traits<ConstrainingTriangle>::iterator
     818            0 :                         iter = m_selMarkedElements.template begin<ConstrainingTriangle>();
     819            0 :                 while(iter != m_selMarkedElements.template end<ConstrainingTriangle>()){
     820              :                         ConstrainingTriangle* cgf = *iter;
     821              :                         ++iter;
     822            0 :                         if(marked_to_normal(cgf))
     823            0 :                                 remove_hmark(cgf, RM_REFINE);
     824              :                 //      if a constraining face was previously created through replacement of
     825              :                 //      a constrained face, we won't process it here
     826            0 :                         if(!marked_to_constraining(cgf))
     827            0 :                                 process_constraining_face(cgf);
     828              :                 }
     829              :         }
     830              : 
     831              :         UG_DLOG(LIB_GRID, 1, "  constraining quadrilaterals.\n");
     832              : //      constraining quadrilaterals
     833              :         {
     834              :                 typename selector_t::template traits<ConstrainingQuadrilateral>::iterator
     835            0 :                         iter = m_selMarkedElements.template begin<ConstrainingQuadrilateral>();
     836            0 :                 while(iter != m_selMarkedElements.template end<ConstrainingQuadrilateral>()){
     837              :                         ConstrainingQuadrilateral* cgf = *iter;
     838              :                         ++iter;
     839            0 :                         if(marked_to_normal(cgf))
     840            0 :                                 remove_hmark(cgf, RM_REFINE);
     841              :                 //      if a constraining face was previously created through replacement of
     842              :                 //      a constrained face, we won't process it here
     843            0 :                         if(!marked_to_constraining(cgf))
     844            0 :                                 process_constraining_face(cgf);
     845              :                 }
     846              :         }
     847              :         HNODE_PROFILE_END();
     848              : 
     849              :         HNODE_PROFILE_BEGIN(href_NormalFaces);
     850              :         UG_DLOG(LIB_GRID, 1, "  normal triangles.\n");
     851              : //      normal triangles
     852              :         {
     853              :                 typename selector_t::template traits<Triangle>::iterator
     854            0 :                         iter = m_selMarkedElements.template begin<Triangle>();
     855            0 :                 while(iter != m_selMarkedElements.template end<Triangle>()){
     856              :                         Face* f = *iter;
     857              :                         ++iter;
     858              : 
     859              :                 //      a normal face may have previously been created by replacing a
     860              :                 //      constrained or constraining face. Those faces won't be considered here
     861            0 :                         if((!refinement_is_allowed(f)) || marked_to_normal(f)){
     862            0 :                                 continue;
     863              :                         }
     864              : 
     865            0 :                         if(marked_to_constraining(f))
     866            0 :                                 refine_face_with_hanging_vertex(f);
     867            0 :                         else if(marked_refine(f))
     868            0 :                                 refine_face_with_normal_vertex(f);
     869              :                 }
     870              :         }
     871              : 
     872              :         UG_DLOG(LIB_GRID, 1, "  normal quadrilaterals.\n");
     873              : //      normal quadrilaterals
     874              :         {
     875              :                 typename selector_t::template traits<Quadrilateral>::iterator
     876            0 :                         iter = m_selMarkedElements.template begin<Quadrilateral>();
     877            0 :                 while(iter != m_selMarkedElements.template end<Quadrilateral>()){
     878              :                         Face* f = *iter;
     879              :                         ++iter;
     880              : 
     881              :                 //      a normal face may have previously been created by replacing a
     882              :                 //      constrained or constraining face. Those faces won't be considered here
     883            0 :                         if((!refinement_is_allowed(f)) || marked_to_normal(f)){
     884            0 :                                 continue;
     885              :                         }
     886              : 
     887            0 :                         if(marked_to_constraining(f))
     888            0 :                                 refine_face_with_hanging_vertex(f);
     889            0 :                         else if(marked_refine(f))
     890            0 :                                 refine_face_with_normal_vertex(f);
     891              :                 }
     892              :         }
     893              :         HNODE_PROFILE_END();
     894              : 
     895              : ////////////////////////////////
     896              : //      Volumes
     897              :         UG_DLOG(LIB_GRID, 1, "  volumes.\n");
     898              :         HNODE_PROFILE_BEGIN(href_Volumes);
     899              :         {
     900              :                 typename selector_t::template traits<Volume>::iterator
     901            0 :                         iter = m_selMarkedElements.template begin<Volume>();
     902            0 :                 while(iter != m_selMarkedElements.template end<Volume>()){
     903              :                         Volume* vol = *iter;
     904              :                         ++iter;
     905            0 :                         if(refinement_is_allowed(vol)){
     906            0 :                                 refine_volume_with_normal_vertex(vol);
     907              :                         }
     908              :                 }
     909              :         }
     910              :         HNODE_PROFILE_END();
     911              : 
     912              :         UG_DLOG(LIB_GRID, 1, "  refinement done.\n");
     913              : 
     914              : ////////////////////////////////
     915              : //      call post_refine to allow derived classes to perform some actions
     916              :         HNODE_PROFILE_BEGIN(href_PostRefine);
     917            0 :         post_refine();
     918              :         HNODE_PROFILE_END();
     919              : 
     920              : 
     921              : 
     922              : ////////////////////////////////
     923              : //      before calling the refinement callback, we make sure that only elements are
     924              : //      marked, which actually received new children
     925              :         for(typename selector_t::template traits<Vertex>::iterator
     926            0 :                         iter = m_selMarkedElements.template begin<Vertex>();
     927            0 :                         iter != m_selMarkedElements.template end<Vertex>();)
     928              :         {
     929              :                 Vertex* e = *iter;
     930              :                 ++iter;
     931            0 :                 if(!(marked_refine(e)))
     932            0 :                         m_selMarkedElements.deselect(e);
     933              :         }
     934              :         for(typename selector_t::template traits<Edge>::iterator
     935            0 :                         iter = m_selMarkedElements.template begin<Edge>();
     936            0 :                         iter != m_selMarkedElements.template end<Edge>();)
     937              :         {
     938              :                 Edge* e = *iter;
     939              :                 ++iter;
     940            0 :                 if(!(marked_refine(e)))
     941            0 :                         m_selMarkedElements.deselect(e);
     942              :         }
     943              :         for(typename selector_t::template traits<Face>::iterator
     944            0 :                         iter = m_selMarkedElements.template begin<Face>();
     945            0 :                         iter != m_selMarkedElements.template end<Face>();)
     946              :         {
     947              :                 Face* e = *iter;
     948              :                 ++iter;
     949            0 :                 if(!(marked_refine(e)))
     950            0 :                         m_selMarkedElements.deselect(e);
     951              :         }
     952              : 
     953              :         // {
     954              :         //      UG_LOG("DEBUG SAVE...\n");
     955              :         //      static int refselCount = 0;
     956              :         //      stringstream ss;
     957              :         //      ss << "refselafter_" << refselCount << ".ugx";
     958              :         //      save_marks_to_file(ss.str().c_str());
     959              :         //      ++refselCount;
     960              :         // }
     961              : 
     962            0 :         projector()->refinement_ends();
     963              :         
     964              : //      notify the grid's message hub that refinement ends
     965              :         HNODE_PROFILE_BEGIN(href_AdaptionEndsMessage);
     966            0 :         m_messageHub->post_message(GridMessage_Adaption(GMAT_HNODE_REFINEMENT_ENDS,
     967              :                                                                                 m_selMarkedElements.get_grid_objects()));
     968              :         HNODE_PROFILE_END();
     969              : 
     970              : ////////////////////////////////
     971              : //      Clean up
     972              : //      clear the refinement-callback if necessary
     973              :         HNODE_PROFILE_BEGIN(href_CleanUp);
     974            0 :         clear_marks();
     975              :         HNODE_PROFILE_END();
     976              : 
     977              : //      debugging utilities for the periodic boundary manager
     978              :         // if(m_pGrid->periodic_boundary_manager()){
     979              :         //      m_pGrid->periodic_boundary_manager()->print_identification<Vertex>();
     980              :         //      m_pGrid->periodic_boundary_manager()->print_identification<Edge>();
     981              :         //      m_pGrid->periodic_boundary_manager()->print_identification<Face>();
     982              : 
     983              :         //      UG_LOG("DEBUGGING: Checking validity of PeriodicBoundaryManager:\n");
     984              :         //      if(m_pGrid->periodic_boundary_manager())
     985              :         //              m_pGrid->periodic_boundary_manager()->validity_check();
     986              :         // }
     987              : 
     988              :         UG_DLOG(LIB_GRID, 1, "  done.\n");
     989            0 : }
     990              : 
     991              : template <class TSelector>
     992              : template <class TElem>
     993            0 : bool HangingNodeRefinerBase<TSelector>::remove_coarsen_marks()
     994              : {
     995              :         typedef typename selector_t::template traits<TElem>::iterator     ElemIter;
     996              :         bool removedCoarsenMark = false;
     997            0 :         for(ElemIter iter = m_selMarkedElements.template begin<TElem>();
     998            0 :                 iter != m_selMarkedElements.template end<TElem>();)
     999              :         {
    1000              :                 TElem* e = *iter;
    1001              :                 ++iter;
    1002            0 :                 if(get_mark(e) == RM_COARSEN){
    1003            0 :                         m_selMarkedElements.deselect(e);
    1004              :                         removedCoarsenMark = true;
    1005              :                 }
    1006              :         }
    1007              : 
    1008            0 :         return removedCoarsenMark;
    1009              : }
    1010              : 
    1011              : template <class TSelector>
    1012            0 : void HangingNodeRefinerBase<TSelector>::collect_objects_for_refine()
    1013              : {
    1014              :         HNODE_PROFILE_FUNC();
    1015              :         UG_DLOG(LIB_GRID, 1, "hnode_ref-start: collect_objects_for_refine\n");
    1016              : 
    1017            0 :         m_adjustingRefMarks = true;
    1018              : 
    1019              : //      build correct selection. see HangingVertexRefiner description.
    1020              : //      unmark all elements which are marked for coarsening
    1021              : 
    1022            0 :         bool removedCoarseMarks = remove_coarsen_marks<Vertex>();
    1023            0 :         removedCoarseMarks |= remove_coarsen_marks<Edge>();
    1024            0 :         removedCoarseMarks |= remove_coarsen_marks<Face>();
    1025            0 :         removedCoarseMarks |= remove_coarsen_marks<Volume>();
    1026              : 
    1027            0 :         if(removedCoarseMarks){
    1028              :                 UG_LOG("WARNING in HangingNodeRefinerBase::collect_objects_for_refine: "
    1029              :                                 "Removed coarsen marks.\n");
    1030              :         }
    1031              : 
    1032              :         std::vector<Vertex*>      newlyMarkedVrts;
    1033              :         std::vector<Edge*>                newlyMarkedEdges;
    1034              :         std::vector<Face*>                        newlyMarkedFaces;
    1035              :         std::vector<Volume*>              newlyMarkedVols;
    1036              : 
    1037            0 :         newlyMarkedVrts.assign(m_selMarkedElements.template begin<Vertex>(),
    1038              :                                                    m_selMarkedElements.template end<Vertex>());
    1039            0 :         newlyMarkedEdges.assign(m_selMarkedElements.template begin<Edge>(),
    1040              :                                                         m_selMarkedElements.template end<Edge>());
    1041            0 :         newlyMarkedFaces.assign(m_selMarkedElements.template begin<Face>(),
    1042              :                                                         m_selMarkedElements.template end<Face>());
    1043            0 :         newlyMarkedVols.assign(m_selMarkedElements.template begin<Volume>(),
    1044              :                                                    m_selMarkedElements.template end<Volume>());
    1045              : 
    1046              :         bool continueAdjustment = true;
    1047              :         bool firstAdjustment = true;
    1048              : 
    1049            0 :         while(continueAdjustment){
    1050            0 :                 if(!firstAdjustment){
    1051              :                 //      we don't simply pass m_newlyMarkedXXX to the adjusters, since we want to
    1052              :                 //      record newly marked elements during adjustment. Those newly marked elems
    1053              :                 //      are then used for the next calls, etc.
    1054              :                 //      This is only necessary if we're not in the first adjustment iteration.
    1055              :                         newlyMarkedVrts.swap(m_newlyMarkedRefVrts);
    1056              :                         newlyMarkedEdges.swap(m_newlyMarkedRefEdges);
    1057              :                         newlyMarkedFaces.swap(m_newlyMarkedRefFaces);
    1058              :                         newlyMarkedVols.swap(m_newlyMarkedRefVols);
    1059              :                 }
    1060              : 
    1061              :                 firstAdjustment = false;
    1062              : 
    1063              :                 m_newlyMarkedRefVrts.clear();
    1064              :                 m_newlyMarkedRefEdges.clear();
    1065              :                 m_newlyMarkedRefFaces.clear();
    1066              :                 m_newlyMarkedRefVols.clear();
    1067              : 
    1068              :         //      call the adjusters
    1069            0 :                 for(size_t i = 0; i < m_refMarkAdjusters.size(); ++i){
    1070            0 :                         if(m_refMarkAdjusters[i]->enabled()){
    1071            0 :                                 m_refMarkAdjusters[i]->ref_marks_changed(*this, newlyMarkedVrts,
    1072              :                                                                                                                         newlyMarkedEdges,
    1073              :                                                                                                                         newlyMarkedFaces,
    1074              :                                                                                                                         newlyMarkedVols);
    1075              :                         }
    1076              :                 }
    1077              : 
    1078              :                 bool continueRequired = (!m_newlyMarkedRefVrts.empty())
    1079            0 :                                                          || (!m_newlyMarkedRefEdges.empty())
    1080            0 :                                                          || (!m_newlyMarkedRefFaces.empty())
    1081            0 :                                                          || (!m_newlyMarkedRefVols.empty());
    1082              : 
    1083            0 :                 continueAdjustment = continue_collect_objects_for_refine(continueRequired);
    1084              :         }
    1085              : 
    1086            0 :         m_adjustingRefMarks = false;
    1087              :         UG_DLOG(LIB_GRID, 1, "hnode_ref-stop: collect_objects_for_refine\n");
    1088            0 : }
    1089              : 
    1090              : template <class TSelector>
    1091            0 : void HangingNodeRefinerBase<TSelector>::
    1092              : assign_hnode_marks()
    1093              : {
    1094              :         UG_DLOG(LIB_GRID, 1, "  assigning hnode marks...\n");
    1095              : //      iterate over all faces and volumes. If the element is not marked, but
    1096              : //      a side is marked, the side has to be marked for hnode refinement.
    1097              : //      Note that we won't mark any new elements for refinement here - we only adjust the marks
    1098              : //      or add conversion marks (HNRM_TO_NORMAL etc).
    1099              : //      Note also that we won't remove any marks during this algorithm (neither normal
    1100              : //      nor hnode marks).
    1101              :         Grid::edge_traits::secure_container edges;
    1102              :         vector<Face*> faces;
    1103              :         vector<Volume*> vols;
    1104              : 
    1105              :         std::vector<int>  vinds;
    1106            0 :         vinds.reserve(4);
    1107              : 
    1108              : //      the grid
    1109              :         UG_ASSERT(m_pGrid, "A grid is required to perform this operation!");
    1110            0 :         Grid& grid = *m_pGrid;
    1111              : 
    1112            0 :         if(grid.num<Volume>() > 0){
    1113            0 :                 for(sel_face_iter iter = m_selMarkedElements.template begin<Face>();
    1114            0 :                         iter != m_selMarkedElements.template end<Face>(); ++iter)
    1115              :                 {
    1116              :                         Face* f = *iter;
    1117              :                         CollectAssociated(vols, grid, f);
    1118              :                 //      if one of the volumes is marked with RM_LOCAL, we'll have to
    1119              :                 //      set up a local mark for the face and compare it.
    1120              :                         bool gotLocal = false;
    1121            0 :                         for(size_t i = 0; i < vols.size(); ++i){
    1122            0 :                                 if(marked_local(vols[i])){
    1123              :                                         gotLocal = true;
    1124              :                                         break;
    1125              :                                 }
    1126              :                         }
    1127              : 
    1128            0 :                         if(gotLocal){
    1129              :                                 int localFaceMark = 0;
    1130            0 :                                 if(marked_full(f)){
    1131            0 :                                         if(f->num_vertices() == 3)
    1132              :                                                 localFaceMark = 7;
    1133            0 :                                         else if(f->num_vertices() == 4)
    1134              :                                                 localFaceMark = 15;
    1135              :                                         else{
    1136            0 :                                                 UG_THROW("Unsupported face type with too many vertices: " << f->num_vertices());
    1137              :                                         }
    1138              :                                 }
    1139            0 :                                 else if(marked_local(f))
    1140            0 :                                         localFaceMark = get_local_mark(f);
    1141            0 :                                 else if(marked_closure(f)){
    1142              :                                         grid.associated_elements_sorted(edges, f);
    1143            0 :                                         for(size_t i = 0; i < edges.size(); ++i){
    1144            0 :                                                 if(marked_full(edges[i]))
    1145            0 :                                                         localFaceMark |= (1<<i);
    1146              :                                         }
    1147              :                                 }
    1148              : 
    1149            0 :                                 for(size_t i_vol = 0; i_vol < vols.size(); ++i_vol){
    1150            0 :                                         Volume* v = vols[i_vol];
    1151            0 :                                         if(!refinement_is_allowed(v))
    1152            0 :                                                 continue;
    1153              : 
    1154            0 :                                         if(!m_selMarkedElements.is_selected(v))
    1155              :                                         {
    1156            0 :                                                 add_hmark(f, HNRM_TO_CONSTRAINING);
    1157              :                                                 break;
    1158              :                                         }
    1159              :                                         else{
    1160            0 :                                                 if(!marked_local(v))
    1161            0 :                                                         continue;
    1162              : 
    1163            0 :                                                 int volLocalMark = get_local_mark(v);
    1164              :                                                 int sideMark = 0;
    1165              : 
    1166            0 :                                                 Face::ConstVertexArray vrts = f->vertices();
    1167            0 :                                                 const size_t numVrts = f->num_vertices();
    1168              : 
    1169            0 :                                                 vinds.resize(numVrts);
    1170            0 :                                                 for(size_t j = 0; j < numVrts; ++j){
    1171            0 :                                                         vinds[j] = GetVertexIndex(v, vrts[j]);
    1172              :                                                 }
    1173              : 
    1174              : 
    1175            0 :                                                 for(size_t j = 0; j < numVrts; ++j){
    1176              :                                                         const int edgeInd =
    1177            0 :                                                                         v->get_edge_index_from_vertices(
    1178            0 :                                                                                         vinds[j], vinds[(j+1)%numVrts]);
    1179              :                                                         
    1180            0 :                                                         sideMark |= ((volLocalMark >> edgeInd) & 1) << j;
    1181              :                                                 }
    1182              : 
    1183              : 
    1184            0 :                                                 if(sideMark != localFaceMark){
    1185            0 :                                                         add_hmark(f, HNRM_TO_CONSTRAINING);
    1186              :                                                         break;
    1187              :                                                 }
    1188              :                                         }
    1189              :                                 }
    1190              :                         }
    1191              :                         else{
    1192            0 :                                 for(size_t i = 0; i < vols.size(); ++i){
    1193            0 :                                         if(refinement_is_allowed(vols[i])
    1194            0 :                                            && (!m_selMarkedElements.is_selected(vols[i])))
    1195              :                                         {
    1196            0 :                                                 add_hmark(f, HNRM_TO_CONSTRAINING);
    1197              :                                                 break;
    1198              :                                         }
    1199              :                                 }
    1200              :                         }
    1201              : 
    1202              :                 }
    1203              : 
    1204              :         //      make sure, that constrained faces, edges and vertices of selected
    1205              :         //      constraining faces will be converted to normal edges, if they are not
    1206              :         //      yet marked and to constraining edges, if they are marked.
    1207              :                 for(typename selector_t::template traits<ConstrainingTriangle>::iterator
    1208            0 :                                 iter = m_selMarkedElements.template begin<ConstrainingTriangle>();
    1209            0 :                         iter != m_selMarkedElements.template end<ConstrainingTriangle>(); ++iter)
    1210              :                 {
    1211              :                         ConstrainingTriangle* cgf = *iter;
    1212            0 :                         if(marked_refine(cgf)){
    1213            0 :                                 add_hmark(cgf, HNRM_TO_NORMAL);
    1214            0 :                                 for(size_t i = 0; i < cgf->num_constrained_vertices(); ++i)
    1215            0 :                                         add_hmark(cgf->constrained_vertex(i), HNRM_TO_NORMAL);
    1216            0 :                                 for(size_t i = 0; i < cgf->num_constrained_edges(); ++i){
    1217              :                                         Edge* cde = cgf->constrained_edge(i);
    1218            0 :                                         if(marked_refine(cde))
    1219            0 :                                                 add_hmark(cde, HNRM_TO_CONSTRAINING);
    1220              :                                         else
    1221            0 :                                                 add_hmark(cde, HNRM_TO_NORMAL);
    1222              :                                 }
    1223            0 :                                 for(size_t i = 0; i < cgf->num_constrained_faces(); ++i){
    1224              :                                         Face* cdf = cgf->constrained_face(i);
    1225            0 :                                         if(marked_refine(cdf))
    1226            0 :                                                 add_hmark(cdf, HNRM_TO_CONSTRAINING);
    1227              :                                         else
    1228            0 :                                                 add_hmark(cdf, HNRM_TO_NORMAL);
    1229              :                                 }
    1230              :                         }
    1231              :                 }
    1232              : 
    1233              :                 for(typename selector_t::template traits<ConstrainingQuadrilateral>::iterator
    1234            0 :                                 iter = m_selMarkedElements.template begin<ConstrainingQuadrilateral>();
    1235            0 :                         iter != m_selMarkedElements.template end<ConstrainingQuadrilateral>(); ++iter)
    1236              :                 {
    1237              :                         ConstrainingQuadrilateral* cgf = *iter;
    1238            0 :                         if(marked_refine(cgf)){
    1239            0 :                                 add_hmark(cgf, HNRM_TO_NORMAL);
    1240            0 :                                 for(size_t i = 0; i < cgf->num_constrained_vertices(); ++i)
    1241            0 :                                         add_hmark(cgf->constrained_vertex(i), HNRM_TO_NORMAL);
    1242            0 :                                 for(size_t i = 0; i < cgf->num_constrained_edges(); ++i){
    1243              :                                         Edge* cde = cgf->constrained_edge(i);
    1244            0 :                                         if(marked_refine(cde))
    1245            0 :                                                 add_hmark(cde, HNRM_TO_CONSTRAINING);
    1246              :                                         else
    1247            0 :                                                 add_hmark(cde, HNRM_TO_NORMAL);
    1248              :                                 }
    1249            0 :                                 for(size_t i = 0; i < cgf->num_constrained_faces(); ++i){
    1250              :                                         Face* cdf = cgf->constrained_face(i);
    1251            0 :                                         if(marked_refine(cdf))
    1252            0 :                                                 add_hmark(cdf, HNRM_TO_CONSTRAINING);
    1253              :                                         else
    1254            0 :                                                 add_hmark(cdf, HNRM_TO_NORMAL);
    1255              :                                 }
    1256              :                         }
    1257              :                 }
    1258              :         }
    1259              :         
    1260            0 :         if(grid.num<Face>() > 0){
    1261            0 :                 for(sel_edge_iter iter = m_selMarkedElements.template begin<Edge>();
    1262            0 :                         iter != m_selMarkedElements.template end<Edge>(); ++iter)
    1263              :                 {
    1264              :                         Edge* e = *iter;
    1265            0 :                         if(!marked_refine(e))
    1266            0 :                                 continue;
    1267              : 
    1268              :                         CollectAssociated(faces, grid, e);
    1269            0 :                         for(size_t i = 0; i < faces.size(); ++i){
    1270            0 :                                 Face* f = faces[i];
    1271            0 :                                 if(marked_to_constraining(f))
    1272              :                                 {
    1273            0 :                                         add_hmark(e, HNRM_TO_CONSTRAINING);
    1274              :                                         break;
    1275              :                                 }
    1276              : 
    1277            0 :                                 if(!refinement_is_allowed(f))
    1278            0 :                                         continue;
    1279              : 
    1280            0 :                                 if(!m_selMarkedElements.is_selected(f))
    1281              :                                 {
    1282            0 :                                         add_hmark(e, HNRM_TO_CONSTRAINING);
    1283              :                                         break;
    1284              :                                 }
    1285            0 :                                 else if(marked_local(f)){
    1286            0 :                                         int localMark = get_local_mark(f);
    1287            0 :                                         int ei = GetEdgeIndex(f, e);
    1288            0 :                                         if(!(localMark & 1<<ei)){
    1289            0 :                                                 add_hmark(e, HNRM_TO_CONSTRAINING);
    1290              :                                                 break;
    1291              :                                         }
    1292              :                                 }
    1293              :                         }
    1294              :                 }
    1295              : 
    1296              :                 for(typename selector_t::template traits<ConstrainingEdge>::iterator
    1297            0 :                                 iter = m_selMarkedElements.template begin<ConstrainingEdge>();
    1298            0 :                         iter != m_selMarkedElements.template end<ConstrainingEdge>(); ++iter)
    1299              :                 {
    1300              :                         ConstrainingEdge* cge = *iter;
    1301            0 :                         if(marked_refine(cge)){
    1302            0 :                                 add_hmark(cge, HNRM_TO_NORMAL);
    1303            0 :                                 if(!marked_to_constraining(cge)){
    1304              :                                 //      this happens in volume geometries, where only some of the
    1305              :                                 //      associated volumes are refined
    1306            0 :                                         for(size_t i = 0; i < cge->num_constrained_vertices(); ++i)
    1307            0 :                                                 add_hmark(cge->constrained_vertex(i), HNRM_TO_NORMAL);
    1308              : 
    1309            0 :                                         for(size_t i = 0; i < cge->num_constrained_edges(); ++i){
    1310              :                                                 Edge* cde = cge->constrained_edge(i);
    1311            0 :                                                 if(marked_refine(cde))
    1312            0 :                                                         add_hmark(cde, HNRM_TO_CONSTRAINING);
    1313              :                                                 else
    1314            0 :                                                         add_hmark(cde, HNRM_TO_NORMAL);
    1315              :                                         }
    1316              :                                 }
    1317              :                         }
    1318              :                 }
    1319              : 
    1320              :                 // FIXME: Also take care of (unmarkable) SHADOW_COPY edges
    1321              :                 // whose children are marked for refinement:
    1322              :                 // These children need to be marked HNRM_TO_CONSTRAINING!
    1323              :                 // How can these be identified!?
    1324              :                 // This is now only implemented in HaningNodeRefiner_MultiGrid::assign_hnode_marks
    1325              : 
    1326              :         }
    1327            0 : }
    1328              : 
    1329              : template <class TSelector>
    1330              : template <class TElem>
    1331            0 : void HangingNodeRefinerBase<TSelector>::
    1332              : add_hmark(TElem* elem, HNodeRefMarks mark)
    1333              : {
    1334              : //      we have to consider periodic boundaries
    1335            0 :         PeriodicBoundaryManager* pbm = m_pGrid->periodic_boundary_manager();
    1336              :         typedef typename TElem::grid_base_object        base_elem_t;
    1337              :         base_elem_t* e = elem;
    1338            0 :         if(pbm && pbm->is_periodic(e)){
    1339            0 :                 base_elem_t* master = pbm->master(e);
    1340            0 :                 m_selMarkedElements.select(master,
    1341            0 :                                         m_selMarkedElements.get_selection_status(master) | mark);
    1342              : 
    1343              :                 typedef typename PeriodicBoundaryManager::Group<base_elem_t>::SlaveContainer
    1344              :                                                  slave_container_t;
    1345            0 :                 slave_container_t* slaves = pbm->slaves(master);
    1346            0 :                 for(typename slave_container_t::iterator i = slaves->begin();
    1347            0 :                         i != slaves->end(); ++i)
    1348              :                 {
    1349            0 :                         m_selMarkedElements.select(*i,
    1350            0 :                                         m_selMarkedElements.get_selection_status(*i) | mark);
    1351              :                 }
    1352              :         }
    1353              :         else{
    1354            0 :                 m_selMarkedElements.select(elem,
    1355            0 :                                         m_selMarkedElements.get_selection_status(elem) | mark);
    1356              :         }
    1357            0 : }
    1358              : 
    1359              : template <class TSelector>
    1360              : template <class TElem>
    1361            0 : void HangingNodeRefinerBase<TSelector>::
    1362              : remove_hmark(TElem* elem, uint mark)
    1363              : {
    1364              :         //      we have to consider periodic boundaries
    1365            0 :         PeriodicBoundaryManager* pbm = m_pGrid->periodic_boundary_manager();
    1366              :         typedef typename TElem::grid_base_object        base_elem_t;
    1367              :         base_elem_t* e = elem;
    1368            0 :         if(pbm && pbm->is_periodic(e)){
    1369            0 :                 base_elem_t* master = pbm->master(e);
    1370            0 :                 m_selMarkedElements.select(master,
    1371            0 :                                         m_selMarkedElements.get_selection_status(master) & (~mark));
    1372              : 
    1373              :                 typedef typename PeriodicBoundaryManager::Group<base_elem_t>::SlaveContainer
    1374              :                                                  slave_container_t;
    1375            0 :                 slave_container_t* slaves = pbm->slaves(master);
    1376            0 :                 for(typename slave_container_t::iterator i = slaves->begin();
    1377            0 :                         i != slaves->end(); ++i)
    1378              :                 {
    1379            0 :                         m_selMarkedElements.select(*i,
    1380            0 :                                         m_selMarkedElements.get_selection_status(*i) & (~mark));
    1381              :                 }
    1382              :         }
    1383              :         else{
    1384            0 :                 m_selMarkedElements.select(elem,
    1385            0 :                                         m_selMarkedElements.get_selection_status(elem) & (~mark));
    1386              :         }
    1387            0 : }
    1388              : 
    1389              : ////////////////////////////////////////////////////////////////////////
    1390              : //      implementation of refine-methods.
    1391              : template <class TSelector>
    1392            0 : void HangingNodeRefinerBase<TSelector>::
    1393              : process_constrained_vertex(ConstrainedVertex* cdv)
    1394              : {
    1395              : 
    1396            0 :         if(marked_to_normal(cdv)){
    1397              :                 Edge* parentEdge = NULL;
    1398              :                 Face* parentFace = NULL;
    1399              :                 GridObject* constrObj = cdv->get_constraining_object();
    1400              : 
    1401            0 :                 if(constrObj){
    1402            0 :                         switch(cdv->get_parent_base_object_id()){
    1403              :                                 case EDGE:{
    1404            0 :                                                 ConstrainingEdge* cge = dynamic_cast<ConstrainingEdge*>(constrObj);
    1405              :                                                 UG_ASSERT(cge, "Constraining edge has invalid type!");
    1406              :                                                 UG_ASSERT(marked_to_normal(cge),
    1407              :                                                                   "Constraining edge has to be converted to a normal edge!");
    1408              :                                                 cge->clear_constrained_vertices();
    1409              :                                                 parentEdge = cge;
    1410              :                                                 UG_ASSERT(get_center_vertex(cge) == cdv,
    1411              :                                                                   "Center vertex and constrained vertex do not match!");
    1412              :                                         }break;
    1413              :                                 case FACE:{
    1414            0 :                                                 ConstrainingFace* cgf = dynamic_cast<ConstrainingFace*>(constrObj);
    1415              :                                                 UG_ASSERT(cgf, "Constraining face has invalid type!");
    1416              :                                                 UG_ASSERT(marked_to_normal(cgf),
    1417              :                                                                   "Constraining edge has to be converted to a normal edge!");
    1418              :                                                 cgf->clear_constrained_vertices();
    1419              :                                                 parentFace = cgf;
    1420              :                                                 UG_ASSERT((get_center_vertex(cgf) == NULL) || (get_center_vertex(cgf) == cdv),
    1421              :                                                                   "Center vertex and constrained vertex do not match!");
    1422              :                                         }break;
    1423              :                                 default:
    1424              :                                         break;
    1425              :                         }
    1426              :                 }
    1427              : 
    1428            0 :                 Grid& grid = *m_pGrid;
    1429            0 :                 Vertex* nVrt = *grid.create_and_replace<RegularVertex>(cdv);
    1430            0 :                 if(parentEdge)
    1431            0 :                         set_center_vertex(parentEdge, nVrt);
    1432            0 :                 else if(parentFace)
    1433            0 :                         set_center_vertex(parentFace, nVrt);
    1434              :         }
    1435            0 : }
    1436              : 
    1437              : template <class TSelector>
    1438            0 : void HangingNodeRefinerBase<TSelector>::
    1439              : process_constrained_edge(ConstrainedEdge* cde)
    1440              : {
    1441              :         GridObject* constrObj = cde->get_constraining_object();
    1442            0 :         if(constrObj && (marked_to_normal(cde) || marked_to_constraining(cde))){
    1443            0 :                 switch(cde->get_parent_base_object_id()){
    1444              :                         case EDGE:{
    1445            0 :                                         ConstrainingEdge* cge = dynamic_cast<ConstrainingEdge*>(constrObj);
    1446              :                                         UG_ASSERT(cge, "Constraining edge has invalid type!");
    1447              :                                         UG_ASSERT(marked_to_normal(cge),
    1448              :                                                           "Constraining edge has to be converted to a normal edge!");
    1449              :                                         cge->clear_constrained_edges();
    1450              :                                 }break;
    1451              :                         case FACE:{
    1452            0 :                                         ConstrainingFace* cgf = dynamic_cast<ConstrainingFace*>(constrObj);
    1453              :                                         UG_ASSERT(cgf, "Constraining face has invalid type!");
    1454              :                                         UG_ASSERT(marked_to_normal(cgf),
    1455              :                                                           "Constraining face has to be converted to a normal face!");
    1456              :                                         cgf->clear_constrained_edges();
    1457              :                                 }break;
    1458              :                         default:
    1459              :                                 break;
    1460              :                 }
    1461              :         }
    1462              : 
    1463            0 :         Grid& grid = *m_pGrid;
    1464            0 :         if(marked_to_normal(cde)){
    1465            0 :                 grid.create_and_replace<RegularEdge>(cde);
    1466              :         }
    1467            0 :         else if(marked_to_constraining(cde)){
    1468            0 :                 refine_edge_with_hanging_vertex(cde);
    1469              :         }
    1470            0 : }
    1471              : 
    1472              : template <class TSelector>
    1473            0 : void HangingNodeRefinerBase<TSelector>::
    1474              : process_constraining_edge(ConstrainingEdge* cge)
    1475              : {
    1476              : /*      HNODE_PROFILE_FUNC();
    1477              : 
    1478              : //      make sure that there is one hanging vertex and two constrained edges.
    1479              :         assert(cge->num_constrained_vertices() == 1 && "bad number of constrained vertices. There has to be exactly 1.");
    1480              :         assert(cge->num_constrained_edges() == 2 && "bad number of constrained edges. There have to be exactly 2.");
    1481              : 
    1482              : //      the grid
    1483              :         Grid& grid = *m_pGrid;
    1484              : 
    1485              : //      the central hanging vertex has to be transformed into a normal vertex
    1486              :         ConstrainedVertex* centralHV = NULL;
    1487              :         if(cge->num_constrained_vertices() > 0)
    1488              :                 centralHV = dynamic_cast<ConstrainedVertex*>(cge->constrained_vertex(0));
    1489              : 
    1490              :         if(!centralHV){
    1491              :                 UG_LOG("The central hanging vertex of a constraining edge is missing. ignoring edge.\n");
    1492              :                 return;
    1493              :         }
    1494              : 
    1495              : //      replace the central vertex with a normal vertex
    1496              :         RegularVertex* centerVrt = *grid.create_and_replace<RegularVertex>(centralHV);
    1497              : 
    1498              : //      Iterate over the constrained edges.
    1499              : //      Unmarked constrained edges will be replaced by a normal edge.
    1500              : //      Marked ones will be replaced by a ConstrainingEdge. Additionally
    1501              : //      associated constrained edges will be created together with the
    1502              : //      new central vertex.
    1503              :         for(size_t i = 0; i < cge->num_constrained_edges(); ++i){
    1504              :                 Edge* cde = cge->constrained_edge(i);
    1505              :                 if(is_marked(cde)){
    1506              :                         refine_edge_with_hanging_vertex(cde);
    1507              :                 }
    1508              :                 else{
    1509              :                 //      the constrained-edge can be transformed to a normal edge
    1510              :                         grid.create_and_replace<RegularEdge>(cde);
    1511              :                 }
    1512              :         }
    1513              : 
    1514              :         cge->clear_constrained_objects();
    1515              :         set_center_vertex(cge, centerVrt);*/
    1516            0 : }
    1517              : 
    1518              : template <class TSelector>
    1519            0 : void HangingNodeRefinerBase<TSelector>::
    1520              : refine_edge_with_normal_vertex(Edge* e, Vertex** newCornerVrts)
    1521              : {
    1522              :         UG_ASSERT(refinement_is_allowed(e), "Refinement of given edge not allowed!");
    1523              : 
    1524              : //      the grid
    1525            0 :         Grid& grid = *m_pGrid;
    1526              : 
    1527            0 :         if(marked_adaptive(e)){
    1528            0 :                 if(newCornerVrts){
    1529            0 :                         grid.create_by_cloning(e, EdgeDescriptor(newCornerVrts[0], newCornerVrts[1]), e);
    1530              :                 }
    1531            0 :                 return;
    1532              :         }
    1533              : 
    1534            0 :         RegularVertex* nVrt = *grid.create<RegularVertex>(e);
    1535            0 :         set_center_vertex(e, nVrt);
    1536              : 
    1537              : //      allow projector to calculate a new position
    1538            0 :         if(m_projector.valid())
    1539            0 :                 m_projector->new_vertex(nVrt, e);
    1540              : 
    1541              : //      split the edge
    1542            0 :         vector<Edge*> vEdges(2);
    1543            0 :         e->refine(vEdges, nVrt, newCornerVrts);
    1544              :         assert((vEdges.size() == 2) && "Edge::refine - produced wrong number of edges.");
    1545            0 :         grid.register_element(vEdges[0], e);
    1546            0 :         grid.register_element(vEdges[1], e);
    1547            0 : }
    1548              : 
    1549              : template <class TSelector>
    1550            0 : void HangingNodeRefinerBase<TSelector>::
    1551              : refine_edge_with_hanging_vertex(Edge* e, Vertex** newCornerVrts)
    1552              : {
    1553              :         UG_ASSERT(refinement_is_allowed(e), "Refinement of given edge not allowed!");
    1554              : 
    1555            0 :         Grid& grid = *m_pGrid;
    1556              : //      we have to insert a hanging node.
    1557              : //      e has to be transformed to a constraining edge at the same time.
    1558              :         assert(!ConstrainingEdge::type_match(e) && "invalid operation. e is a constraining edge.");
    1559              :         //assert(!ConstrainedEdge::type_match(e) && "invalid operation. e is a constrained edge.");
    1560              : 
    1561            0 :         ConstrainingEdge* ce = *grid.create_and_replace<ConstrainingEdge>(e);
    1562              : 
    1563            0 :         ConstrainedVertex* hv = *grid.create<ConstrainedVertex>(ce);
    1564              : 
    1565              : //      allow projector to calculate a new position
    1566            0 :         if(m_projector.valid())
    1567            0 :                 m_projector->new_vertex(hv, ce);
    1568              : 
    1569            0 :         set_center_vertex(ce, hv);
    1570              :         hv->set_constraining_object(ce);
    1571            0 :         ce->add_constrained_object(hv);
    1572              : 
    1573              :         hv->set_local_coordinate_1(0.5);
    1574              : 
    1575              : //      two constrained edges have to be created.
    1576              :         ConstrainedEdge* nEdge[2];
    1577            0 :         if(newCornerVrts){
    1578            0 :                 nEdge[0] = *grid.create<ConstrainedEdge>(EdgeDescriptor(newCornerVrts[0], hv), ce);
    1579            0 :                 nEdge[1] = *grid.create<ConstrainedEdge>(EdgeDescriptor(hv, newCornerVrts[1]), ce);
    1580              :         }
    1581              :         else{
    1582            0 :                 nEdge[0] = *grid.create<ConstrainedEdge>(EdgeDescriptor(ce->vertex(0), hv), ce);
    1583            0 :                 nEdge[1] = *grid.create<ConstrainedEdge>(EdgeDescriptor(hv, ce->vertex(1)), ce);
    1584              :         }
    1585              : 
    1586            0 :         for(uint i = 0; i < 2; ++i)
    1587              :         {
    1588            0 :                 ce->add_constrained_object(nEdge[i]);
    1589              :                 nEdge[i]->set_constraining_object(ce);
    1590              :         }
    1591            0 : }
    1592              : 
    1593              : template <class TSelector>
    1594            0 : void HangingNodeRefinerBase<TSelector>::
    1595              : refine_face_with_normal_vertex(Face* f, Vertex** newCornerVrts)
    1596              : {
    1597              :         UG_ASSERT(refinement_is_allowed(f), "Refinement of given face not allowed!");
    1598              : 
    1599              : //UG_LOG("refine_face_with_normal_vertex\n");
    1600            0 :         Grid& grid = *m_pGrid;
    1601              : 
    1602              :         Vertex* vNewEdgeVertices[MAX_FACE_VERTICES];
    1603            0 :         vector<Face*>             vFaces(f->num_vertices());// heuristic
    1604              : 
    1605            0 :         const size_t numVrts = f->num_vertices();
    1606              :         const size_t numEdges = f->num_edges();
    1607              :         bool noEdgeVrts = true;
    1608              : 
    1609            0 :         const int localMark = get_local_mark(f);
    1610            0 :         if(localMark && marked_local(f)){
    1611            0 :                 for(size_t i = 0; i < numEdges; ++i){
    1612            0 :                         if(localMark & (1<<i)){
    1613            0 :                                 vNewEdgeVertices[i] = get_center_vertex(grid.get_edge(f, i));
    1614            0 :                                 if(vNewEdgeVertices[i])
    1615              :                                         noEdgeVrts = false;
    1616              :                         }
    1617              :                         else
    1618            0 :                                 vNewEdgeVertices[i] = NULL;
    1619              :                 }
    1620              :         }
    1621              :         else{
    1622            0 :                 for(size_t i = 0; i < numEdges; ++i){
    1623            0 :                         Edge* e = grid.get_edge(f, i);
    1624              : 
    1625              :                 //      if the face is refined with a regular rule, then every edge has to have
    1626              :                 //      an associated center vertex
    1627              :                         UG_ASSERT(marked_adaptive(f) ||
    1628              :                                    (get_mark(f) == RM_REFINE && get_center_vertex(e) != NULL),
    1629              :                                    "violated for " << ElementDebugInfo(grid, f));
    1630              : 
    1631              :                 //      assign the center vertex
    1632            0 :                         vNewEdgeVertices[i] = get_center_vertex(e);
    1633            0 :                         if(vNewEdgeVertices[i])
    1634              :                                 noEdgeVrts = false;
    1635              :                 }
    1636              :         }
    1637              : 
    1638            0 :         if(marked_adaptive(f) && noEdgeVrts){
    1639            0 :                 if(newCornerVrts){
    1640            0 :                         FaceDescriptor desc(numVrts);
    1641            0 :                         for(size_t i = 0; i < numVrts; ++i)
    1642            0 :                                 desc.set_vertex(i, newCornerVrts[i]);
    1643            0 :                         grid.create_by_cloning(f, desc, f);
    1644              :                 }
    1645              :                 return;
    1646              :         }
    1647              : 
    1648              : //      we'll perform a regular refine
    1649            0 :         Vertex* nVrt = NULL;
    1650              :         /*f->refine_regular(vFaces, &nVrt, vNewEdgeVertices, NULL,
    1651              :                                           RegularVertex(), newCornerVrts);*/
    1652            0 :         f->refine(vFaces, &nVrt, vNewEdgeVertices, NULL, newCornerVrts);
    1653              : 
    1654              : //      if a new vertex has been created during refine, then register it at the grid.
    1655            0 :         if(nVrt)
    1656              :         {
    1657              :                 grid.register_element(nVrt, f);
    1658              : 
    1659              :         //      allow projector to calculate a new position
    1660            0 :                 if(m_projector.valid())
    1661            0 :                         m_projector->new_vertex(nVrt, f);
    1662              :         }
    1663              : 
    1664            0 :         for(uint i = 0; i < vFaces.size(); ++i)
    1665              :         {
    1666            0 :                 grid.register_element(vFaces[i], f);
    1667              :         }
    1668              : 
    1669            0 :         set_center_vertex(f, nVrt);
    1670            0 : }
    1671              : 
    1672              : template <class TSelector>
    1673            0 : void HangingNodeRefinerBase<TSelector>::
    1674              : refine_face_with_hanging_vertex(Face* f, Vertex** newCornerVrts)
    1675              : {
    1676              :         UG_ASSERT(refinement_is_allowed(f), "Refinement of given face not allowed!");
    1677              : 
    1678              : //UG_LOG("refine_face_with_hanging_vertex\n");
    1679            0 :         Grid& grid = *m_pGrid;
    1680              : 
    1681            0 :         size_t numVrts = f->num_vertices();
    1682              : /*
    1683              :         vector<Edge*>     vEdges(f->num_edges());
    1684              :         vector<Vertex*> vNewEdgeVertices(f->num_edges());
    1685              :         vector<Face*>             vFaces(numVrts);// heuristic
    1686              : 
    1687              : //todo: iterate over edges directly
    1688              : //      collect all associated edges.
    1689              :         CollectEdges(vEdges, grid, f);
    1690              :         size_t numEdges = vEdges.size();
    1691              : 
    1692              :         assert(numEdges == f->num_edges() && "ERROR in RefineFaceWithNormalVertex(...): associated edges missing.");
    1693              : 
    1694              : //      each should have an associated vertex. sort them into vNewEdgeVertices.
    1695              :         for(size_t i = 0; i < numEdges; ++i)
    1696              :         {
    1697              :                 Edge* e = vEdges[i];
    1698              :                 int edgeIndex = GetEdgeIndex(f, e);
    1699              : 
    1700              :                 assert((edgeIndex >= 0) && (edgeIndex < (int)vEdges.size()) && "ERROR in RefineFaceWithNormalVertex(...): unknown problem in CollectEdges / GetEdgeIndex.");
    1701              :                 //assert((get_center_vertex(e) != NULL) && "ERROR in RefineFaceWithNormalVertex(...): no new vertex on refined edge.");
    1702              :                 vNewEdgeVertices[edgeIndex] = get_center_vertex(e);
    1703              :         }
    1704              : */
    1705              :         Vertex* vNewEdgeVertices[MAX_FACE_VERTICES];
    1706            0 :         vector<Face*>             vFaces(f->num_vertices());// heuristic
    1707              : 
    1708              :         size_t numEdges = f->num_edges();
    1709              :         size_t numMarkedEdges = 0;
    1710              : 
    1711            0 :         const int localMark = get_local_mark(f);
    1712            0 :         if(localMark && marked_local(f)){
    1713            0 :                 for(size_t i = 0; i < numEdges; ++i){
    1714            0 :                         if(localMark & (1<<i)){
    1715            0 :                                 vNewEdgeVertices[i] = get_center_vertex(grid.get_edge(f, i));
    1716            0 :                                 if(vNewEdgeVertices[i])
    1717            0 :                                         ++numMarkedEdges;
    1718              :                         }
    1719              :                         else
    1720            0 :                                 vNewEdgeVertices[i] = NULL;
    1721              :                 }
    1722              :         }
    1723              :         else{
    1724            0 :                 for(size_t i = 0; i < numEdges; ++i){
    1725            0 :                         Edge* e = grid.get_edge(f, i);
    1726              : 
    1727              :                 //      if the face is refined with a regular rule, then every edge has to have
    1728              :                 //      an associated center vertex
    1729              :                         assert(marked_adaptive(f) ||
    1730              :                                         ((get_mark(f) == RM_REFINE)));
    1731              : 
    1732              :                 //      assign the center vertex
    1733            0 :                         vNewEdgeVertices[i] = get_center_vertex(e);
    1734            0 :                         if(vNewEdgeVertices[i])
    1735            0 :                                 ++numMarkedEdges;
    1736              :                 }
    1737              :         }
    1738              : 
    1739              :         ConstrainingFace* cgf = NULL;
    1740              :         ConstrainedVertex* hv = NULL;
    1741              : 
    1742              : //      the face has to be replaced by a constraining face.
    1743              : //      we'll perform a switch here depending on the number of vertices
    1744            0 :         switch(numVrts)
    1745              :         {
    1746            0 :                 case 3:
    1747              :                         {
    1748              :                         //      create the constraining triangle and replace the old face.
    1749            0 :                                 cgf = *grid.create_and_replace<ConstrainingTriangle>(f);
    1750              : 
    1751              :                         //      create the constrained faces.
    1752              :                         //      the following triangle will not be registered at the grid. Just a temporary one.
    1753            0 :                                 ConstrainedTriangle constrainedTri(cgf->vertex(0),
    1754            0 :                                                                                                         cgf->vertex(1),
    1755            0 :                                                                                                         cgf->vertex(2));
    1756              : 
    1757              :                         //      refine the constrained tri
    1758              :                                 Vertex* tmpVrt;
    1759            0 :                                 constrainedTri.refine(vFaces, &tmpVrt, vNewEdgeVertices,
    1760              :                                                                           NULL, newCornerVrts);
    1761              :                         }
    1762            0 :                         break;
    1763            0 :                 case 4:
    1764              :                         {
    1765            0 :                                 cgf = *grid.create_and_replace<ConstrainingQuadrilateral>(f);
    1766              : 
    1767              :                         //      a central hanging vertex is required
    1768            0 :                                 if(numMarkedEdges == 4){
    1769            0 :                                         hv = *grid.create<ConstrainedVertex>(cgf);
    1770              : 
    1771              :                                 //      allow projector to calculate a new position
    1772            0 :                                         if(m_projector.valid())
    1773            0 :                                                 m_projector->new_vertex(hv, cgf);
    1774              : 
    1775            0 :                                         set_center_vertex(cgf, hv);
    1776              : 
    1777              :                                         hv->set_constraining_object(cgf);
    1778            0 :                                         cgf->add_constrained_object(hv);
    1779              :                                         hv->set_local_coordinates(0.5, 0.5);
    1780              :                                 }
    1781              : 
    1782              :                         //      create the constrained faces.
    1783              :                         //      the following quadrilateral will not be registered at the grid. Just a temporary one.
    1784            0 :                                 ConstrainedQuadrilateral cdf(cgf->vertex(0), cgf->vertex(1),
    1785            0 :                                                                                          cgf->vertex(2), cgf->vertex(3));
    1786              : 
    1787              :                         //      refine the constrained quad
    1788              :                                 Vertex* tmpVrt;
    1789            0 :                                 cdf.refine(vFaces, &tmpVrt, vNewEdgeVertices, hv, newCornerVrts);
    1790              : 
    1791            0 :                                 UG_COND_THROW(tmpVrt != hv, "Internal refinement error.");
    1792              :                         }
    1793            0 :                         break;
    1794              :                 default:
    1795              :                         assert(!"unsupported element type.");
    1796              :                         break;
    1797              :         }
    1798              : 
    1799              :         if(cgf)
    1800              :         {
    1801              :         //      register the new faces
    1802            0 :                 for(size_t i = 0; i < vFaces.size(); ++i)
    1803              :                 {
    1804            0 :                         ConstrainedFace* cdf = dynamic_cast<ConstrainedFace*>(vFaces[i]);
    1805              :                         assert(cdf && "constrained face refine did produce faces which are not constrained.");
    1806            0 :                         if(cdf)
    1807              :                         {
    1808              :                                 grid.register_element(cdf, cgf);
    1809              :                                 cdf->set_constraining_object(cgf);
    1810            0 :                                 cgf->add_constrained_object(cdf);
    1811              :                         }
    1812              :                 }
    1813              : 
    1814              :         //      we have to link the new constrained edges which have been auto-generated between the constrained faces.
    1815              :         //      Since only edges that lie inside of the constraining face are newly created, and since only those
    1816              :         //      have to be linked with the constraining face, the following algorithm will be ok for
    1817              :         //      triangles and quadrilaterals.
    1818              :         //      Check for each new edge-vertex, if an edge exists with the new center vertex or with it's next neighbor.
    1819            0 :                 if(hv)
    1820              :                 {
    1821            0 :                         for(size_t i = 0; i < numEdges; ++i) {
    1822            0 :                                 ConstrainedEdge* e = dynamic_cast<ConstrainedEdge*>(grid.get_edge(vNewEdgeVertices[i], hv));
    1823            0 :                                 if(e)
    1824              :                                 {
    1825              :                                 //      link e with the constraining face
    1826              :                                         e->set_constraining_object(cgf);
    1827            0 :                                         cgf->add_constrained_object(e);
    1828              :                                 }
    1829              :                         }
    1830              :                 }
    1831            0 :                 else if(numVrts == 3 && numMarkedEdges == 3){
    1832            0 :                         for(size_t i = 0; i < numEdges; ++i) {
    1833              :                         //      check if a constrained edge exists between the vertex and its next neighbor
    1834            0 :                                 Vertex* vNext = vNewEdgeVertices[(i + 1) % numEdges];
    1835            0 :                                 ConstrainedEdge* e = dynamic_cast<ConstrainedEdge*>(grid.get_edge(vNewEdgeVertices[i], vNext));
    1836            0 :                                 if(e)
    1837              :                                 {
    1838              :                                 //      link e with the constraining face
    1839              :                                         e->set_constraining_object(cgf);
    1840            0 :                                         cgf->add_constrained_object(e);
    1841              :                                 }
    1842              :                         }
    1843              :                 }
    1844              :                 else{
    1845            0 :                         for(size_t i = 0; i < numEdges; ++i) {
    1846            0 :                                 Vertex* vCur = vNewEdgeVertices[i];
    1847            0 :                                 if(!vCur)
    1848            0 :                                         continue;
    1849              : 
    1850              :                         //      check if constrained edges exist between pairs of new edge vertices
    1851              :                         //      and pairs of new edge vertices and normal vertices
    1852            0 :                                 for(size_t j = i + 1; j < numEdges; ++j){
    1853            0 :                                         Vertex* vNext = vNewEdgeVertices[j];
    1854            0 :                                         if(vNext){
    1855            0 :                                                 ConstrainedEdge* e = dynamic_cast<ConstrainedEdge*>(grid.get_edge(vCur, vNext));
    1856            0 :                                                 if(e)
    1857              :                                                 {
    1858              :                                                 //      link e with the constraining face
    1859              :                                                         e->set_constraining_object(cgf);
    1860            0 :                                                         cgf->add_constrained_object(e);
    1861              :                                                 }
    1862              :                                         }
    1863              :                                 }
    1864              : 
    1865            0 :                                 for(size_t j = i + 2; j < i + 2 + numVrts - 2; ++j){
    1866              :                                         Vertex* vNext;
    1867            0 :                                         if(newCornerVrts)
    1868            0 :                                                 vNext = newCornerVrts[j%numVrts];
    1869              :                                         else
    1870            0 :                                                 vNext = cgf->vertex(j%numVrts);
    1871              : 
    1872            0 :                                         ConstrainedEdge* e = dynamic_cast<ConstrainedEdge*>(grid.get_edge(vCur, vNext));
    1873            0 :                                         if(e)
    1874              :                                         {
    1875              :                                         //      link e with the constraining face
    1876              :                                                 e->set_constraining_object(cgf);
    1877            0 :                                                 cgf->add_constrained_object(e);
    1878              :                                         }
    1879              :                                 }
    1880              :                         }
    1881              :                 }
    1882              :         }
    1883            0 : }
    1884              : 
    1885              : template <class TSelector>
    1886            0 : void HangingNodeRefinerBase<TSelector>::
    1887              : process_constrained_face(ConstrainedFace* cdf)
    1888              : {
    1889              :         GridObject* constrObj = cdf->get_constraining_object();
    1890              : 
    1891            0 :         if(constrObj && (marked_to_normal(cdf) || marked_to_constraining(cdf))){
    1892            0 :                 switch(cdf->get_parent_base_object_id()){
    1893              :                         case FACE:{
    1894            0 :                                         ConstrainingFace* cgf = dynamic_cast<ConstrainingFace*>(constrObj);
    1895              :                                         UG_ASSERT(cgf, "Constraining face has invalid type!");
    1896              :                                         UG_ASSERT(marked_to_normal(cgf),
    1897              :                                                           "Constraining face has to be converted to a normal face!");
    1898              :                                         cgf->clear_constrained_faces();
    1899              :                                 }break;
    1900              :                         default:
    1901              :                                 UG_ASSERT(cdf->get_constraining_object() == NULL,
    1902              :                                                   "Invalid constraining object encountered!");
    1903              :                                 break;
    1904              :                 }
    1905              :         }
    1906              : 
    1907            0 :         Grid& grid = *m_pGrid;
    1908            0 :         if(marked_to_normal(cdf)){
    1909            0 :                 if(cdf->num_vertices() == 3)
    1910            0 :                         grid.create_and_replace<Triangle>(cdf);
    1911              :                 else
    1912            0 :                         grid.create_and_replace<Quadrilateral>(cdf);
    1913              :         }
    1914            0 :         else if(marked_to_constraining(cdf)){
    1915            0 :                 refine_face_with_hanging_vertex(cdf);
    1916              :         }
    1917            0 : }
    1918              : 
    1919              : template <class TSelector>
    1920            0 : void HangingNodeRefinerBase<TSelector>::
    1921              : process_constraining_face(ConstrainingFace* cgf)
    1922              : {
    1923            0 :         Grid& grid = *m_pGrid;
    1924              : /*
    1925              :         size_t numVrts = cgf->num_vertices();
    1926              : 
    1927              : //      make sure that there is one hanging vertex and two constrained edges.
    1928              :         UG_ASSERT(cgf->num_constrained_edges() == numVrts,
    1929              :                          "bad number of constrained edges: " << cgf->num_constrained_edges()
    1930              :                          << ". There have to be as many as vertices: " << numVrts << "."
    1931              :                          << "At face with center " << GetGridObjectCenter(grid, cgf));
    1932              :         UG_ASSERT(cgf->num_constrained_faces() == 4,
    1933              :                           "bad number of constrained faces. There have to be exactly 4. "
    1934              :                           << "At face with center " << GetGridObjectCenter(grid, cgf));
    1935              : 
    1936              :         ConstrainedVertex* centralHV = NULL;
    1937              :         RegularVertex* centerVrt = NULL;
    1938              : 
    1939              :         if(numVrts == 4){
    1940              :         //      the central hanging vertex has to be transformed into a normal vertex
    1941              :                 centralHV = NULL;
    1942              :                 if(cgf->num_constrained_vertices() > 0)
    1943              :                         centralHV = dynamic_cast<ConstrainedVertex*>(cgf->constrained_vertex(0));
    1944              : 
    1945              :         //      replace the central vertex with a normal vertex
    1946              :                 if(centralHV)
    1947              :                         centerVrt = *grid.create_and_replace<RegularVertex>(centralHV);
    1948              :         }
    1949              : 
    1950              : //      Iterate over the constrained edges.
    1951              : //      Unmarked constrained edges will be replaced by a normal edge.
    1952              : //      Marked ones will be replaced by a ConstrainingEdge. Additionally
    1953              : //      associated constrained edges will be created together with the
    1954              : //      new central vertex.
    1955              :         for(size_t i = 0; i < cgf->num_constrained_edges(); ++i){
    1956              :                 Edge* cde = cgf->constrained_edge(i);
    1957              :                 if(is_marked(cde)){
    1958              :                         refine_edge_with_hanging_vertex(cde);
    1959              :                 }
    1960              :                 else{
    1961              :                 //      the constrained-edge can be transformed to a normal edge
    1962              :                         grid.create_and_replace<RegularEdge>(cde);
    1963              :                 }
    1964              :         }
    1965              : 
    1966              : //      iterate over the constrained faces.
    1967              : //      If it is marked, we'll replace it by a constraining face and create
    1968              : //      associated constrained faces.
    1969              : //      if not, it will simply be transformed to a normal face.
    1970              : //      To ease implementation we will transform it anyway and if required we will
    1971              : //      call refine_face_with_hanging_vertex(...).
    1972              :         for(size_t i = 0; i < cgf->num_constrained_faces(); ++i){
    1973              :                 Face* f = cgf->constrained_face(i);
    1974              :                 if(is_marked(f)){
    1975              :                 //      refine it using hanging_node_refinement.
    1976              :                         refine_face_with_hanging_vertex(f);
    1977              :                 }
    1978              :                 else{
    1979              :                 //      replace it by a normal face
    1980              :                         if(f->num_vertices() == 3)
    1981              :                                 f = *grid.create_and_replace<Triangle>(f);
    1982              :                         else
    1983              :                                 f = *grid.create_and_replace<Quadrilateral>(f);
    1984              :                 }
    1985              :         }
    1986              : */
    1987              : //      cgf->clear_constrained_objects();
    1988              : //      cgf itself now has to be transformed to a normal face
    1989              :         UG_ASSERT(marked_to_normal(cgf), "A constraining face has to be converted to"
    1990              :                                                                          " a normal face when it is refined.");
    1991            0 :         Vertex* centerVrt = get_center_vertex(cgf);
    1992              :         Face* nFace;
    1993            0 :         if(cgf->num_vertices() == 3)
    1994            0 :                 nFace = *grid.create_and_replace<Triangle>(cgf);
    1995              :         else
    1996            0 :                 nFace = *grid.create_and_replace<Quadrilateral>(cgf);
    1997              : 
    1998            0 :         if(centerVrt)
    1999            0 :                 set_center_vertex(nFace, centerVrt);
    2000            0 : }
    2001              : 
    2002              : template <class TSelector>
    2003            0 : void HangingNodeRefinerBase<TSelector>::
    2004              : refine_volume_with_normal_vertex(Volume* v, Vertex** newCornerVrts)
    2005              : {
    2006              :         UG_ASSERT(refinement_is_allowed(v), "Refinement of given volume not allowed!");
    2007              : 
    2008            0 :         Grid& grid = *m_pGrid;
    2009              : 
    2010              :         //vector<Edge*>   vEdges(v->num_edges());
    2011            0 :         vector<Vertex*> vNewEdgeVertices(v->num_edges());
    2012              :         //vector<Face*>           vFaces(v->num_faces());
    2013            0 :         vector<Vertex*>   vNewFaceVertices(v->num_faces());
    2014            0 :         vector<Volume*>           vVolumes(8);// heuristic
    2015              : //      collect all associated edges.
    2016              : 
    2017            0 :         const size_t numEdges = v->num_edges();
    2018              :         bool noEdgeVrts = true;
    2019              : 
    2020              : 
    2021            0 :         const int localMark = get_local_mark(v);
    2022            0 :         if(localMark && marked_local(v)){
    2023            0 :                 for(size_t i = 0; i < numEdges; ++i){
    2024            0 :                         if(localMark & (1<<i)){
    2025            0 :                                 vNewEdgeVertices[i] = get_center_vertex(grid.get_edge(v, i));
    2026            0 :                                 if(vNewEdgeVertices[i])
    2027              :                                         noEdgeVrts = false;
    2028              :                         }
    2029              :                         else
    2030            0 :                                 vNewEdgeVertices[i] = NULL;
    2031              :                 }
    2032              :         }
    2033              :         else{
    2034            0 :                 for(size_t i = 0; i < numEdges; ++i){
    2035            0 :                         Edge* e = grid.get_edge(v, i);
    2036            0 :                         vNewEdgeVertices[i] = get_center_vertex(e);
    2037            0 :                         if(vNewEdgeVertices[i])
    2038              :                                 noEdgeVrts = false;
    2039            0 :                         UG_COND_THROW(!(marked_adaptive(v) || vNewEdgeVertices[i]),
    2040              :                                                 "In order to fully refine a volume, all edges have "
    2041              :                                                 "to contain a new vertex!");
    2042              :                 }
    2043              :         }
    2044              : 
    2045            0 :         if(marked_adaptive(v) && noEdgeVrts){
    2046            0 :                 if(newCornerVrts){
    2047            0 :                         size_t numVrts = v->num_vertices();
    2048            0 :                         VolumeDescriptor desc(numVrts);
    2049            0 :                         for(size_t i = 0; i < numVrts; ++i)
    2050            0 :                                 desc.set_vertex(i, newCornerVrts[i]);
    2051            0 :                         grid.create_by_cloning(v, desc, v);
    2052              :                 }
    2053              :                 return;
    2054              :         }
    2055              : 
    2056            0 :         size_t numFaces = v->num_faces();
    2057            0 :         for(size_t i = 0; i < numFaces; ++i){
    2058            0 :                 Face* f = grid.get_face(v, i);
    2059              : 
    2060              :                 /*if(!VolumeContains(v, f))
    2061              :                 {
    2062              :                         UG_LOG("Grid::get_face(vol, ind) returned bad face.");
    2063              :                         MultiGrid* pmg = dynamic_cast<MultiGrid*>(m_pGrid);
    2064              :                         UG_LOG("Vol in level " << pmg->get_level(v));
    2065              :                         UG_LOG(", face in level " << pmg->get_level(f) << endl);
    2066              :                         UG_LOG("positions of volume vertices:");
    2067              :                         for(size_t i_c = 0; i_c < v->num_vertices(); ++i_c){
    2068              :                                 UG_LOG(" " << GetGridObjectCenter(grid, v->vertex(i_c)));
    2069              :                         }
    2070              :                         UG_LOG("\npositions of face vertices:");
    2071              :                         for(size_t i_c = 0; i_c < f->num_vertices(); ++i_c){
    2072              :                                 UG_LOG(" " << GetGridObjectCenter(grid, f->vertex(i_c)));
    2073              :                         }
    2074              :                         UG_LOG(endl);
    2075              :                 }*/
    2076              : 
    2077            0 :                 if(f->num_vertices() == 3)
    2078            0 :                         vNewFaceVertices[i] = NULL;
    2079              :                 else{
    2080            0 :                         vNewFaceVertices[i] = get_center_vertex(f);
    2081            0 :                         UG_COND_THROW(!(marked_adaptive(v) || vNewFaceVertices[i]),
    2082              :                                         "In order to fully refine a volume, all quadrilateral sides have"
    2083              :                                         " to contain a new vertex!"
    2084              :                                         << ", vol-center " << GetGridObjectCenter(grid, v)
    2085              :                                         << ", face-center " << GetGridObjectCenter(grid, f));
    2086              :                 //todo:remove this!!!
    2087              :                         /*if(!vNewFaceVertices[i]){
    2088              :                                 UG_LOG("missing face-vertex: " << GetGridObjectCenter(grid, f) << endl);
    2089              :                                 UG_LOG("corners of face:");
    2090              :                                 for(size_t i_c = 0; i_c < f->num_vertices(); ++i_c){
    2091              :                                         UG_LOG(" " << GetGridObjectCenter(grid, f->vertex(i_c)));
    2092              :                                 }
    2093              :                                 UG_LOG(endl);
    2094              :                                 UG_LOG("during refinement of volume: " << GetGridObjectCenter(grid, v) << endl);
    2095              :                         }*/
    2096              :                 }
    2097              :         }
    2098              : 
    2099              : //      if we're performing tetrahedral refinement, we have to collect
    2100              : //      the corner coordinates, so that the refinement algorithm may choose
    2101              : //      the best interior diagonal.
    2102            0 :         vector3 corners[4];
    2103              :         vector3* pCorners = NULL;
    2104            0 :         if((v->num_vertices() == 4) && m_projector.valid()){
    2105            0 :                 for(size_t i = 0; i < 4; ++i){
    2106            0 :                         corners[i] = m_projector->geometry()->pos(v->vertex(i));
    2107              :                 }
    2108              :                 pCorners = corners;
    2109              :         }
    2110              : 
    2111              : //      refine the volume and register new volumes at the grid.
    2112            0 :         Vertex* createdVrt = NULL;
    2113            0 :         v->refine(vVolumes, &createdVrt, &vNewEdgeVertices.front(),
    2114            0 :                           &vNewFaceVertices.front(), NULL, RegularVertex(), newCornerVrts, pCorners);
    2115              : 
    2116            0 :         if(createdVrt){
    2117              :         //      register the new vertex
    2118              :                 grid.register_element(createdVrt, v);
    2119              : 
    2120              :         //      allow projector to calculate a new position
    2121            0 :                 if(m_projector.valid())
    2122            0 :                         m_projector->new_vertex(createdVrt, v);
    2123              :         }
    2124              : 
    2125            0 :         for(uint i = 0; i < vVolumes.size(); ++i)
    2126            0 :                 grid.register_element(vVolumes[i], v);
    2127            0 : }
    2128              : 
    2129              : template class HangingNodeRefinerBase<Selector>;
    2130              : template void HangingNodeRefinerBase<Selector>::add_hmark(Vertex*, HNodeRefMarks);
    2131              : template void HangingNodeRefinerBase<Selector>::add_hmark(Edge*, HNodeRefMarks);
    2132              : template void HangingNodeRefinerBase<Selector>::add_hmark(Face*, HNodeRefMarks);
    2133              : template void HangingNodeRefinerBase<Selector>::add_hmark(Volume*, HNodeRefMarks);
    2134              : 
    2135              : template class HangingNodeRefinerBase<MGSelector>;
    2136              : template void HangingNodeRefinerBase<MGSelector>::add_hmark(Vertex*, HNodeRefMarks);
    2137              : template void HangingNodeRefinerBase<MGSelector>::add_hmark(Edge*, HNodeRefMarks);
    2138              : template void HangingNodeRefinerBase<MGSelector>::add_hmark(Face*, HNodeRefMarks);
    2139              : template void HangingNodeRefinerBase<MGSelector>::add_hmark(Volume*, HNodeRefMarks);
    2140              : 
    2141              : }// end of namespace
        

Generated by: LCOV version 2.0-1