The Refinement system allows to temporarily refine a grid or single entities without changing the grid itself. You may want to do this because you want to write your data to a file and have to do subsampling, but want to continue the calculation with the unmodified grid afterwards.
What Refinement can do for you
For a given geometry type and number of refined intervals, Refinement will
assign consecutive integer indices starting at 0 to each subvertex,
assign consecutive integer indices starting at 0 to each subelement,
calculate the coordinates of the subvertices for you,
calculate subvertex-indices of the corners of the subelements for you.
The geometry type of the refined entity and of the subelements may be different, for example you can refine a quadrilateral but get subelements which are triangles.
Currently the following geometry types are supported:
hypercubes (quadrilaterals, hexahedrons),
simplices (triangles, tetrahedrons),
triangulating hypercubes into simplices (quadrilaterals -> triangles, hexahedrons -> tetrahedrons).
What Refinement can't do for you
Refinement does not actually subsample your data, it only tells you where to subsample your data.
The geometry types need to be known at compile time. See VirtualRefinement if you need to calculate the right geometry type at run time.
No Refinement implementations for anything besides hypercubes and simplices have been written yet.
The user interface
template<unsigned topologyId, class CoordType,
unsigned coerceToId, int dimension_>
class StaticRefinement
{
public:
constexprstaticint dimension = dimension_;
template<int codimension>
struct codim
{
class SubEntityIterator;
};
typedef ImplementationDefined VertexIterator; // These are aliases for codim<codim>::SubEntityIterator
The Iterators can do all the usual things that Iterators can do, except dereferencing. In addition, to do something useful, they support some additional methods:
template<unsigned topologyId, class CoordType, unsigned coerceToId, int dimension>
class VertexIterator
{
public:
typedef ImplementationDefined Refinement;
int index() const;
Refinement::CoordVector coords() const;
}
template<unsigned topologyId, class CoordType, unsigned coerceToId, int dimension>
class ElementIterator
{
public:
typedef ImplementationDefined Refinement;
int index() const;
// Coords of the center of mass of the element
Refinement::CoordVector coords() const;
Refinement::IndexVector vertexIndices() const;
}
How to use it
Either use VirtualRefinement, or if you don't want to do that, read on.
// Include the necessary files
#include <dune/grid/common/refinement.hh>
// If you know that you are only ever going to need one refinement
// backend, you can include the corresponding file directly:
The Refinement system gives this guarantee (besides conforming to the above interface:
The indices of the subvertices and subelement start at 0 and are consecutive.
Implementing a new Refinement type
If you want to write a Refinement implementation for a particular geometry type, e.g. SquaringTheCircle (or a particular set of geometry types) here is how:
create a file refinement/squaringthecircle.cc and #include "base.cc". Your file will be included by others, so don't forget to protect against double inclusion.
implement a class (or template class) RefinementImp conforming exactly to the user interface above.
put it (and it's helper stuff as appropriate) into it's own namespace Dune::RefinementImp::SquaringTheCircle.
define the mapping of topologyId, CoordType and coerceToId to your implementation by specialising template struct RefinementImp::Traits. It should look like this:
This namespace contains the implementation of Refinement.
Definition base.cc:29
If you implement a template class, you have to specialise struct RefinementImp::Traits for every possible combination of topologyId and coerceToId that your implementation supports.
#include "refinement/squaringthecircle.cc" from refinement.hh.
This is enough to integrate your implementation into the Refinement system. You probably want to include it into VirtualRefinement also.
Namespaces
The (non-virtual) Refinement system is organized in the following way into namespaces:
Layer 0 declares struct RefinementImp::Traits<topologyId, CoordType, coerceToId, dim>. It's member typedef Imp tells which Refinement implementation to use for a given topologyId (and CoordType). It is located in refinementbase.cc.
Layer 1 defines RefinementImp::XXX::RefinementImp. It implements the Refinements for each topologyId, coerceToId (and CoordType). Also in this layer are the definitions of struct RefinementImp::Traits. This layer is located in refinementXXX.cc.
Layer 2 puts it all together. It defines class StaticRefinement<topologyId, CoordType, coerceToId, dim> by deriving from the corresponding RefinementImp. It is located in refinementbase.cc.
There is a dummy layer 2.5 which simply includes all the refinementXXX.cc files. It is located in refinement.cc.