00001 #ifndef VIENNAGRID_DETAIL_SEGMENT_LAYERS_HPP
00002 #define VIENNAGRID_DETAIL_SEGMENT_LAYERS_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 :
00113 public next_segment_layer_selector<Config, dim-1>::type
00114
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
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
00143 container_type *
00144 container(dimension_tag<dim>) { return &elements; }
00145
00146
00147 const container_type *
00148 container(dimension_tag<dim>) const { return &elements; }
00149
00150
00151 private:
00152 container_type elements;
00153 };
00154
00155
00156
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
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;
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
00206 base_type::fill(cell);
00207 }
00208
00210
00211 using base_type::container;
00212
00213
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
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
00256
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
00268 container_type *
00269 container(dimension_tag<dim>) { return &elements; }
00270
00271
00272 const container_type *
00273 container(dimension_tag<dim>) const { return &elements; }
00274
00275 private:
00276 container_type elements;
00277 };
00278
00279 }
00280
00281
00282
00283 namespace result_of
00284 {
00285
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
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
00303
00304 typedef std::set< element_type *, viennagrid::detail::id_ptr_compare > type;
00305 };
00306
00307
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 }
00326
00327 }
00328 #endif