|
ViennaGrid
1.0.1
|
00001 #ifndef VIENNAGRID_DETAIL_SEGMENT_LAYERS_HPP 00002 #define VIENNAGRID_DETAIL_SEGMENT_LAYERS_HPP 00003 00004 /* ======================================================================= 00005 Copyright (c) 2011-2012, Institute for Microelectronics, 00006 Institute for Analysis and Scientific Computing, 00007 TU Wien. 00008 00009 ----------------- 00010 ViennaGrid - The Vienna Grid Library 00011 ----------------- 00012 00013 Authors: Karl Rupp rupp@iue.tuwien.ac.at 00014 Josef Weinbub weinbub@iue.tuwien.ac.at 00015 00016 (A list of additional contributors can be found in the PDF manual) 00017 00018 License: MIT (X11), see file LICENSE in the base directory 00019 ======================================================================= */ 00020 00021 00022 #include <map> 00023 #include <set> 00024 #include <deque> 00025 00026 #include "viennagrid/forwards.h" 00027 #include "viennagrid/element.hpp" 00028 #include "viennagrid/detail/element_key.hpp" 00029 00034 namespace viennagrid 00035 { 00036 00038 00039 namespace detail 00040 { 00042 struct id_ptr_compare 00043 { 00044 template <typename ElementType> 00045 bool operator()(ElementType * e1, ElementType * e2) const 00046 { 00047 return e1->id() < e2->id(); 00048 } 00049 }; 00050 00052 template <typename Conf> 00053 class segment_domain_holder 00054 { 00055 typedef viennagrid::domain_t<Conf> domain_type; 00056 public: 00057 void domain(domain_type & d) { domain_ = &d; } 00058 00059 domain_type & domain() { return * domain_; } 00060 domain_type const & domain() const { return * domain_; } 00061 00062 std::size_t id() const 00063 { 00064 for (std::size_t i=0; i<domain_->segments().size(); ++i) 00065 { 00066 if (this == &(domain_->segments()[i])) 00067 return i; 00068 } 00069 00070 assert(false && "Segment ID cannot be found!"); 00071 return domain_->segments().size(); 00072 } 00073 00074 protected: 00075 domain_type * domain_; 00076 }; 00077 00078 template <typename Config, 00079 long dim> 00080 class segment_layers_full; 00081 00082 template <typename Config, 00083 long dim> 00084 class segment_layers_empty; 00085 00087 template <typename Config, 00088 long dim, 00089 typename handling_tag = typename result_of::bndcell_handling<Config, segment_t<Config>, dim>::type 00090 > 00091 struct next_segment_layer_selector 00092 { 00093 typedef segment_layers_full<Config, dim> type; 00094 }; 00095 00096 template <typename Config, long dim> 00097 struct next_segment_layer_selector<Config, dim, no_handling_tag> 00098 { 00099 typedef segment_layers_empty<Config, dim> type; 00100 }; 00101 00102 template <typename Config, typename handling_tag> 00103 struct next_segment_layer_selector<Config, 0, handling_tag> 00104 { 00105 typedef segment_layers_full<Config, 0> type; 00106 }; 00107 00108 00110 template <typename Config, 00111 long dim> 00112 class segment_layers_full : //public segment_layers<Config, 0, handling_tag> 00113 public next_segment_layer_selector<Config, dim-1>::type 00114 //public segment_domain_holder<Config> 00115 { 00116 typedef typename Config::cell_tag CellTag; 00117 typedef typename viennagrid::topology::bndcells<CellTag, dim>::tag ElementTag; 00118 typedef viennagrid::element_t<Config, ElementTag > LevelElementType; 00119 typedef typename viennagrid::topology::bndcells<CellTag, 0>::tag VertexTag; 00120 typedef viennagrid::element_t<Config, VertexTag > VertexType; 00121 typedef viennagrid::element_t<Config, typename Config::cell_tag> CellType; 00122 typedef typename viennagrid::result_of::element_container< segment_t<Config>, 00123 dim>::type container_type; 00124 typedef typename next_segment_layer_selector<Config, dim-1>::type base_type; 00125 00126 public: 00127 00128 void fill(CellType & cell) 00129 { 00130 //add vertices to segment: (note that the ncells<0>() is not available here) 00131 LevelElementType ** level_elements = cell.container(dimension_tag<dim>()); 00132 for (long i=0; i<topology::bndcells<typename Config::cell_tag, dim>::num; ++i) 00133 elements.insert(level_elements[i]); 00134 00135 base_type::fill(cell); 00136 } 00137 00139 00140 using base_type::container; 00141 00142 //non-const: 00143 container_type * 00144 container(dimension_tag<dim>) { return &elements; } 00145 00146 //const: 00147 const container_type * 00148 container(dimension_tag<dim>) const { return &elements; } 00149 00150 00151 private: 00152 container_type elements; 00153 }; 00154 00155 00156 //vertex level: 00158 template <typename Config> 00159 class segment_layers_full<Config, 0> : public segment_domain_holder<Config> 00160 { 00161 typedef typename Config::cell_tag CellTag; 00162 typedef typename viennagrid::topology::bndcells<CellTag, 0>::tag VertexTag; 00163 typedef viennagrid::element_t<Config, VertexTag > VertexType; 00164 typedef viennagrid::element_t<Config, typename Config::cell_tag> CellType; 00165 typedef typename result_of::element_container< segment_t<Config>, 00166 0>::type ContainerType; 00167 00168 public: 00169 00170 void fill(CellType & cell) 00171 { 00172 //add vertices to segment: (note that the ncells<0>() is not available here) 00173 VertexType ** cell_vertices = cell.container(dimension_tag<0>()); 00174 for (long i=0; i<viennagrid::topology::bndcells<typename Config::cell_tag, 0>::num; ++i) 00175 elements.insert(cell_vertices[i]); 00176 } 00177 00178 ContainerType * container(dimension_tag<0>) { return &elements; } 00179 const ContainerType * container(dimension_tag<0>) const { return &elements; } 00180 00181 private: 00182 ContainerType elements; //container of elements 00183 }; 00184 00185 00187 template <typename Config, 00188 long dim> 00189 class segment_layers_empty : public next_segment_layer_selector<Config, dim-1>::type 00190 { 00191 typedef typename Config::cell_tag CellTag; 00192 typedef typename viennagrid::topology::bndcells<CellTag, dim>::tag ElementTag; 00193 typedef viennagrid::element_t<Config, ElementTag > LevelElementType; 00194 typedef typename viennagrid::topology::bndcells<CellTag, 0>::tag VertexTag; 00195 typedef viennagrid::element_t<Config, VertexTag > VertexType; 00196 typedef viennagrid::element_t<Config, typename Config::cell_tag> CellType; 00197 typedef typename viennagrid::result_of::element_container< segment_t<Config>, 00198 dim>::type container_type; 00199 typedef typename next_segment_layer_selector<Config, dim-1>::type base_type; 00200 00201 public: 00202 00203 void fill(CellType & cell) 00204 { 00205 //nothing to do here. Just forward to lower level: 00206 base_type::fill(cell); 00207 } 00208 00210 00211 using base_type::container; 00212 00213 //non-const: 00214 container_type * 00215 container(dimension_tag<dim>) 00216 { 00217 typedef typename result_of::bndcell_handling<Config, 00218 CellTag, 00219 dim 00220 >::ERROR_HANDLING_OF_ELEMENTS_AT_THIS_TOPOLOGICAL_LEVEL_NOT_PROVIDED error_type; 00221 return NULL; 00222 } 00223 00224 //const: 00225 const container_type * 00226 container(dimension_tag<dim>) const 00227 { 00228 typedef typename result_of::bndcell_handling<Config, 00229 CellTag, 00230 dim 00231 >::ERROR_HANDLING_OF_ELEMENTS_AT_THIS_TOPOLOGICAL_LEVEL_NOT_PROVIDED error_type; 00232 return NULL; 00233 } 00234 00235 }; 00236 00238 template <typename Config, 00239 long dim> 00240 class segment_layers_top : public next_segment_layer_selector<Config, dim-1>::type 00241 { 00242 typedef typename Config::cell_tag CellTag; 00243 typedef typename viennagrid::topology::bndcells<typename Config::cell_tag, dim>::tag ElementTag; 00244 typedef viennagrid::element_t<Config, ElementTag > ElementType; 00245 typedef typename viennagrid::topology::bndcells<typename Config::cell_tag, 0>::tag VertexTag; 00246 typedef viennagrid::element_t<Config, VertexTag > VertexType; 00247 typedef viennagrid::element_t<Config, typename Config::cell_tag> CellType; 00248 typedef typename viennagrid::result_of::element_container< segment_t<Config>, dim>::type container_type; 00249 typedef typename next_segment_layer_selector<Config, dim-1>::type base_type; 00250 00251 public: 00252 00253 void push_back(CellType & cell) 00254 { 00255 //add cell to domain and keep pointer in segment 00256 //std::cout << "Adding cell to domain and to segment" << std::endl; 00257 elements.push_back(base_type::domain_->push_back(cell)); 00258 00259 base_type::fill(*elements.back()); 00260 } 00261 00262 00264 00265 using base_type::container; 00266 00267 //non-const: 00268 container_type * 00269 container(dimension_tag<dim>) { return &elements; } 00270 00271 //const: 00272 const container_type * 00273 container(dimension_tag<dim>) const { return &elements; } 00274 00275 private: 00276 container_type elements; 00277 }; 00278 00279 } //namespace detail 00280 00281 00282 // a few metafunctions returning the correct container for segments: 00283 namespace result_of 00284 { 00285 //at cell level 00287 template <typename config_type, long cell_level> 00288 struct element_container< segment_t<config_type>, cell_level, cell_level> 00289 { 00290 typedef typename viennagrid::result_of::ncell<config_type, cell_level>::type element_type; 00291 00292 typedef std::deque< element_type * > type; 00293 }; 00294 00295 //at vertex level 00297 template <typename config_type, long cell_level> 00298 struct element_container< segment_t<config_type>, 0, cell_level> 00299 { 00300 typedef typename viennagrid::result_of::ncell<config_type, 0>::type element_type; 00301 00302 // Note that with the use of deque, pointer comparison does not induce a valid ordering! 00303 // This is a problem when trying to write mesh files (vertices are not printed in order) 00304 typedef std::set< element_type *, viennagrid::detail::id_ptr_compare > type; 00305 }; 00306 00307 //at any other level: 00309 template <typename config_type, long dim, long cell_level> 00310 struct element_container< segment_t<config_type>, dim, cell_level> 00311 { 00312 typedef typename viennagrid::result_of::ncell<config_type, dim>::type element_type; 00313 00314 typedef std::set< element_type * > type; 00315 }; 00316 00318 template <typename ConfigType> 00319 struct segment 00320 { 00321 typedef segment_t<ConfigType> type; 00322 }; 00323 00324 00325 } //namespace result_of 00326 00327 } //namespace viennagrid 00328 #endif
1.7.6.1