1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 // vi: set et ts=4 sw=2 sts=2: 3 #ifndef DUNE_GRID_COMMON_PARTITIONSET_HH 4 #define DUNE_GRID_COMMON_PARTITIONSET_HH 5 6 #include <dune/common/keywords.hh> 7 #include <dune/common/typetraits.hh> 8 #include <dune/grid/common/gridenums.hh> 9 10 namespace Dune { 11 12 /** 13 * \addtogroup GIRelatedTypes 14 * \{ 15 */ 16 17 namespace { 18 19 // Simple TMP to deduce partition iterator type from set of partitions. 20 template<unsigned int partitions> 21 struct derive_partition_iterator_type 22 { 23 // We did not match any specialization, bail out... 24 static_assert(AlwaysFalse<std::integral_constant<unsigned int,partitions> >::value, 25 "There is no partition iterator for this combination of entity partitions"); 26 }; 27 28 29 // specializations of derive_partition_iterator_type for existing PartitionIteratorTypes 30 31 template<> 32 struct derive_partition_iterator_type< 33 (1 << InteriorEntity) 34 > 35 : public std::integral_constant<PartitionIteratorType,Interior_Partition> 36 {}; 37 38 template<> 39 struct derive_partition_iterator_type< 40 (1 << InteriorEntity) | 41 (1 << BorderEntity) 42 > 43 : public std::integral_constant<PartitionIteratorType,InteriorBorder_Partition> 44 {}; 45 46 template<> 47 struct derive_partition_iterator_type< 48 (1 << InteriorEntity) | 49 (1 << BorderEntity) | 50 (1 << OverlapEntity) 51 > 52 : public std::integral_constant<PartitionIteratorType,Overlap_Partition> 53 {}; 54 55 template<> 56 struct derive_partition_iterator_type< 57 (1 << InteriorEntity) | 58 (1 << BorderEntity) | 59 (1 << OverlapEntity) | 60 (1 << FrontEntity) 61 > 62 : public std::integral_constant<PartitionIteratorType,OverlapFront_Partition> 63 {}; 64 65 template<> 66 struct derive_partition_iterator_type< 67 (1 << InteriorEntity) | 68 (1 << BorderEntity) | 69 (1 << OverlapEntity) | 70 (1 << FrontEntity) | 71 (1 << GhostEntity) 72 > 73 : public std::integral_constant<PartitionIteratorType,All_Partition> 74 {}; 75 76 template<> 77 struct derive_partition_iterator_type< 78 (1 << GhostEntity) 79 > 80 : public std::integral_constant<PartitionIteratorType,Ghost_Partition> 81 {}; 82 83 84 // Simple TMP to deduce set of partitions from partition iterator type. 85 86 template<PartitionIteratorType pitype> 87 struct derive_partition_set; 88 89 90 // specializations of derive_partition_set for existing PartitionIteratorTypes 91 92 template<> 93 struct derive_partition_set<Interior_Partition> 94 : std::integral_constant<unsigned int, (1 << InteriorEntity)> 95 {}; 96 97 template<> 98 struct derive_partition_set<InteriorBorder_Partition> 99 : std::integral_constant<unsigned int, (1 << InteriorEntity) | (1 << BorderEntity)> 100 {}; 101 102 template<> 103 struct derive_partition_set<Overlap_Partition> 104 : std::integral_constant<unsigned int, (1 << InteriorEntity) | (1 << BorderEntity) | (1 << OverlapEntity)> 105 {}; 106 107 template<> 108 struct derive_partition_set<OverlapFront_Partition> 109 : std::integral_constant<unsigned int, (1 << InteriorEntity) | (1 << BorderEntity) | (1 << OverlapEntity) | (1 << FrontEntity)> 110 {}; 111 112 template<> 113 struct derive_partition_set<Ghost_Partition> 114 : std::integral_constant<unsigned int, (1 << GhostEntity)> 115 {}; 116 117 template<> 118 struct derive_partition_set<All_Partition> 119 : std::integral_constant<unsigned int, (1 << InteriorEntity) | (1 << BorderEntity) | (1 << OverlapEntity) | (1 << FrontEntity) | (1 << GhostEntity)> 120 {}; 121 122 } // anonymous namespace 123 124 125 //! A set of PartitionType values. 126 /** 127 * PartitionSet contains a set of PartitionType values fixed at compile time. The contents 128 * of the set is encoded in the template parameter partitions, but the exact semantics are 129 * an implementation detail. PartitionSets can be combined by adding them up. They also support 130 * removing partitions by subtracting them. 131 * 132 * \tparam partitions Implementation-defined representation of the partition set. 133 */ 134 template<unsigned int partitions> 135 struct PartitionSet 136 { 137 //! \private The actual representation should not be used outside of the implementation. 138 static constexpr unsigned int value = partitions; 139 140 141 //! Returns a new PartitionSet that also contains the partitions in set. 142 template<unsigned int p> 143 struct PartitionSet<partitions | p> operator +Dune::PartitionSet144 constexpr operator+(const PartitionSet<p>&) const 145 { 146 return PartitionSet<partitions | p>(); 147 } 148 149 //! Returns a new PartitionSet that does not contain the partitions in set. 150 template<unsigned int p> 151 struct PartitionSet<partitions & ~p> operator -Dune::PartitionSet152 constexpr operator-(const PartitionSet<p>&) const 153 { 154 return PartitionSet<partitions & ~p>(); 155 } 156 157 //! Writes the PartitionSet to an output stream. operator <<(std::ostream & os,const PartitionSet &)158 friend std::ostream& operator<<(std::ostream& os, const PartitionSet&) 159 { 160 unsigned int set = partitions; 161 os << "partition set {"; 162 bool first = true; 163 for (unsigned int p = 0; set; set &= ~(1 << p++)) 164 { 165 if (!(set & (1 << p))) 166 continue; 167 if (!first) 168 os << ","; 169 first = false; 170 os << static_cast<PartitionType>(p); 171 } 172 os << "}"; 173 return os; 174 } 175 176 //! Returns the PartitionIteratorType that can be used to iterate over the partitions in the set. 177 /** 178 * 179 * \throws raises a static assertion if the partitions do not correspond to a valid PartitionIteratorType. 180 */ partitionIteratorDune::PartitionSet181 static constexpr PartitionIteratorType partitionIterator() 182 { 183 return derive_partition_iterator_type<partitions>::value; 184 } 185 186 //! Tests whether the given PartitionType is contained in this set. containsDune::PartitionSet187 static constexpr bool contains(PartitionType pt) 188 { 189 return partitions & (1 << pt); 190 } 191 192 //! Tests whether the given PartitionSet is contained in this set. 193 template<unsigned int contained_partitions> containsDune::PartitionSet194 static constexpr bool contains(PartitionSet<contained_partitions>) 195 { 196 return (partitions & contained_partitions) == contained_partitions; 197 } 198 199 //! Tests whether two PartitionsSet are equal. 200 template<unsigned int p2> operator ==Dune::PartitionSet201 constexpr bool operator==(PartitionSet<p2>) const 202 { 203 return partitions == p2; 204 } 205 206 //! Tests whether two PartitionsSet are not equal. 207 template<unsigned int p2> operator !=Dune::PartitionSet208 constexpr bool operator!=(PartitionSet<p2>) const 209 { 210 return partitions != p2; 211 } 212 213 }; 214 215 //! Creates a PartitionSet for the given PartitionType. 216 /** 217 * \related PartitionSet 218 */ 219 template<PartitionType p> partitionSet()220 PartitionSet<(1 << p)> partitionSet() 221 { 222 return PartitionSet<(1 << p)>(); 223 } 224 225 /** 226 * \brief creates a PartitionSet for the given PartitionIteratorType 227 * \related PartitionSet 228 */ 229 template<PartitionIteratorType pitype> partitionSet()230 constexpr PartitionSet<derive_partition_set<pitype>::value> partitionSet() 231 { 232 return PartitionSet<derive_partition_set<pitype>::value>(); 233 } 234 235 //! Predefined PartitionSets for commonly used combinations of parallel grid PartitionTypes. 236 namespace Partitions { 237 238 239 #ifdef DOXYGEN 240 241 //! Type of PartitionSet for the interior partition. 242 typedef PartitionSet<...> Interior; 243 244 //! Type of PartitionSet for the border partition. 245 typedef PartitionSet<...> Border; 246 247 //! Type of PartitionSet for the overlap partition. 248 typedef PartitionSet<...> Overlap; 249 250 //! Type of PartitionSet for the front partition. 251 typedef PartitionSet<...> Front; 252 253 //! Type of PartitionSet for the ghost partition. 254 typedef PartitionSet<...> Ghost; 255 256 //! Type of PartitionSet for the interior and border partitions. 257 typedef PartitionSet<...> InteriorBorder; 258 259 //! Type of PartitionSet for the interior, border and overlap partitions. 260 typedef PartitionSet<...> InteriorBorderOverlap; 261 262 //! Type of PartitionSet for the interior, border, overlap and front partitions. 263 typedef PartitionSet<...> InteriorBorderOverlapFront; 264 265 //! Type of PartitionSet for all partitions. 266 typedef PartitionSet<...> All; 267 268 269 //! PartitionSet for the interior partition. 270 constexpr Interior interior; 271 272 //! PartitionSet for the border partition. 273 constexpr Border border; 274 275 //! PartitionSet for the overlap partition. 276 constexpr Overlap overlap; 277 278 //! PartitionSet for the front partition. 279 constexpr Front front; 280 281 //! PartitionSet for the ghost partition. 282 constexpr Ghost ghost; 283 284 //! PartitionSet for the interior and border partitions. 285 constexpr InteriorBorder interiorBorder; 286 287 //! PartitionSet for the interior, border and overlap partitions. 288 constexpr InteriorBorderOverlap interiorBorderOverlap; 289 290 //! PartitionSet for the interior, border, overlap and front partitions. 291 constexpr InteriorBorderOverlapFront interiorBorderOverlapFront; 292 293 //! PartitionSet for all partitions. 294 constexpr All all; 295 296 #else // DOXYGEN 297 298 // First declare the types and objects for individual partitions 299 300 typedef decltype(partitionSet<InteriorEntity>()) Interior; 301 typedef decltype(partitionSet<BorderEntity>()) Border; 302 typedef decltype(partitionSet<OverlapEntity>()) Overlap; 303 typedef decltype(partitionSet<FrontEntity>()) Front; 304 typedef decltype(partitionSet<GhostEntity>()) Ghost; 305 306 #ifndef __cpp_inline_variables 307 namespace { 308 #endif 309 310 // place global objects in anonymous namespace to ensure that visibility is 311 // restricted to the current translation unit, making it easier for the compiler 312 // to eliminate the actual objects and to avoid linking problems 313 314 DUNE_INLINE_VARIABLE constexpr Interior interior = {}; 315 DUNE_INLINE_VARIABLE constexpr Border border = {}; 316 DUNE_INLINE_VARIABLE constexpr Overlap overlap = {}; 317 DUNE_INLINE_VARIABLE constexpr Front front = {}; 318 DUNE_INLINE_VARIABLE constexpr Ghost ghost = {}; 319 320 #ifndef __cpp_inline_variables 321 } 322 #endif 323 324 // Now we can declare the partition sets that are a result of combining partitions 325 326 typedef decltype(interior + border) InteriorBorder; 327 typedef decltype(interior + border + overlap) InteriorBorderOverlap; 328 typedef decltype(interior + border + overlap + front) InteriorBorderOverlapFront; 329 typedef decltype(interior + border + overlap + front + ghost) All; 330 331 #ifndef __cpp_inline_variables 332 namespace { 333 #endif 334 335 // again, place the global objects in an anonymous namespace 336 337 DUNE_INLINE_VARIABLE constexpr InteriorBorder interiorBorder = {}; 338 DUNE_INLINE_VARIABLE constexpr InteriorBorderOverlap interiorBorderOverlap = {}; 339 DUNE_INLINE_VARIABLE constexpr InteriorBorderOverlapFront interiorBorderOverlapFront = {}; 340 DUNE_INLINE_VARIABLE constexpr All all = {}; 341 342 #ifndef __cpp_inline_variables 343 } 344 #endif 345 346 #endif // DOXYGEN 347 348 } // namespace Partitions 349 350 /** 351 * \} group Parallel Grid Partitions 352 */ 353 354 } // namespace Dune 355 356 #endif // DUNE_GRID_COMMON_PARTITIONSET_HH 357