00001 #ifndef VIENNAGRID_ALGORITHM_BOUNDARY_HPP
00002 #define VIENNAGRID_ALGORITHM_BOUNDARY_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <vector>
00022 #include "viennagrid/forwards.h"
00023 #include "viennagrid/domain.hpp"
00024 #include "viennagrid/detail/element_iterators.hpp"
00025 #include "viennagrid/detail/domain_iterators.hpp"
00026
00031 namespace viennagrid
00032 {
00034 template <typename T>
00035 class boundary_key
00036 {
00037 typedef typename T::ERROR_BOUNDARY_KEY_MUST_BE_USED_WITH_NCELL_OR_DOMAIN_OR_SEGMENT error_type;
00038 };
00039
00041 template <typename ConfigType, typename ElementTag>
00042 class boundary_key<element_t<ConfigType, ElementTag> >
00043 {
00044 typedef element_t<ConfigType, ElementTag> element_type;
00045
00046 public:
00047 boundary_key(element_type const & e) : e_(&e) {}
00048
00050 bool operator<(boundary_key const & other) const
00051 {
00052 return e_ < other.e_;
00053 }
00054 private:
00055 element_type const * e_;
00056 };
00057
00059 template <typename ConfigType>
00060 class boundary_key< segment_t<ConfigType> >
00061 {
00062 public:
00063 boundary_key(std::size_t seg_id) : seg_id_(seg_id) {}
00064
00066 bool operator<(boundary_key const & other) const
00067 {
00068 return seg_id_ < other.seg_id_;
00069 }
00070 private:
00071 std::size_t seg_id_;
00072 };
00073
00075 template <typename ConfigType>
00076 class boundary_key< domain_t<ConfigType> > {};
00077
00078 }
00079
00080
00081
00083 namespace viennadata
00084 {
00086 namespace config
00087 {
00088 template <typename ConfigType>
00089 struct key_dispatch<viennagrid::boundary_key< viennagrid::domain_t<ConfigType> > >
00090 {
00091 typedef type_key_dispatch_tag tag;
00092 };
00093 }
00094 }
00095
00096 namespace viennagrid
00097 {
00098
00103 template <long dim>
00104 struct boundary_setter
00105 {
00107 template <typename FacetType, typename KeyType>
00108 static void apply(FacetType const & facet, KeyType const & key, full_handling_tag)
00109 {
00110 typedef typename FacetType::config_type ConfigType;
00111 typedef typename ConfigType::cell_tag CellTag;
00112
00113 typedef typename viennagrid::result_of::const_ncell_range<FacetType, dim>::type ElementOnFacetRange;
00114 typedef typename result_of::iterator<ElementOnFacetRange>::type ElementOnFacetIterator;
00115
00116 ElementOnFacetRange eof_container = ncells<dim>(facet);
00117 for (ElementOnFacetIterator eofit = eof_container.begin();
00118 eofit != eof_container.end();
00119 ++eofit)
00120 {
00121 viennadata::access<KeyType, bool>(key)(*eofit) = true;
00122 }
00123
00124
00125 boundary_setter<dim - 1>::apply(facet,
00126 key,
00127 typename viennagrid::result_of::bndcell_handling<ConfigType, CellTag, dim-1>::type()
00128 );
00129 }
00130
00132 template <typename FacetType, typename KeyType>
00133 static void apply(FacetType const & facet, KeyType const & key, no_handling_tag)
00134 {
00135 typedef typename FacetType::config_type ConfigType;
00136 typedef typename ConfigType::cell_tag CellTag;
00137
00138
00139 boundary_setter<dim - 1>::apply(facet,
00140 key,
00141 typename viennagrid::result_of::bndcell_handling<ConfigType, CellTag, dim-1>::type()
00142 );
00143 }
00144
00145 };
00146
00147
00149 template <>
00150 struct boundary_setter< -1 >
00151 {
00152 template <typename FacetType, typename KeyType, typename HandlingTag>
00153 static void apply(FacetType const & facet, KeyType const & key, HandlingTag)
00154 {
00155 }
00156 };
00157
00159 template <typename DomainSegmentType, typename KeyType>
00160 void detect_boundary_impl(DomainSegmentType const & seg, KeyType const & key, no_handling_tag)
00161 {
00162 typedef typename DomainSegmentType::ERROR_CANNOT_DETECT_BOUNDARY_BECAUSE_FACETS_ARE_DISABLED error_type;
00163 }
00164
00166 template <typename DomainSegmentType, typename KeyType>
00167 void detect_boundary_impl(DomainSegmentType const & seg, KeyType const & key, full_handling_tag)
00168 {
00169 typedef typename DomainSegmentType::config_type ConfigType;
00170 typedef typename ConfigType::cell_tag CellTag;
00171 typedef typename viennagrid::result_of::ncell<ConfigType, CellTag::dim-1>::type FacetType;
00172 typedef typename viennagrid::result_of::ncell<ConfigType, CellTag::dim>::type CellType;
00173
00174 typedef typename viennagrid::result_of::const_ncell_range<DomainSegmentType, CellTag::dim-1>::type FacetRange;
00175 typedef typename viennagrid::result_of::iterator<FacetRange>::type FacetIterator;
00176
00177 typedef typename viennagrid::result_of::const_ncell_range<DomainSegmentType, CellTag::dim>::type CellRange;
00178 typedef typename viennagrid::result_of::iterator<CellRange>::type CellIterator;
00179
00180 typedef typename viennagrid::result_of::const_ncell_range<CellType, CellTag::dim-1>::type FacetOnCellRange;
00181 typedef typename viennagrid::result_of::iterator<FacetOnCellRange>::type FacetOnCellIterator;
00182
00183
00184 CellRange cells = viennagrid::ncells<CellTag::dim>(seg);
00185 for (CellIterator cit = cells.begin();
00186 cit != cells.end();
00187 ++cit)
00188 {
00189 FacetOnCellRange facets_on_cell = ncells<CellTag::dim-1>(*cit);
00190 for (FacetOnCellIterator focit = facets_on_cell.begin();
00191 focit != facets_on_cell.end();
00192 ++focit)
00193 {
00194 bool * data_ptr = viennadata::find<KeyType, bool>(key)(*focit);
00195 if (data_ptr == NULL)
00196 {
00197 viennadata::access<KeyType, bool>(key)(*focit) = true;
00198 }
00199 else
00200 {
00201 if (*data_ptr == false)
00202 *data_ptr = true;
00203 else
00204 viennadata::erase<KeyType, bool>(key)(*focit);
00205 }
00206 }
00207 }
00208
00209
00210 FacetRange facets = viennagrid::ncells<CellTag::dim-1>(seg);
00211 for (FacetIterator fit = facets.begin();
00212 fit != facets.end();
00213 ++fit)
00214 {
00215 if (viennadata::find<KeyType, bool>(key)(*fit) != NULL)
00216 {
00217 if (viennadata::access<KeyType, bool>(key)(*fit) == true)
00218 boundary_setter<CellTag::dim-2>::apply(*fit,
00219 key,
00220 typename viennagrid::result_of::bndcell_handling<ConfigType, CellTag, CellTag::dim-2>::type()
00221 );
00222 }
00223 }
00224 }
00225
00226
00227
00235 template <typename DomainSegmentType, typename KeyType>
00236 void detect_boundary(DomainSegmentType const & segment, KeyType const & key)
00237 {
00238 typedef typename DomainSegmentType::config_type ConfigType;
00239 typedef typename ConfigType::cell_tag CellTag;
00240 typedef typename result_of::domain<ConfigType>::type DomainType;
00241 typedef typename result_of::bndcell_handling<ConfigType, DomainType,
00242 CellTag::dim-1>::type HandlingTag;
00243
00244 if (viennadata::access<KeyType, bool>(key)(segment) == false)
00245 {
00246 detect_boundary_impl(segment, key, HandlingTag());
00247 viennadata::access<KeyType, bool>(key)(segment) = true;
00248 }
00249 }
00250
00251
00257 template <typename ConfigType, typename ElementTag>
00258 bool is_boundary(element_t<ConfigType, ElementTag> const & el,
00259 domain_t<ConfigType> const & domain)
00260 {
00261 typedef boundary_key<domain_t<ConfigType> > BoundaryKey;
00262
00263 detect_boundary(domain, BoundaryKey());
00264 if (viennadata::find<BoundaryKey, bool>()(el) != NULL)
00265 {
00266 return viennadata::access<BoundaryKey, bool>()(el);
00267 }
00268 return false;
00269 }
00270
00276 template <typename ConfigType, typename ElementTag>
00277 bool is_boundary(element_t<ConfigType, ElementTag> const & el,
00278 segment_t<ConfigType> const & segment)
00279 {
00280 typedef boundary_key<segment_t<ConfigType> > BoundaryKey;
00281
00282 BoundaryKey key(segment.id());
00283 detect_boundary(segment, key);
00284
00285 if (viennadata::find<BoundaryKey, bool>(key)(el) != NULL)
00286 {
00287 return viennadata::access<BoundaryKey, bool>(key)(el);
00288 }
00289 return false;
00290 }
00291
00292 }
00293
00294 #endif