ViennaGrid - The Vienna Grid Library  2.1.0
viennagrid/algorithm/detail/refine_tri.hpp
Go to the documentation of this file.
00001 #ifndef VIENNAGRID_ALGORITHM_DETAIL_REFINE_TRI_HPP
00002 #define VIENNAGRID_ALGORITHM_DETAIL_REFINE_TRI_HPP
00003 
00004 /* =======================================================================
00005    Copyright (c) 2011-2014, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008 
00009                             -----------------
00010                      ViennaGrid - The Vienna Grid Library
00011                             -----------------
00012 
00013    License:      MIT (X11), see file LICENSE in the base directory
00014 ======================================================================= */
00015 
00016 #include "viennagrid/forwards.hpp"
00017 #include "viennagrid/mesh/segmentation.hpp"
00018 #include "viennagrid/topology/vertex.hpp"
00019 #include "viennagrid/topology/line.hpp"
00020 #include "viennagrid/algorithm/norm.hpp"
00021 
00026 namespace viennagrid
00027 {
00028   namespace detail
00029   {
00030 
00031     template<typename ElementsVerticesHandleContainerT, typename VertexHandleContainer>
00032     void add_refinement_element(ElementsVerticesHandleContainerT & elements_vertices,
00033                                 VertexHandleContainer vertex_handle_container,
00034                                 unsigned int i0, unsigned int i1, unsigned int i2)
00035     {
00036       elements_vertices.resize( elements_vertices.size()+1 );
00037 
00038       elements_vertices.back().resize(3);
00039       elements_vertices.back()[0] = *viennagrid::advance(vertex_handle_container.begin(), i0);
00040       elements_vertices.back()[1] = *viennagrid::advance(vertex_handle_container.begin(), i1);
00041       elements_vertices.back()[2] = *viennagrid::advance(vertex_handle_container.begin(), i2);
00042     }
00043 
00044 
00046     template<>
00047     struct element_refinement<triangle_tag>
00048     {
00049 
00051       template<typename ElementType, typename MeshT,
00052                typename ElementsVerticesHandleContainerT,
00053                typename VertexCopyMapT,
00054                typename EdgeRefinementFlagAccessor, typename EdgeToVertexHandleAccessor>
00055       static void apply0(ElementType const & element_in, MeshT const &,
00056                          ElementsVerticesHandleContainerT & elements_vertices,
00057                          VertexCopyMapT & vertex_copy_map_,
00058                          EdgeRefinementFlagAccessor const &, EdgeToVertexHandleAccessor const &)
00059       {
00060         typedef typename viennagrid::result_of::const_element_range<ElementType, viennagrid::vertex_tag>::type            VertexOnCellRange;
00061         typedef typename viennagrid::result_of::iterator<VertexOnCellRange>::type         VertexOnCellIterator;
00062 
00063         typedef typename viennagrid::result_of::vertex_handle<MeshT>::type             VertexHandleType;
00064 
00065         static_array<VertexHandleType, boundary_elements<triangle_tag, vertex_tag>::num> vertex_handles;
00066 
00067         //
00068         // Step 1: Get vertices on the new mesh
00069         //
00070 
00071         //grab existing vertices:
00072         VertexOnCellRange vertices_on_cell = viennagrid::elements<viennagrid::vertex_tag>(element_in);
00073         VertexOnCellIterator vocit = vertices_on_cell.begin();
00074         vertex_handles[0] = vertex_copy_map_(*vocit); ++vocit;
00075         vertex_handles[1] = vertex_copy_map_(*vocit); ++vocit;
00076         vertex_handles[2] = vertex_copy_map_(*vocit);
00077 
00078         //
00079         // Step 2: Add new cells to new mesh:
00080         //
00081 
00082         add_refinement_element( elements_vertices, vertex_handles, 0, 1, 2);
00083 
00084       } //apply0()
00085 
00086 
00096       template<typename ElementType, typename MeshT,
00097                typename ElementsVerticesHandleContainerT,
00098                typename VertexCopyMapT,
00099                typename EdgeRefinementFlagAccessor, typename EdgeToVertexHandleAccessor>
00100       static void apply1(ElementType const & element_in, MeshT const &,
00101                          ElementsVerticesHandleContainerT & elements_vertices,
00102                          VertexCopyMapT & vertex_copy_map_,
00103                          EdgeRefinementFlagAccessor const & edge_refinement_flag_accessor, EdgeToVertexHandleAccessor const & edge_to_vertex_handle_accessor)
00104       {
00105         typedef typename viennagrid::result_of::const_element_range<ElementType, viennagrid::vertex_tag>::type            VertexOnCellRange;
00106         typedef typename viennagrid::result_of::iterator<VertexOnCellRange>::type         VertexOnCellIterator;
00107         typedef typename viennagrid::result_of::const_element_range<ElementType, viennagrid::line_tag>::type            EdgeOnCellRange;
00108         typedef typename viennagrid::result_of::iterator<EdgeOnCellRange>::type           EdgeOnCellIterator;
00109 
00110         typedef typename viennagrid::result_of::handle<MeshT, viennagrid::vertex_tag>::type             VertexHandleType;
00111         typedef typename viennagrid::result_of::element<MeshT, viennagrid::line_tag>::type             EdgeType;
00112 
00113         const unsigned int num_vertices = boundary_elements<triangle_tag, vertex_tag>::num;
00114         static_array<VertexHandleType, num_vertices+1> vertex_handles;
00115 
00116 
00117         //
00118         // Step 1: Get vertices on the new mesh
00119         //
00120 
00121         //grab existing vertices:
00122         VertexOnCellRange vertices_on_cell(element_in);
00123         VertexOnCellIterator vocit = vertices_on_cell.begin();
00124         vertex_handles[0] = vertex_copy_map_(*vocit); ++vocit;
00125         vertex_handles[1] = vertex_copy_map_(*vocit); ++vocit;
00126         vertex_handles[2] = vertex_copy_map_(*vocit);
00127 
00128         //add vertices from edge
00129         EdgeOnCellRange edges_on_cell(element_in);
00130         std::size_t offset = 0;
00131         EdgeOnCellIterator eocit = edges_on_cell.begin();
00132         EdgeType const & e0 = *eocit; ++eocit;
00133         EdgeType const & e1 = *eocit; ++eocit;
00134         EdgeType const & e2 = *eocit;
00135 
00136         if ( edge_refinement_flag_accessor(e0) )
00137         {
00138           vertex_handles[3] = edge_to_vertex_handle_accessor(e0);
00139           offset = 0;
00140         }
00141         else if ( edge_refinement_flag_accessor(e1) )
00142         {
00143           vertex_handles[3] = edge_to_vertex_handle_accessor(e1);
00144           offset = 2;
00145         }
00146         else if ( edge_refinement_flag_accessor(e2) )
00147         {
00148           vertex_handles[3] = edge_to_vertex_handle_accessor(e2);
00149           offset = 1;
00150         }
00151         else
00152         {
00153           assert( (2 < 2) && "Logic error: Triangle does not have an edges for bisection!");
00154         }
00155 
00156         //
00157         // Step 2: Add new cells to new mesh:
00158         //
00159         //0-3-2
00160         add_refinement_element( elements_vertices, vertex_handles, (offset + 0) % num_vertices, 3, (offset + 2) % num_vertices );
00161 
00162         //3-1-2:
00163         add_refinement_element( elements_vertices, vertex_handles, 3, (offset + 1) % num_vertices, (offset + 2) % num_vertices );
00164       } //apply1()
00165 
00166 
00177       template<typename ElementType, typename MeshT,
00178                typename ElementsVerticesHandleContainerT,
00179                typename VertexCopyMapT,
00180                typename EdgeRefinementFlagAccessor, typename EdgeToVertexHandleAccessor>
00181       static void apply2(ElementType const & element_in, MeshT const & mesh,
00182                          ElementsVerticesHandleContainerT & elements_vertices,
00183                          VertexCopyMapT & vertex_copy_map_,
00184                          EdgeRefinementFlagAccessor const & edge_refinement_flag_accessor, EdgeToVertexHandleAccessor const & edge_to_vertex_handle_accessor)
00185       {
00186         typedef typename viennagrid::result_of::const_element_range<ElementType, viennagrid::vertex_tag>::type            VertexOnCellRange;
00187         typedef typename viennagrid::result_of::iterator<VertexOnCellRange>::type         VertexOnCellIterator;
00188         typedef typename viennagrid::result_of::const_element_range<ElementType, viennagrid::line_tag>::type            EdgeOnCellRange;
00189         typedef typename viennagrid::result_of::iterator<EdgeOnCellRange>::type           EdgeOnCellIterator;
00190 
00191         typedef typename viennagrid::result_of::handle<MeshT, viennagrid::vertex_tag>::type             VertexHandleType;
00192         typedef typename viennagrid::result_of::element<MeshT, viennagrid::line_tag>::type             EdgeType;
00193 
00194         const unsigned int num_vertices = boundary_elements<triangle_tag, vertex_tag>::num;
00195         static_array<VertexHandleType, num_vertices+2> vertex_handles;
00196 
00197 
00198         //
00199         // Step 1: Get vertices on the new mesh
00200         //
00201 
00202         //grab existing vertices:
00203         VertexOnCellRange vertices_on_cell = viennagrid::elements<viennagrid::vertex_tag>(element_in);
00204         VertexOnCellIterator vocit = vertices_on_cell.begin();
00205         vertex_handles[0] = vertex_copy_map_(*vocit); ++vocit;
00206         vertex_handles[1] = vertex_copy_map_(*vocit); ++vocit;
00207         vertex_handles[2] = vertex_copy_map_(*vocit);
00208 
00209         //Find rotation offset such that first two edges are to be refined
00210         EdgeOnCellRange edges_on_cell = viennagrid::elements<viennagrid::line_tag>(element_in);
00211         std::size_t offset = 0;
00212 
00213         EdgeOnCellIterator eocit = edges_on_cell.begin();
00214         EdgeType const & e0 = *eocit; ++eocit;
00215         EdgeType const & e1 = *eocit; ++eocit;
00216         EdgeType const & e2 = *eocit;
00217 
00218         if ( edge_refinement_flag_accessor(e0) && edge_refinement_flag_accessor(e1) )
00219         {
00220           vertex_handles[3] = edge_to_vertex_handle_accessor(e1);
00221           vertex_handles[4] = edge_to_vertex_handle_accessor(e0);
00222           offset = 2;
00223         }
00224         else if ( edge_refinement_flag_accessor(e0) && edge_refinement_flag_accessor(e2) )
00225         {
00226           vertex_handles[3] = edge_to_vertex_handle_accessor(e0);
00227           vertex_handles[4] = edge_to_vertex_handle_accessor(e2);
00228           offset = 0;
00229         }
00230         else if ( edge_refinement_flag_accessor(e1) && edge_refinement_flag_accessor(e2) )
00231         {
00232           vertex_handles[3] = edge_to_vertex_handle_accessor(e2);
00233           vertex_handles[4] = edge_to_vertex_handle_accessor(e1);
00234           offset = 1;
00235         }
00236         else
00237         {
00238           assert( (2 < 2) && "Logic error: Triangle does not have two edges for bisection!");
00239         }
00240 
00241         //
00242         // Step 2: Add new cells to new mesh:
00243         //
00244 
00245         //3-1-4:
00246         add_refinement_element( elements_vertices, vertex_handles, 3, (offset + 1) % num_vertices, 4 );
00247 
00248         //split second-longest edge
00249         VertexHandleType vh0 = vertex_handles[(offset + 0) % num_vertices];
00250         VertexHandleType vh1 = vertex_handles[(offset + 1) % num_vertices];
00251         VertexHandleType vh2 = vertex_handles[(offset + 2) % num_vertices];
00252         double len_edge1 = viennagrid::norm( viennagrid::point(mesh, vh1) - viennagrid::point(mesh, vh0) );
00253         double len_edge2 = viennagrid::norm( viennagrid::point(mesh, vh2) - viennagrid::point(mesh, vh1) );
00254 
00255         if (len_edge1 > len_edge2) //split edge [v0, v1] again
00256         {
00257           //0-3-2:
00258           add_refinement_element( elements_vertices, vertex_handles, (offset + 0) % num_vertices, 3, (offset + 2) % num_vertices );
00259 
00260           //2-3-4:
00261           add_refinement_element( elements_vertices, vertex_handles, (offset + 2) % num_vertices, 3, 4 );
00262         }
00263         else //split edge [v1, v2]
00264         {
00265           //0-3-4:
00266           add_refinement_element( elements_vertices, vertex_handles, (offset + 0) % num_vertices, 3, 4 );
00267 
00268           //0-4-2:
00269           add_refinement_element( elements_vertices, vertex_handles, (offset + 0) % num_vertices, 4, (offset + 2) % num_vertices );
00270         }
00271 
00272 
00273       } //apply2()
00274 
00275 
00276 
00277 
00279       template<typename ElementType, typename MeshT,
00280                typename ElementsVerticesHandleContainerT,
00281                typename VertexCopyMapT,
00282                typename EdgeRefinementFlagAccessor, typename EdgeToVertexHandleAccessor>
00283       static void apply3(ElementType const & element_in, MeshT const &,
00284                          ElementsVerticesHandleContainerT & elements_vertices,
00285                          VertexCopyMapT & vertex_copy_map_,
00286                          EdgeRefinementFlagAccessor const &, EdgeToVertexHandleAccessor const & edge_to_vertex_handle_accessor)
00287       {
00288         typedef typename viennagrid::result_of::const_element_range<ElementType, viennagrid::vertex_tag>::type            VertexOnCellRange;
00289         typedef typename viennagrid::result_of::iterator<VertexOnCellRange>::type         VertexOnCellIterator;
00290         typedef typename viennagrid::result_of::const_element_range<ElementType, viennagrid::line_tag>::type            EdgeOnCellRange;
00291         typedef typename viennagrid::result_of::iterator<EdgeOnCellRange>::type           EdgeOnCellIterator;
00292 
00293         typedef typename viennagrid::result_of::handle<MeshT, viennagrid::vertex_tag>::type             VertexHandleType;
00294 
00295         const unsigned int num_vertices = boundary_elements<triangle_tag, vertex_tag>::num;
00296         const unsigned int num_lines = boundary_elements<triangle_tag, line_tag>::num;
00297 
00298         static_array<VertexHandleType, num_vertices+num_lines> vertex_handles;
00299 
00300         //
00301         // Step 1: Get vertices on the new mesh
00302         //
00303 
00304         //grab existing vertices:
00305         VertexOnCellRange vertices_on_cell = viennagrid::elements<viennagrid::vertex_tag>(element_in);
00306         VertexOnCellIterator vocit = vertices_on_cell.begin();
00307         vertex_handles[0] = vertex_copy_map_(*vocit); ++vocit;
00308         vertex_handles[1] = vertex_copy_map_(*vocit); ++vocit;
00309         vertex_handles[2] = vertex_copy_map_(*vocit);
00310 
00311         //add vertices from edge
00312         EdgeOnCellRange edges_on_cell = viennagrid::elements<viennagrid::line_tag>(element_in);
00313         EdgeOnCellIterator eocit = edges_on_cell.begin();
00314         vertex_handles[3] = edge_to_vertex_handle_accessor(*eocit); ++eocit;
00315         vertex_handles[4] = edge_to_vertex_handle_accessor(*eocit); ++eocit;
00316         vertex_handles[5] = edge_to_vertex_handle_accessor(*eocit);
00317 
00318         //
00319         // Step 2: Add new cells to new mesh:
00320         //
00321 
00322         //0-3-4:
00323         add_refinement_element( elements_vertices, vertex_handles, 0, 3, 4 );
00324 
00325         //3-1-5:
00326         add_refinement_element( elements_vertices, vertex_handles, 3, 1, 5 );
00327 
00328         //4-5-2:
00329         add_refinement_element( elements_vertices, vertex_handles, 4, 5, 2 );
00330 
00331         //4-3-5:
00332         add_refinement_element( elements_vertices, vertex_handles, 4, 3, 5 );
00333 
00334       } //apply3()
00335 
00336 
00346       template<typename ElementT, typename MeshT,
00347                typename ElementsVerticesHandleContainerT, typename VertexCopyMapT,
00348                typename EdgeRefinementFlagAccessor, typename EdgeToVertexHandleAccessor>
00349       static void apply(ElementT const & element_in, MeshT const & mesh,
00350                         ElementsVerticesHandleContainerT & elements_vertices,
00351                         VertexCopyMapT & vertex_copy_map_,
00352                         EdgeRefinementFlagAccessor const & edge_refinement_flag_accessor,
00353                         EdgeToVertexHandleAccessor const & edge_to_vertex_handle_accessor)
00354       {
00355         typedef typename viennagrid::result_of::const_element_range<ElementT, viennagrid::line_tag>::type            EdgeOnCellRange;
00356         typedef typename viennagrid::result_of::iterator<EdgeOnCellRange>::type                 EdgeOnCellIterator;
00357 
00358         std::size_t edges_to_refine = 0;
00359         EdgeOnCellRange edges_on_cell(element_in);
00360         for (EdgeOnCellIterator eocit = edges_on_cell.begin();
00361                                 eocit != edges_on_cell.end();
00362                               ++eocit)
00363         {
00364           if ( edge_refinement_flag_accessor(*eocit) )
00365             ++edges_to_refine;
00366         }
00367 
00368         switch (edges_to_refine)
00369         {
00370           case 0: apply0(element_in, mesh, elements_vertices, vertex_copy_map_, edge_refinement_flag_accessor,  edge_to_vertex_handle_accessor); break;
00371           case 1: apply1(element_in, mesh, elements_vertices, vertex_copy_map_, edge_refinement_flag_accessor, edge_to_vertex_handle_accessor); break;
00372           case 2: apply2(element_in, mesh, elements_vertices, vertex_copy_map_, edge_refinement_flag_accessor, edge_to_vertex_handle_accessor); break;
00373           case 3: apply3(element_in, mesh, elements_vertices, vertex_copy_map_, edge_refinement_flag_accessor, edge_to_vertex_handle_accessor); break;
00374           default: //nothing to do...
00375                   break;
00376         }
00377       } //apply()
00378     };
00379 
00380   } // namespace detail
00381 }
00382 
00383 #endif
00384