1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 
4 #ifndef DUNE_GEOMETRY_VIRTUALREFINEMENT_CC
5 #define DUNE_GEOMETRY_VIRTUALREFINEMENT_CC
6 
7 /*!
8  * \file
9  * \brief This file contains the virtual wrapper around refinement.
10  */
11 
12 #include <cassert>
13 #include <typeinfo>
14 
15 #include <dune/common/exceptions.hh>
16 #include <dune/common/fvector.hh>
17 #include <dune/common/iteratorfacades.hh>
18 
19 #include "type.hh"
20 #include "refinement.hh"
21 
22 namespace Dune
23 {
24   // //////////////////////////////////////////
25   //
26   // The virtual base class and its iterators
27   //
28 
29   //
30   // Refinement
31   //
32 
33   template<int dimension, class CoordType>
34   typename VirtualRefinement<dimension, CoordType>::VertexIterator
35   VirtualRefinement<dimension, CoordType>::
vBegin(Dune::RefinementIntervals tag) const36   vBegin(Dune::RefinementIntervals tag) const
37   {
38     return VertexIterator(vBeginBack(tag));
39   }
40 
41   template<int dimension, class CoordType>
42   typename VirtualRefinement<dimension, CoordType>::VertexIterator
43   VirtualRefinement<dimension, CoordType>::
vEnd(Dune::RefinementIntervals tag) const44   vEnd(Dune::RefinementIntervals tag) const
45   {
46     return VertexIterator(vEndBack(tag));
47   }
48 
49   template<int dimension, class CoordType>
50   typename VirtualRefinement<dimension, CoordType>::ElementIterator
51   VirtualRefinement<dimension, CoordType>::
eBegin(Dune::RefinementIntervals tag) const52   eBegin(Dune::RefinementIntervals tag) const
53   {
54     return ElementIterator(eBeginBack(tag));
55   }
56 
57   template<int dimension, class CoordType>
58   typename VirtualRefinement<dimension, CoordType>::ElementIterator
59   VirtualRefinement<dimension, CoordType>::
eEnd(Dune::RefinementIntervals tag) const60   eEnd(Dune::RefinementIntervals tag) const
61   {
62     return ElementIterator(eEndBack(tag));
63   }
64 
65   //
66   // The iterators
67   //
68 
69   template<int dimension, class CoordType, int codimension>
70   class VirtualRefinementSubEntityIteratorSpecial;
71 
72   // The iterator for vertices
73   template<int dimension, class CoordType>
74   class VirtualRefinementSubEntityIteratorSpecial<dimension, CoordType, dimension>
75   {};
76 
77   // The iterator for elements
78   template<int dimension, class CoordType>
79   class VirtualRefinementSubEntityIteratorSpecial<dimension, CoordType, 0>
80   {
81   public:
82     typedef VirtualRefinement<dimension, CoordType> Refinement;
83     typedef typename Refinement::template Codim<0>::SubEntityIterator Common;
84     typedef typename Refinement::IndexVector IndexVector;
85 
86     IndexVector vertexIndices() const;
87   };
88 
89   template<int dimension, class CoordType>
90   typename VirtualRefinementSubEntityIteratorSpecial<dimension, CoordType, 0>::IndexVector
91   VirtualRefinementSubEntityIteratorSpecial<dimension, CoordType, 0>::
vertexIndices() const92   vertexIndices() const
93   {
94     return static_cast<const Common *>(this)->backend->vertexIndices();
95   }
96 
97   // The iterator common stuff
98   template<int dimension, class CoordType>
99   template<int codimension>
100   class VirtualRefinement<dimension, CoordType>::Codim<codimension>::SubEntityIterator
101     : public ForwardIteratorFacade<typename VirtualRefinement<dimension, CoordType>::template Codim<codimension>::SubEntityIterator, int>,
102       public VirtualRefinementSubEntityIteratorSpecial<dimension, CoordType, codimension>
103   {
104   public:
105     typedef VirtualRefinement<dimension, CoordType> Refinement;
106     typedef typename Refinement::template Codim<codimension>::SubEntityIterator This;
107     typedef typename Refinement::template SubEntityIteratorBack<codimension> IteratorBack;
108     typedef typename Refinement::CoordVector CoordVector;
109 
110     SubEntityIterator(IteratorBack *backend);
111     SubEntityIterator(const This &other);
112     ~SubEntityIterator();
113 
114     This &operator=(const This &other);
115 
116     bool equals(const This &other) const;
117     void increment();
118 
119     int index() const;
120 
121     // If you simply use an unqualified CoordVector here g++-4.2 chokes
122     typename VirtualRefinement<dimension, CoordType>::template Codim<codimension>::SubEntityIterator::
123     CoordVector coords() const;
124   private:
125     friend class VirtualRefinementSubEntityIteratorSpecial<dimension, CoordType, codimension>;
126     IteratorBack *backend;
127   };
128 
129 #ifndef DOXYGEN
130   template<int dimension, class CoordType>
131   template<int codimension>
132   VirtualRefinement<dimension, CoordType>::Codim<codimension>::SubEntityIterator::
SubEntityIterator(IteratorBack * backend_)133   SubEntityIterator(IteratorBack *backend_)
134     : backend(backend_)
135   {}
136 
137   template<int dimension, class CoordType>
138   template<int codimension>
139   VirtualRefinement<dimension, CoordType>::Codim<codimension>::SubEntityIterator::
SubEntityIterator(const This & other)140   SubEntityIterator(const This &other)
141     : backend(other.backend->clone())
142   {}
143 
144   template<int dimension, class CoordType>
145   template<int codimension>
146   VirtualRefinement<dimension, CoordType>::Codim<codimension>::SubEntityIterator::
~SubEntityIterator()147   ~SubEntityIterator()
148   {
149     delete backend;
150   }
151 
152   template<int dimension, class CoordType>
153   template<int codimension>
154   typename VirtualRefinement<dimension, CoordType>::template Codim<codimension>::SubEntityIterator &
155   VirtualRefinement<dimension, CoordType>::Codim<codimension>::SubEntityIterator::
operator =(const This & other)156   operator=(const This &other)
157   {
158     delete backend;
159     backend = other.backend->clone();
160   }
161 
162   template<int dimension, class CoordType>
163   template<int codimension>
164   bool
165   VirtualRefinement<dimension, CoordType>::Codim<codimension>::SubEntityIterator::
equals(const This & other) const166   equals(const This &other) const
167   { return *backend == *(other.backend); }
168 
169   template<int dimension, class CoordType>
170   template<int codimension>
171   void
172   VirtualRefinement<dimension, CoordType>::Codim<codimension>::SubEntityIterator::
increment()173   increment()
174   {
175     ++*backend;
176   }
177 
178   template<int dimension, class CoordType>
179   template<int codimension>
180   int
181   VirtualRefinement<dimension, CoordType>::Codim<codimension>::SubEntityIterator::
index() const182   index() const
183   { return backend->index(); }
184 
185   template<int dimension, class CoordType>
186   template<int codimension>
187   typename VirtualRefinement<dimension, CoordType>::template Codim<codimension>::SubEntityIterator::CoordVector
188   VirtualRefinement<dimension, CoordType>::Codim<codimension>::SubEntityIterator::
coords() const189   coords() const
190   { return backend->coords(); }
191 #endif // DOXYGEN
192 
193   //
194   // The iterator backend
195   //
196 
197   template<int dimension, class CoordType, int codimension>
198   class VirtualRefinementSubEntityIteratorBackSpecial;
199 
200   // The iterator backend for vertices
201   template<int dimension, class CoordType>
202   class VirtualRefinementSubEntityIteratorBackSpecial<dimension, CoordType, dimension>
203   {
204   public:
205 
~VirtualRefinementSubEntityIteratorBackSpecial()206     virtual ~VirtualRefinementSubEntityIteratorBackSpecial()
207     {}
208   };
209 
210   // The iterator backend for elements
211   template<int dimension, class CoordType>
212   class VirtualRefinementSubEntityIteratorBackSpecial<dimension, CoordType, 0>
213   {
214   public:
215     typedef VirtualRefinement<dimension, CoordType> Refinement;
216     typedef typename Refinement::IndexVector IndexVector;
217 
218     virtual IndexVector vertexIndices() const = 0;
219 
~VirtualRefinementSubEntityIteratorBackSpecial()220     virtual ~VirtualRefinementSubEntityIteratorBackSpecial()
221     {}
222   };
223 
224   // The iterator backend common stuff
225   template<int dimension, class CoordType>
226   template<int codimension>
227   class VirtualRefinement<dimension, CoordType>::SubEntityIteratorBack
228     : public VirtualRefinementSubEntityIteratorBackSpecial<dimension, CoordType, codimension>
229   {
230   public:
231     typedef VirtualRefinement<dimension, CoordType> Refinement;
232     typedef typename Refinement::template SubEntityIteratorBack<codimension> This;
233     typedef typename Refinement::CoordVector CoordVector;
234 
~SubEntityIteratorBack()235     virtual ~SubEntityIteratorBack() {}
236 
237     virtual This *clone() const = 0;
238 
239     virtual bool operator==(const This &other) const = 0;
240     virtual This &operator++() = 0;
241 
242     virtual int index() const = 0;
243     virtual CoordVector coords() const = 0;
244   };
245 
246   // /////////////////////////////////////////////////
247   //
248   // The derived classes and their iterator backends
249   //
250 
251   //
252   // The refinement implementation
253   //
254 
255   template<unsigned topologyId, class CoordType,
256       unsigned coerceToId, int dimension>
257   class VirtualRefinementImp
258     : public Dune::VirtualRefinement<dimension, CoordType>
259   {
260   public:
261     typedef Dune::StaticRefinement<topologyId, CoordType, coerceToId, dimension> StaticRefinement;
262     typedef Dune::VirtualRefinement<dimension, CoordType> VirtualRefinement;
263 
264     template<int codimension>
265     class SubEntityIteratorBack;
266 
267     int nVertices(Dune::RefinementIntervals tag) const;
268 
269     int nElements(Dune::RefinementIntervals tag) const;
270 
271     static VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension> &instance();
272   private:
VirtualRefinementImp()273     VirtualRefinementImp() {}
274 
275     typename VirtualRefinement::VertexIteratorBack *vBeginBack(Dune::RefinementIntervals tag) const;
276     typename VirtualRefinement::VertexIteratorBack *vEndBack(Dune::RefinementIntervals tag) const;
277     typename VirtualRefinement::ElementIteratorBack *eBeginBack(Dune::RefinementIntervals tag) const;
278     typename VirtualRefinement::ElementIteratorBack *eEndBack(Dune::RefinementIntervals tag) const;
279   };
280 
281   template<unsigned topologyId, class CoordType,
282       unsigned coerceToId, int dimension>
283   VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension> &
instance()284   VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::instance()
285   {
286     static VirtualRefinementImp instance_{};
287     return instance_;
288   }
289 
290     template<unsigned topologyId, class CoordType,
291       unsigned coerceToId, int dimension>
292   int VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::
nVertices(Dune::RefinementIntervals tag) const293   nVertices(Dune::RefinementIntervals tag) const
294   {
295     return StaticRefinement::nVertices(tag);
296   }
297 
298   template<unsigned topologyId, class CoordType,
299       unsigned coerceToId, int dimension>
300   typename VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::VirtualRefinement::VertexIteratorBack *
301   VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::
vBeginBack(Dune::RefinementIntervals tag) const302   vBeginBack(Dune::RefinementIntervals tag) const
303   {
304     return new SubEntityIteratorBack<dimension>(StaticRefinement::vBegin(tag));
305   }
306 
307   template<unsigned topologyId, class CoordType,
308       unsigned coerceToId, int dimension>
309   typename VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::VirtualRefinement::VertexIteratorBack *
310   VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::
vEndBack(Dune::RefinementIntervals tag) const311   vEndBack(Dune::RefinementIntervals tag) const
312   {
313     return new SubEntityIteratorBack<dimension>(StaticRefinement::vEnd(tag));
314   }
315 
316   template<unsigned topologyId, class CoordType,
317       unsigned coerceToId, int dimension>
nElements(Dune::RefinementIntervals tag) const318   int VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::nElements(Dune::RefinementIntervals tag) const
319   {
320     return StaticRefinement::nElements(tag);
321   }
322 
323   template<unsigned topologyId, class CoordType,
324       unsigned coerceToId, int dimension>
325   typename VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::VirtualRefinement::ElementIteratorBack *
326   VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::
eBeginBack(Dune::RefinementIntervals tag) const327   eBeginBack(Dune::RefinementIntervals tag) const
328   {
329     return new SubEntityIteratorBack<0>(StaticRefinement::eBegin(tag));
330   }
331 
332   template<unsigned topologyId, class CoordType,
333       unsigned coerceToId, int dimension>
334   typename VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::VirtualRefinement::ElementIteratorBack *
335   VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::
eEndBack(Dune::RefinementIntervals tag) const336   eEndBack(Dune::RefinementIntervals tag) const
337   {
338     return new SubEntityIteratorBack<0>(StaticRefinement::eEnd(tag));
339   }
340 
341   //
342   // The iterator backend implementation
343   //
344 
345   // The iterator backend implementation specialties
346   template<unsigned topologyId, class CoordType,
347       unsigned coerceToId, int dimension, int codimension>
348   class VirtualRefinementImpSubEntityIteratorBackSpecial;
349 
350   // The iterator backend implementation specialties for vertices
351   template<unsigned topologyId, class CoordType,
352       unsigned coerceToId, int dimension>
353   class VirtualRefinementImpSubEntityIteratorBackSpecial<topologyId, CoordType, coerceToId, dimension, dimension>
354     : public VirtualRefinement<dimension, CoordType>::template SubEntityIteratorBack<dimension>
355   {};
356 
357   // The iterator backend implementation specialties for elements
358 
359   template<unsigned topologyId, class CoordType,
360       unsigned coerceToId, int dimension>
361   class VirtualRefinementImpSubEntityIteratorBackSpecial<topologyId, CoordType, coerceToId, dimension, 0>
362     : public VirtualRefinement<dimension, CoordType>::template SubEntityIteratorBack<0>
363   {
364   public:
365     typedef Dune::VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension> VirtualRefinementImp;
366     typedef typename VirtualRefinementImp::template SubEntityIteratorBack<0> Common;
367     typedef typename VirtualRefinementImp::StaticRefinement StaticRefinement;
368     typedef VirtualRefinement<dimension, CoordType> RefinementBase;
369     typedef typename RefinementBase::IndexVector IndexVector;
370 
371     IndexVector vertexIndices() const;
372   };
373 
374   template<unsigned topologyId, class CoordType,
375       unsigned coerceToId, int dimension>
376   typename VirtualRefinementImpSubEntityIteratorBackSpecial<topologyId, CoordType, coerceToId, dimension, 0>::IndexVector
377   VirtualRefinementImpSubEntityIteratorBackSpecial<topologyId, CoordType, coerceToId, dimension, 0>::
vertexIndices() const378   vertexIndices() const
379   {
380     IndexVector vIndices;
381     vIndices.reserve(StaticRefinement::IndexVector::dimension);
382 
383     typename StaticRefinement::IndexVector sIndices = static_cast<const Common *>(this)->backend.vertexIndices();
384     for(int i = 0; i < StaticRefinement::IndexVector::dimension; ++i)
385       vIndices.push_back(sIndices[i]);
386     return vIndices;
387   }
388 
389   // The shared iterator backend implementation
390   template<unsigned topologyId, class CoordType,
391       unsigned coerceToId, int dimension>
392   template<int codimension>
393   class VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::SubEntityIteratorBack
394     : public VirtualRefinementImpSubEntityIteratorBackSpecial<topologyId, CoordType, coerceToId, dimension, codimension>
395   {
396   public:
397     typedef typename StaticRefinement::template Codim<codimension>::SubEntityIterator BackendIterator;
398     typedef typename VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::template SubEntityIteratorBack<codimension> This;
399     typedef typename VirtualRefinement::template SubEntityIteratorBack<codimension> Base;
400     typedef typename VirtualRefinement::CoordVector CoordVector;
401 
402     SubEntityIteratorBack(const BackendIterator &backend);
403     SubEntityIteratorBack(const This &other);
404 
405     Base *clone() const;
406 
407     bool operator==(const Base &other) const;
408     Base &operator++();
409 
410     int index() const;
411     CoordVector coords() const;
412 
413   private:
414     friend class VirtualRefinementImpSubEntityIteratorBackSpecial<topologyId, CoordType, coerceToId, dimension, codimension>;
415     BackendIterator backend;
416   };
417 
418   template<unsigned topologyId, class CoordType,
419       unsigned coerceToId, int dimension>
420   template<int codimension>
421   VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::SubEntityIteratorBack<codimension>::
SubEntityIteratorBack(const BackendIterator & backend_)422   SubEntityIteratorBack(const BackendIterator &backend_)
423     : backend(backend_)
424   {}
425 
426   template<unsigned topologyId, class CoordType,
427       unsigned coerceToId, int dimension>
428   template<int codimension>
429   VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::SubEntityIteratorBack<codimension>::
SubEntityIteratorBack(const This & other)430   SubEntityIteratorBack(const This &other)
431     : VirtualRefinementImpSubEntityIteratorBackSpecial<topologyId, CoordType, coerceToId, dimension, codimension>(other),
432       backend(other.backend)
433   {}
434 
435   template<unsigned topologyId, class CoordType, unsigned coerceToId, int dimension>
436   template<int codimension>
437   typename VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::template SubEntityIteratorBack<codimension>::Base *
438   VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::SubEntityIteratorBack<codimension>::
clone() const439   clone() const
440   { return new This(*this); }
441 
442   template<unsigned topologyId, class CoordType, unsigned coerceToId, int dimension>
443   template<int codimension>
444   bool
445   VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::SubEntityIteratorBack<codimension>::
operator ==(const Base & other) const446   operator==(const Base &other) const
447   {
448     try {
449       return backend == dynamic_cast<const This &>(other).backend;
450     }
451     catch(const std::bad_cast&)
452     {
453       return false;
454     }
455   }
456 
457   template<unsigned topologyId, class CoordType, unsigned coerceToId, int dimension>
458   template<int codimension>
459   typename VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::template SubEntityIteratorBack<codimension>::Base &
460   VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::SubEntityIteratorBack<codimension>::
operator ++()461   operator++()
462   {
463     ++backend;
464     return *this;
465   }
466 
467   template<unsigned topologyId, class CoordType, unsigned coerceToId, int dimension>
468   template<int codimension>
469   int
470   VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::SubEntityIteratorBack<codimension>::
index() const471   index() const
472   { return backend.index(); }
473 
474   template<unsigned topologyId, class CoordType, unsigned coerceToId, int dimension>
475   template<int codimension>
476   typename VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::template SubEntityIteratorBack<codimension>::CoordVector
477   VirtualRefinementImp<topologyId, CoordType, coerceToId, dimension>::SubEntityIteratorBack<codimension>::
coords() const478   coords() const
479   { return backend.coords(); }
480 
481   // ////////////////////////
482   //
483   // The refinement builder
484   //
485 
486   template<int dimension, class CoordType>
487   class RefinementBuilder;
488 
489   /*!
490    * \brief return a reference to the VirtualRefinement according to
491    *          the parameters
492    *
493    * \tparam dimension Dimension of the element to refine
494    * \tparam CoordType C++ type of the coordinates
495    *
496    * \throws NotImplemented There is no Refinement implementation for
497    *                        the specified parameters.
498    */
499   template<int dimension, class CoordType>
500   VirtualRefinement<dimension, CoordType> &
buildRefinement(GeometryType geometryType,GeometryType coerceTo)501   buildRefinement( //! geometry type of the refined element
502     GeometryType geometryType,
503     //! geometry type of the subelements
504     GeometryType coerceTo)
505   {
506     // Check that the user used valid geometry types
507     assert(geometryType.dim() == dimension && coerceTo.dim() == dimension);
508     return RefinementBuilder<dimension, CoordType>::build( geometryType.id(), coerceTo.id() );
509   }
510 
511   // In principle the trick with the class is no longer necessary,
512   // but I'm keeping it in here so it will be easier to specialize
513   // buildRefinement when someone implements pyramids and prisms
514   template<int dimension, class CoordType>
515   class RefinementBuilder
516   {
517   public:
518     static
519     VirtualRefinement<dimension, CoordType> &
build(unsigned topologyId,unsigned coerceToId)520     build(unsigned topologyId, unsigned coerceToId)
521     {
522       topologyId &= ~1;
523       coerceToId &= ~1;
524 
525       constexpr unsigned idSimplex = GeometryTypes::simplex(dimension).id() & ~1;
526       constexpr unsigned idCube = GeometryTypes::cube(dimension).id() & ~1;
527 
528       switch( topologyId )
529       {
530       //case GeometryType::simplex:
531       case idSimplex :
532         //switch( coerceTo )
533         switch( coerceToId )
534         {
535         //case GeometryType::simplex:
536         case idSimplex :
537           return VirtualRefinementImp< idSimplex, CoordType, idSimplex, dimension>::instance();
538         default :
539           break;
540         }
541         break;
542 
543       //case GeometryType::cube:
544       case idCube :
545         switch( coerceToId )
546         {
547         case idSimplex :
548           return VirtualRefinementImp< idCube, CoordType, idSimplex, dimension>::instance();
549         case idCube :
550           return VirtualRefinementImp< idCube, CoordType, idCube, dimension>::instance();
551         default :
552           break;
553         }
554         break;
555 
556       default :
557         break;
558       }
559       DUNE_THROW( NotImplemented, "No Refinement<" << topologyId << ", CoordType, "
560                                                    << coerceToId << " >.");
561     }
562   };
563 
564   template<class CoordType>
565   class RefinementBuilder<1, CoordType>
566   {
567     static const std::size_t dimension = 1;
568   public:
569     static
570     VirtualRefinement<dimension, CoordType> &
build(unsigned topologyId,unsigned coerceToId)571     build(unsigned topologyId, unsigned coerceToId)
572     {
573       topologyId &= ~1;
574       coerceToId &= ~1;
575 
576       constexpr unsigned idSimplex = GeometryTypes::simplex(dimension).id() & ~1;
577 
578       if (topologyId == 0 && coerceToId == 0)
579         return VirtualRefinementImp< idSimplex, CoordType, idSimplex, dimension>::instance();
580 
581       DUNE_THROW( NotImplemented, "No Refinement<" << topologyId << ", CoordType, "
582                                                    << coerceToId << " >.");
583     }
584   };
585 
586   template<class CoordType>
587   class RefinementBuilder<3, CoordType>
588   {
589     static const std::size_t dimension = 3;
590   public:
591     static
592     VirtualRefinement<dimension, CoordType> &
build(unsigned topologyId,unsigned coerceToId)593     build(unsigned topologyId, unsigned coerceToId)
594     {
595       topologyId &= ~1;
596       coerceToId &= ~1;
597 
598       constexpr unsigned idSimplex = GeometryTypes::simplex(dimension).id() & ~1;
599       constexpr unsigned idCube = GeometryTypes::cube(dimension).id() & ~1;
600       constexpr unsigned idPrism = GeometryTypes::prism.id() & ~1;
601       constexpr unsigned idPyramid = GeometryTypes::pyramid.id() & ~1;
602 
603       switch( topologyId )
604       {
605       //case GeometryType::simplex:
606       case idSimplex :
607         //switch( coerceTo )
608         switch( coerceToId )
609         {
610         //case GeometryType::simplex:
611         case idSimplex :
612           return VirtualRefinementImp< idSimplex, CoordType, idSimplex, dimension>::instance();
613         default :
614           break;
615         }
616         break;
617 
618       //case GeometryType::cube:
619       case idCube :
620         switch( coerceToId )
621         {
622         case idSimplex :
623           return VirtualRefinementImp< idCube, CoordType, idSimplex, dimension>::instance();
624         case idCube :
625           return VirtualRefinementImp< idCube, CoordType, idCube, dimension>::instance();
626         default :
627           break;
628         }
629         break;
630 
631       //case GeometryType::prism:
632       case idPrism :
633         switch( coerceToId )
634         {
635         case idSimplex :
636           return VirtualRefinementImp< idPrism, CoordType, idSimplex, dimension>::instance();
637         default :
638           break;
639         }
640         break;
641 
642       //case GeometryType::pyramid:
643       case idPyramid :
644         switch( coerceToId )
645         {
646         case idSimplex :
647           return VirtualRefinementImp< idPyramid, CoordType, idSimplex, dimension>::instance();
648         default :
649           break;
650         }
651         break;
652 
653       default :
654         break;
655       }
656       DUNE_THROW( NotImplemented, "No Refinement<" << topologyId << ", CoordType, "
657                                                    << coerceToId << " >.");
658     }
659   };
660 
661 } // namespace Dune
662 
663 #endif // DUNE_GEOMETRY_VIRTUALREFINEMENT_CC
664