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