Content  


Example: Iterators

The (possibly nested) iteration over mesh entities is one of the main ingredients for a plethora of algorithms. Consequently, ViennaGrid is designed such that these iterations can be carried out in a unified and flexible, yet efficient manner. In the following, it is shown how one can iterate over the elements of the full mesh, and how boundary and coboundary iterations are carried out.

A generic recipe for iterations with ViennaGrid is as follows:

  • Get the correct range type for the iteration. A range is similar to a container, but does not 'store' or 'own' the respective elements. The respective facility for iteration is the element_range metafunction, taking as first argument the type of the host element, and as second type the element type (or tag) over which to iterate.
  • Get the iterator type using the iterator metafunction.
  • Set up the range object by passing the enclosing mesh, segment, or element to the constructor.
  • Iterate over the range in the usual STL-like way.

In the following, the code for an iteration over all edges of a mesh is shown:

Iteration over all edges of the mesh
using namespace viennagrid;
 
// Step 1: Get the type of the range object as well as the iterator type
//         Here, we wish to iterate over all 1-dimensional elements (i.e. edges)
//         of the mesh with type 'MeshType'
typedef result_of::edge_range<MeshType>::type     EdgeRange;
typedef result_of::iterator<EdgeRange>::type      EdgeIterator;
 
// Step 2: Set up the range object. 
EdgeRange edges(mesh);  
 
// Step 3: Iterate over the range in the same way as for a STL container:
for (EdgeIterator eit = edges.begin();
                  eit != edges.end();
                ++eit)
{
  //Let's just print the edge: 
  std::cout << *eit << std::endl;
}

Using the same recipe, one can also iterate over all vertices (topologically 0-dimensional) of each edge. For the following snippet, the type of edge elements is taken as 'EdgeType':

Iteration over all vertices of all edges of the domain:
// First part same as before:
typedef result_of::edge_range<MeshType>::type    EdgeRange;
typedef result_of::iterator<EdgeRange>::type     EdgeIterator;
 
EdgeRange edges(mesh);  
for (EdgeIterator eit  = edges.begin();
                  eit != edges.end();
                ++eit)
{
  // Get the types:
  typedef result_of::edge<MeshType>::type                  EdgeType;
  typedef result_of::vertex_range<EdgeType>::type          VertexOnEdgeRange;
  typedef result_of::iterator<VertexOnEdgeRange>::type     VertexOnEdgeIterator;
  
  // Set up the range object and iterate in the STL way:
  VertexOnEdgeRange vertices(*eit);
  for (VertexOnEdgeIterator voeit  = vertices.begin();
                            voeit != vertices.end()
                          ++voeit)
  {
     //Let's just print each visited vertex:
     std::cout << *voeit << std::endl;
  }  
}

Conversely, one may also iterate over all topologically 2-dimensional elements (triangles or quadrilateral) of the mesh using the same pattern. In addition, one has to specify the enclosing cell complex for the iteration, because in multi-segment meshes some of the neighboring 2-elements might be in a different segment.

Iteration over all 2-elements of each edge
// First part same as before:
typedef result_of::edge_range<MeshType>::type    EdgeRange;
typedef result_of::iterator<EdgeRange>::type     EdgeIterator;
 
EdgeRange edges(mesh);  
for (EdgeIterator eit  = edges.begin();
                  eit != edges.end();
                ++eit)
{
  // Get the types: We refer to 2-dimensional objects as 'facet' in the following:
  typedef result_of::edge<MeshType>::type              EdgeType;
  typedef result_of::facet<MeshType>::type             FacetType;
  typedef result_of::coboundary_range<Mesh, EdgeType, FacetType>::type  FacetOnEdgeRange;
  typedef result_of::iterator<FacetOnEdgeRange>::type                FacetOnEdgeIterator;
  
  // Set up the range object and iterate over all facets in the mesh adjacent to the edge
  FaceOnEdgeRange facets(mesh, eit.handle());
  for (FaceOnEdgeIterator foeit  = facets.begin();
                          foeit != facets.end()
                        ++foeit)
  {
     //Let's just print each visited face:
     std::cout << *foeit << std::endl;
  }  
}

More details on dimension-independent traversal for mesh cells, how the above loops can be written in different ways, and on the underlying concepts can be found in the PDF manual.