]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Provide functions for C++11 range-based for loops. Document C++11 interaction.
authorWolfgang Bangerth <bangerth@math.tamu.edu>
Thu, 7 Aug 2014 15:56:53 +0000 (10:56 -0500)
committerWolfgang Bangerth <bangerth@math.tamu.edu>
Thu, 14 Aug 2014 13:45:28 +0000 (08:45 -0500)
This commit consists of the following individual commits:

Specifically, add Triangulation::cells(), Triangulation::active_cells() and
similar for the ones on a single level.

Fix up code to make it compile.

Fix one compile error.

Also provide similar functions for the two DoFHandler classes.

Augment documentation.

Update the specification of how we implement C++11 range-based for loops.

Link to the new documentation module (still coming up).

Document C++11 features and interaction.

12 files changed:
doc/doxygen/headers/c++11.h [new file with mode: 0644]
doc/doxygen/headers/std_cxx1x.h
doc/news/changes.h
include/deal.II/base/iterator_range.h [new file with mode: 0644]
include/deal.II/dofs/dof_handler.h
include/deal.II/grid/tria.h
include/deal.II/hp/dof_handler.h
source/dofs/dof_handler.cc
source/grid/tria.cc
source/hp/dof_handler.cc
tests/deal.II/range_based_for_tria.cc [new file with mode: 0644]
tests/deal.II/range_based_for_tria.with_cxx11=true.output [new file with mode: 0644]

diff --git a/doc/doxygen/headers/c++11.h b/doc/doxygen/headers/c++11.h
new file mode 100644 (file)
index 0000000..c543616
--- /dev/null
@@ -0,0 +1,103 @@
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+/**
+ * @defgroup CPP11 deal.II and the C++11 standard
+ *
+ * At present, deal.II only requires a compiler that conforms to the
+ * <a href="http://en.wikipedia.org/wiki/C%2B%2B#Standardization">C++98</a>
+ * standard and does not rely on compilers to either
+ * provide the features introduced in
+ * <a href="http://en.wikipedia.org/wiki/C%2B%2B03">C++03</a> or
+ * <a href="http://en.wikipedia.org/wiki/C%2B%2B11">C++11</a>
+ * 
+ * That said, deal.II interfaces with C++11 in several ways as
+ * outlined below.
+ * 
+ * 
+ * <h3>Use of C++11 classes and substitution by BOOST</h3>
+ *
+ * deal.II makes use of many of the classes that were only
+ * added as part of C++11. This includes std::shared_ptr,
+ * std::function, std::bind, std::tuple and a number of others.
+ * Because we do not assume that the compiler actually supports
+ * C++11, there needs to be a way to ensure that these classes
+ * are available also for pre-C++11 compilers. This is done using
+ * the following approach:
+ *
+ * - We create a namespace std_cxx1x.
+ * - If the compiler supports C++11, we import the relevant classes
+ *   and functions into this namespace using statements such as
+ *   @code
+ *     namespace std_cxx1x {  using std::shared_ptr;  }
+ *   @endcode
+ * - If the compiler does not support C++11, if its support for
+ *   C++11 is incomplete, or if it is buggy, then we use as a fallback
+ *   the corresponding classes and functions provided by the
+ *   <a href="http://www.boost.org">BOOST library</a> through
+ *   statements such as
+ *   @code
+ *     namespace std_cxx1x {  using boost::shared_ptr;  }
+ *   @endcode
+ *
+ * Consequently, namespace std_cxx1x contains all of the symbols
+ * we require. The classes that can be used this way are obviously
+ * a subset of the intersection between C++11 and what BOOST provides.
+ *
+ *
+ * <h3>Support for C++11 range-based for loops</h3>
+ *
+ * C++11 provides many new core language features, such as
+ * rvalue references and move semantics, initialized lists, tuples,
+ * variadic templates and
+ * others. For a complete list, see  http://en.wikipedia.org/wiki/C++11 .
+ * We can not use most of these in deal.II itself because we cannot rely
+ * on compilers supporting them.
+ *
+ * However, this does not preclude users from using such features in their
+ * own applications if they can be reasonably sure that the compilers on
+ * all of the systems they will work on do support C++11. An example are
+ * <a href="http://en.wikipedia.org/wiki/C++11#Type_inference">automatically
+ * typed variables</a>.
+ *
+ * deal.II does provide some features that make programming simpler when using
+ * C++11. This is true, in particular, for
+ * <a href="http://en.wikipedia.org/wiki/C++11#Range-based_for_loop">range-based
+ * for loops</a>. deal.II-based codes often have many loops of the kind
+ * @code
+ *   Triangulation<dim> triangulation;
+ *   ...
+ *   typename Triangulation<dim>::active_cell_iterator
+ *     cell = triangulation.begin_active(),
+ *     endc = triangulation.end();
+ *   for (; cell!=endc; ++cell)
+ *     cell->set_refine_flag();
+ * @endcode
+ * Using C++11's range-based for loops, you can now write this as follows:
+ * @code
+ *   Triangulation<dim> triangulation;
+ *   ...
+ *   for (auto cell : triangulation.active_cell_iterators())
+ *     cell->set_refine_flag();
+ * @endcode
+ * This relies on functions such as Triangulation::active_cell_iterators(),
+ * and equivalents in the DoF handler classes,
+ * DoFHandler::active_cell_iterators(), hp::DoFHandler::active_cell_iterators().
+ * There are variants of these functions that provide iterator ranges
+ * for all cells (not just the active ones) and for cells on individual
+ * levels.
+ */
index 5cc44b5fc5bbb3e20d95566bfd7422d5b57b3202..02f038e2ea97d9660be555a22b44167725b1f4e9 100644 (file)
 
 
 /**
- * A namespace that contains a selection of classes and functions that will be part of the
- * next C++ standard (tentatively called C++1x) and that are currently
- * available via the <a href="http://www.boost.org/">BOOST</a> library. The
+ * A namespace that contains a selection of classes and functions that are part
+ * of the C++11 standard and that are also provided by the
+ * <a href="http://www.boost.org/">BOOST</a> library. The
  * elements that are available through the current namespace are either
  * imported from namespace <code>std</code> (if a compiler's library provides
  * them) or from namespace boost.
+ *
+ * For more information on the topic,
+ * see also @ref CPP11 "C++11 standard"
+ *
+ * @ingroup CPP11
  */
 namespace std_cxx1x
 {
index 469c185d1fc0d5cfb517693bb9b2fba2b77e75af..7631e8d60ea12cf5e1b636eee4c66aae6753d004 100644 (file)
@@ -97,7 +97,12 @@ inconvenience this causes.
 
 
 <ol>
-
+  <li> New: There is now a documentation module that describes
+  deal.II's support for and interaction with the
+  @ref CPP11 "C++11 standard".
+  <br>
+  (Wolfgang Bangerth, 2014/08/14)
+  </li>
 
   <li> New: Added FunctionManifold descritpion.
   <br>
@@ -110,7 +115,6 @@ inconvenience this causes.
   (Luca Heltai, 2014/08/07)
   </li>
 
-
   <li> New: Added CylindricalManifold descritpion.
   <br>
   This class allows refinement of cylindrical manifolds. It is a good
@@ -246,6 +250,19 @@ inconvenience this causes.
 <h3>Specific improvements</h3>
 
 <ol>
+  <li> New: To better support applications that want to use C++11's
+  <a href="http://en.wikipedia.org/wiki/C%2B%2B11#Range-based_for_loop">range-based
+  for loops</a>, there are now functions Triangulation::cell_iterators(),
+  Triangulation::all_cell_iterators() and similarly in classes DoFHandler
+  and hp::DoFHandler
+  that return a range object that can then be used in range-based for loops.
+  The underlying implementation uses the new IteratorRange class.
+  <br>
+  See the new @ref CPP11 "C++11" page for more information.
+  <br>
+  (Wolfgang Bangerth, 2014/08/07)
+  </li>
+
   <li> New: TrilinosWrappers::PreconditionAMG can now be initialized from an
   object of type Epetra_RowMatrix, which allows using it with more arbitrary
   matrix objects, including matrix-free methods.
diff --git a/include/deal.II/base/iterator_range.h b/include/deal.II/base/iterator_range.h
new file mode 100644 (file)
index 0000000..c752cc2
--- /dev/null
@@ -0,0 +1,334 @@
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#ifndef __deal2__iterator_range_h
+#define __deal2__iterator_range_h
+
+
+#include <deal.II/base/config.h>
+
+#include <iterator>
+
+
+DEAL_II_NAMESPACE_OPEN
+
+
+/**
+ * A class that is used to denote a collection of iterators that can
+ * be expressed in terms of a range of iterators characterized by a begin
+ * and an end iterator. As is common in C++, these ranges are specified as
+ * half open intervals defined by a begin iterator and a one-past-the-end
+ * iterator.
+ *
+ * The purpose of this class is so that classes such as Triangulation and
+ * DoFHandler can return ranges of cell iterators using an object of the
+ * current type from functions such as Triangulation::cells() and that such an
+ * object can then be used in a range-based for loop as supported by C++11,
+ * see also @ref CPP11 "C++11 standard".
+ *
+ * For example, such a loop could look like this if the goal is to set
+ * the user flag on every active cell:
+ * @code
+ *   Triangulation<dim> triangulation;
+ *   ...
+ *   for (auto cell : triangulation.active_cell_iterators())
+ *     cell->set_user_flag();
+ * @endcode
+ * In other words, the <code>cell</code> objects are iterators, and the
+ * range object returned by Triangulation::active_cell_iterators() and
+ * similar functions are conceptually thought of as <i>collections of
+ * iterators</i>.
+ *
+ * Of course, the class may also be used to denote other iterator
+ * ranges using different kinds of iterators into other containers.
+ *
+ *
+ * <h3>Class design: Motivation</h3>
+ *
+ * Informally, the way the C++11 standard describes
+ * <a href="http://en.wikipedia.org/wiki/C%2B%2B11#Range-based_for_loop">range-based
+ * for loops</a> works as follows: A <i>range-based for loop</i> of the form
+ * @code
+ *   Container c;
+ *   for (auto v : c)
+ *     statement;
+ * @endcode
+ * where <code>c</code> is a container or collection, is equivalent to the following
+ * loop:
+ * @code
+ *   Container c;
+ *   for (auto tmp=c.begin(); tmp!=c.end(); ++tmp)
+ *     {
+ *       auto v = *tmp;
+ *       statement;
+ *     }
+ * @endcode
+ * In other words, the compiler introduces a temporary variable that <i>iterates</i>
+ * over the elements of the container or collection, and the original variable
+ * <code>v</code> that appeared in the range-based for loop represents the
+ * <i>dereferenced</i> state of these iterators -- in other words, the
+ * <i>elements</i> of the collection.
+ *
+ * In the context of loops over cells, we typically want to retain the fact that
+ * the loop variable is an iterator, not a value. This is because in deal.II,
+ * we never actually use the <i>dereferenced state</i> of a cell iterator:
+ * conceptually, it would represent a cell, and technically it is implemented
+ * by classes such as CellAccessor and DoFCellAccessor, but these classes are
+ * never used explicitly. Consequently, what we would like is that a call
+ * such as Triangulation::active_cell_iterators() returns an object that
+ * represents a <i>collection of iterators</i> of the kind
+ * <code>{begin, begin+1, ..., end-1}</code>. This is conveniently expressed
+ * as the half open interval <code>[begin,end)</code>. The loop variable in the
+ * range-based for loop would then take on each of these iterators in turn.
+ *
+ *
+ * <h3>Class design: Implementation</h3>
+ *
+ * To represent the desired semantics as outlined above, this class
+ * stores a half-open range of iterators <code>[b,e)</code> of
+ * the given template type. Secondly, the class needs to provide begin()
+ * and end() functions in such a way that if you <i>dereference</i> the
+ * result of IteratorRange::begin(), you get the <code>b</code> iterator.
+ * Furthermore, you must be able to increment the object returned by
+ * IteratorRange::begin() so that <code>*(++begin()) == b+1</code>.
+ * In other words, IteratorRange::begin() must return an iterator that
+ * when dereferenced returns an iterator of the template type
+ * <code>Iterator</code>: It is an iterator over iterators in the same
+ * sense as if you had a pointer into an array of pointers.
+ *
+ * This is implemented in the form of the IteratorRange::IteratorOverIterators
+ * class.
+ *
+ * @ingroup CPP11
+ * @author Wolfgang Bangerth, 2014
+ */
+template <typename Iterator>
+class IteratorRange
+{
+public:
+  /**
+   * A class that implements the semantics of iterators over iterators
+   * as discussed in the design sections of the IteratorRange class.
+   */
+  class IteratorOverIterators : public std::iterator<std::forward_iterator_tag, Iterator,
+                                                     typename Iterator::difference_type>
+  {
+  public:
+    /**
+     * Typedef the elements of the collection to give them a name that is
+     * more distinct.
+     */
+    typedef Iterator BaseIterator;
+
+    /**
+     * Constructor. Initialize this iterator-over-iterator in
+     * such a way that it points to the given argument.
+     *
+     * @param iterator An iterator to which this object
+     *   is supposed to point.
+     */
+    IteratorOverIterators (const BaseIterator &iterator);
+
+    /**
+     * Dereferencing operator.
+     * @return The iterator within the collection currently pointed to.
+     */
+    BaseIterator operator* () const;
+
+    /**
+     * Dereferencing operator.
+     * @return The iterator within the collection currently pointed to.
+     */
+    const BaseIterator * operator-> () const;
+
+    /**
+     * Prefix increment operator. Move the current iterator to the next
+     * element of the collection and return the new value.
+     */
+    IteratorOverIterators & operator ++ ();
+
+    /**
+     * Postfix increment operator. Move the current iterator to the next
+     * element of the collection, but return the previous value of the
+     * iterator.
+     */
+    IteratorOverIterators operator ++ (int);
+
+    /**
+     * Comparison operator
+     * @param i_o_i Another iterator over iterators.
+     * @return Returns whether the current iterator points to a
+     *   different object than the iterator represented by the
+     *   argument.
+     */
+    bool operator != (const IteratorOverIterators &i_o_i);
+
+  private:
+    /**
+     * The object this iterator currently points to.
+     */
+    BaseIterator element_of_iterator_collection;
+  };
+
+
+  /**
+   * Typedef for the iterator type represent by this class.
+   */
+  typedef Iterator iterator;
+
+  /**
+   * Default constructor. Create a range represented by two
+   * default constructed iterators. This range is likely (depending
+   * on the type of the iterators) empty.
+   */
+  IteratorRange();
+
+  /**
+   * Constructor. Constructs a range given the begin and end iterators.
+   *
+   * @param[in] begin An iterator pointing to the first element of the range
+   * @param[in] end   An iterator pointing past the last element represented
+   *   by this range.
+   */
+  IteratorRange (const iterator begin,
+                 const iterator end);
+
+  /**
+   * Return the iterator pointing to the first element of this range.
+   */
+  IteratorOverIterators begin();
+
+  /**
+   * Return the iterator pointing to the element past the last
+   * element of this range.
+   */
+  IteratorOverIterators end();
+
+private:
+  /**
+   * Iterators characterizing the begin and end of the range.
+   */
+  const iterator it_begin;
+  const iterator it_end;
+};
+
+
+// ------------------- template member functions
+
+
+template <typename Iterator>
+inline
+IteratorRange<Iterator>::IteratorOverIterators::
+IteratorOverIterators (const BaseIterator &iterator)
+  :
+  element_of_iterator_collection (iterator)
+{}
+
+
+
+template <typename Iterator>
+inline
+typename IteratorRange<Iterator>::IteratorOverIterators::BaseIterator
+IteratorRange<Iterator>::IteratorOverIterators::operator* () const
+{
+  return element_of_iterator_collection;
+}
+
+
+
+template <typename Iterator>
+inline
+const typename IteratorRange<Iterator>::IteratorOverIterators::BaseIterator *
+IteratorRange<Iterator>::IteratorOverIterators::operator-> () const
+{
+  return &element_of_iterator_collection;
+}
+
+
+
+template <typename Iterator>
+inline
+typename IteratorRange<Iterator>::IteratorOverIterators &
+IteratorRange<Iterator>::IteratorOverIterators::operator ++ ()
+{
+  ++element_of_iterator_collection;
+  return *this;
+}
+
+
+
+template <typename Iterator>
+inline
+typename IteratorRange<Iterator>::IteratorOverIterators
+IteratorRange<Iterator>::IteratorOverIterators::operator ++ (int)
+{
+  const IteratorOverIterators old_value = *this;
+  ++element_of_iterator_collection;
+  return *old_value;
+}
+
+
+
+template <typename Iterator>
+inline
+bool
+IteratorRange<Iterator>::IteratorOverIterators::operator != (const IteratorOverIterators &i_o_i)
+{
+  return element_of_iterator_collection != i_o_i.element_of_iterator_collection;
+}
+
+
+template <typename Iterator>
+inline
+IteratorRange<Iterator>::IteratorRange ()
+  :
+  it_begin(),
+  it_end()
+{}
+
+
+
+template <typename Iterator>
+inline
+IteratorRange<Iterator>::IteratorRange (const iterator b,
+                                        const iterator e)
+  :
+  it_begin(b),
+  it_end(e)
+{}
+
+
+template <typename Iterator>
+inline
+typename IteratorRange<Iterator>::IteratorOverIterators
+IteratorRange<Iterator>::begin()
+{
+  return IteratorOverIterators(it_begin);
+}
+
+
+template <typename Iterator>
+inline
+typename IteratorRange<Iterator>::IteratorOverIterators
+IteratorRange<Iterator>::end()
+{
+  return IteratorOverIterators(it_end);
+}
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
index e5b155ead0b001c0606ef99177fa73d09192fced..df011c759c6078efcbde2509a4fd4cf64151d589 100644 (file)
@@ -1,7 +1,7 @@
 // ---------------------------------------------------------------------
 // $Id$
 //
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
 //
 // This file is part of the deal.II library.
 //
@@ -23,6 +23,7 @@
 #include <deal.II/base/exceptions.h>
 #include <deal.II/base/smartpointer.h>
 #include <deal.II/base/index_set.h>
+#include <deal.II/base/iterator_range.h>
 #include <deal.II/base/std_cxx1x/shared_ptr.h>
 #include <deal.II/dofs/block_info.h>
 #include <deal.II/dofs/dof_iterator_selector.h>
@@ -632,6 +633,126 @@ public:
    */
   level_cell_iterator end_mg () const;
 
+  /*@}*/
+
+  /**
+   *  @name Cell iterator functions returning ranges of iterators
+   */
+
+  /**
+   * Return an iterator range that contains all cells (active or not)
+   * that make up this DoFHandler. Such a range is useful to
+   * initialize range-based for loops as supported by C++11. See the
+   * example in the documentation of active_cell_iterators().
+   *
+   * @return The half open range <code>[this->begin(), this->end())</code>
+   *
+   * @ingroup CPP11
+   */
+  IteratorRange<cell_iterator>        cell_iterators () const;
+
+  /**
+   * Return an iterator range that contains all active cells
+   * that make up this DoFHandler. Such a range is useful to
+   * initialize range-based for loops as supported by C++11,
+   * see also @ref CPP11 "C++11 standard".
+   *
+   * Range-based for loops are useful in that they require much less
+   * code than traditional loops (see
+   * <a href="http://en.wikipedia.org/wiki/C%2B%2B11#Range-based_for_loop">here</a>
+   * for a discussion of how they work). An example is that without
+   * range-based for loops, one often writes code such as the following:
+   * @code
+   *   DoFHandler<dim> dof_handler;
+   *   ...
+   *   typename DoFHandler<dim>::active_cell_iterator
+   *     cell = dof_handler.begin_active(),
+   *     endc = dof_handler.end();
+   *   for (; cell!=endc; ++cell)
+   *     {
+   *       fe_values.reinit (cell);
+   *       ...do the local integration on 'cell'...;
+   *     }
+   * @endcode
+   * Using C++11's range-based for loops, this is now entirely
+   * equivalent to the following:
+   * @code
+   *   DoFHandler<dim> dof_handler;
+   *   ...
+   *   for (auto cell : dof_handler.active_cell_iterators())
+   *     {
+   *       fe_values.reinit (cell);
+   *       ...do the local integration on 'cell'...;
+   *     }
+   * @endcode
+   * To use this feature, you need a compiler that supports C++11.
+   *
+   * @return The half open range <code>[this->begin_active(), this->end())</code>
+   *
+   * @ingroup CPP11
+   */
+  IteratorRange<active_cell_iterator> active_cell_iterators () const;
+
+  /**
+   * Return an iterator range that contains all cells (active or not)
+   * that make up this DoFHandler in their level-cell form. Such a range is useful to
+   * initialize range-based for loops as supported by C++11. See the
+   * example in the documentation of active_cell_iterators().
+   *
+   * @return The half open range <code>[this->begin_mg(), this->end_mg())</code>
+   *
+   * @ingroup CPP11
+   */
+  IteratorRange<level_cell_iterator>  mg_cell_iterators () const;
+
+  /**
+   * Return an iterator range that contains all cells (active or not)
+   * that make up the given level of this DoFHandler. Such a range is useful to
+   * initialize range-based for loops as supported by C++11. See the
+   * example in the documentation of active_cell_iterators().
+   *
+   * @param[in] level A given level in the refinement hierarchy of this
+   *   triangulation.
+   * @return The half open range <code>[this->begin(level), this->end(level))</code>
+   *
+   * @pre level must be less than this->n_levels().
+   *
+   * @ingroup CPP11
+   */
+  IteratorRange<cell_iterator>        cell_iterators_on_level (const unsigned int level) const;
+
+  /**
+   * Return an iterator range that contains all active cells
+   * that make up the given level of this DoFHandler. Such a range is useful to
+   * initialize range-based for loops as supported by C++11. See the
+   * example in the documentation of active_cell_iterators().
+   *
+   * @param[in] level A given level in the refinement hierarchy of this
+   *   triangulation.
+   * @return The half open range <code>[this->begin_active(level), this->end(level))</code>
+   *
+   * @pre level must be less than this->n_levels().
+   *
+   * @ingroup CPP11
+   */
+  IteratorRange<active_cell_iterator> active_cell_iterators_on_level (const unsigned int level) const;
+
+  /**
+   * Return an iterator range that contains all cells (active or not)
+   * that make up the given level of this DoFHandler in their level-cell form.
+   * Such a range is useful to
+   * initialize range-based for loops as supported by C++11. See the
+   * example in the documentation of active_cell_iterators().
+   *
+   * @param[in] level A given level in the refinement hierarchy of this
+   *   triangulation.
+   * @return The half open range <code>[this->begin_mg(level), this->end_mg(level))</code>
+   *
+   * @pre level must be less than this->n_levels().
+   *
+   * @ingroup CPP11
+   */
+  IteratorRange<level_cell_iterator> mg_cell_iterators_on_level (const unsigned int level) const;
 
   //@}
 
index ed43e3f220e587be26a29b8c7f7d6971f9cc9044..1eacc53dc021435977f100ce8bd300890ae67d4d 100644 (file)
@@ -23,6 +23,7 @@
 #include <deal.II/base/subscriptor.h>
 #include <deal.II/base/smartpointer.h>
 #include <deal.II/base/geometry_info.h>
+#include <deal.II/base/iterator_range.h>
 #include <deal.II/base/std_cxx1x/function.h>
 #include <deal.II/grid/tria_iterator_selector.h>
 #include <deal.II/grid/tria_faces.h>
@@ -2544,6 +2545,94 @@ public:
   active_cell_iterator last_active () const;
   /*@}*/
 
+  /**
+   *  @name Cell iterator functions returning ranges of iterators
+   */
+
+  /**
+   * Return an iterator range that contains all cells (active or not)
+   * that make up this triangulation. Such a range is useful to
+   * initialize range-based for loops as supported by C++11. See the
+   * example in the documentation of active_cell_iterators().
+   *
+   * @return The half open range <code>[this->begin(), this->end())</code>
+   *
+   * @ingroup CPP11
+   */
+  IteratorRange<cell_iterator>        cell_iterators () const;
+
+  /**
+   * Return an iterator range that contains all active cells
+   * that make up this triangulation. Such a range is useful to
+   * initialize range-based for loops as supported by C++11,
+   * see also @ref CPP11 "C++11 standard".
+   *
+   * Range-based for loops are useful in that they require much less
+   * code than traditional loops (see
+   * <a href="http://en.wikipedia.org/wiki/C%2B%2B11#Range-based_for_loop">here</a>
+   * for a discussion of how they work). An example is that without
+   * range-based for loops, one often writes code such as the following
+   * (assuming for a moment that our goal is setting the user flag
+   * on every active cell):
+   * @code
+   *   Triangulation<dim> triangulation;
+   *   ...
+   *   typename Triangulation<dim>::active_cell_iterator
+   *     cell = triangulation.begin_active(),
+   *     endc = triangulation.end();
+   *   for (; cell!=endc; ++cell)
+   *     cell->set_user_flag();
+   * @endcode
+   * Using C++11's range-based for loops, this is now entirely
+   * equivalent to the following:
+   * @code
+   *   Triangulation<dim> triangulation;
+   *   ...
+   *   for (auto cell : triangulation.active_cell_iterators())
+   *     cell->set_user_flag();
+   * @endcode
+   * To use this feature, you need a compiler that supports C++11.
+   *
+   * @return The half open range <code>[this->begin_active(), this->end())</code>
+   *
+   * @ingroup CPP11
+   */
+  IteratorRange<active_cell_iterator> active_cell_iterators () const;
+
+  /**
+   * Return an iterator range that contains all cells (active or not)
+   * that make up the given level of this triangulation. Such a range is useful to
+   * initialize range-based for loops as supported by C++11. See the
+   * example in the documentation of active_cell_iterators().
+   *
+   * @param[in] level A given level in the refinement hierarchy of this
+   *   triangulation.
+   * @return The half open range <code>[this->begin(level), this->end(level))</code>
+   *
+   * @pre level must be less than this->n_levels().
+   *
+   * @ingroup CPP11
+   */
+  IteratorRange<cell_iterator>        cell_iterators_on_level (const unsigned int level) const;
+
+  /**
+   * Return an iterator range that contains all active cells
+   * that make up the given level of this triangulation. Such a range is useful to
+   * initialize range-based for loops as supported by C++11. See the
+   * example in the documentation of active_cell_iterators().
+   *
+   * @param[in] level A given level in the refinement hierarchy of this
+   *   triangulation.
+   * @return The half open range <code>[this->begin_active(level), this->end(level))</code>
+   *
+   * @pre level must be less than this->n_levels().
+   *
+   * @ingroup CPP11
+   */
+  IteratorRange<active_cell_iterator> active_cell_iterators_on_level (const unsigned int level) const;
+
+  /*@}*/
+
   /*---------------------------------------*/
   /*---------------------------------------*/
 
index 10f0522892708d54f062b105aeacc89a1c91e664..7103b9273a54e252cca09638c05cc1e57a758d59 100644 (file)
@@ -23,6 +23,7 @@
 #include <deal.II/base/exceptions.h>
 #include <deal.II/base/template_constraints.h>
 #include <deal.II/base/smartpointer.h>
+#include <deal.II/base/iterator_range.h>
 #include <deal.II/dofs/function_map.h>
 #include <deal.II/dofs/dof_iterator_selector.h>
 #include <deal.II/dofs/number_cache.h>
@@ -404,6 +405,98 @@ namespace hp
 
     /*@}*/
 
+    /**
+     *  @name Cell iterator functions returning ranges of iterators
+     */
+
+    /**
+     * Return an iterator range that contains all cells (active or not)
+     * that make up this DoFHandler. Such a range is useful to
+     * initialize range-based for loops as supported by C++11. See the
+     * example in the documentation of active_cell_iterators().
+     *
+     * @return The half open range <code>[this->begin(), this->end())</code>
+     *
+     * @ingroup CPP11
+     */
+    IteratorRange<cell_iterator>        cell_iterators () const;
+
+    /**
+     * Return an iterator range that contains all active cells
+     * that make up this DoFHandler. Such a range is useful to
+     * initialize range-based for loops as supported by C++11,
+     * see also @ref CPP11 "C++11 standard".
+     *
+     * Range-based for loops are useful in that they require much less
+     * code than traditional loops (see
+     * <a href="http://en.wikipedia.org/wiki/C%2B%2B11#Range-based_for_loop">here</a>
+     * for a discussion of how they work). An example is that without
+     * range-based for loops, one often writes code such as the following:
+     * @code
+     *   DoFHandler<dim> dof_handler;
+     *   ...
+     *   typename DoFHandler<dim>::active_cell_iterator
+     *     cell = dof_handler.begin_active(),
+     *     endc = dof_handler.end();
+     *   for (; cell!=endc; ++cell)
+     *     {
+     *       fe_values.reinit (cell);
+     *       ...do the local integration on 'cell'...;
+     *     }
+     * @endcode
+     * Using C++11's range-based for loops, this is now entirely
+     * equivalent to the following:
+     * @code
+     *   DoFHandler<dim> dof_handler;
+     *   ...
+     *   for (auto cell : dof_handler.active_cell_iterators())
+     *     {
+     *       fe_values.reinit (cell);
+     *       ...do the local integration on 'cell'...;
+     *     }
+     * @endcode
+     * To use this feature, you need a compiler that supports C++11.
+     *
+     * @return The half open range <code>[this->begin_active(), this->end())</code>
+     *
+     * @ingroup CPP11
+     */
+    IteratorRange<active_cell_iterator> active_cell_iterators () const;
+
+    /**
+     * Return an iterator range that contains all cells (active or not)
+     * that make up the given level of this DoFHandler. Such a range is useful to
+     * initialize range-based for loops as supported by C++11. See the
+     * example in the documentation of active_cell_iterators().
+     *
+     * @param[in] level A given level in the refinement hierarchy of this
+     *   triangulation.
+     * @return The half open range <code>[this->begin(level), this->end(level))</code>
+     *
+     * @pre level must be less than this->n_levels().
+     *
+     * @ingroup CPP11
+     */
+    IteratorRange<cell_iterator>        cell_iterators_on_level (const unsigned int level) const;
+
+    /**
+     * Return an iterator range that contains all active cells
+     * that make up the given level of this DoFHandler. Such a range is useful to
+     * initialize range-based for loops as supported by C++11. See the
+     * example in the documentation of active_cell_iterators().
+     *
+     * @param[in] level A given level in the refinement hierarchy of this
+     *   triangulation.
+     * @return The half open range <code>[this->begin_active(level), this->end(level))</code>
+     *
+     * @pre level must be less than this->n_levels().
+     *
+     * @ingroup CPP11
+     */
+    IteratorRange<active_cell_iterator> active_cell_iterators_on_level (const unsigned int level) const;
+
+    /*@}*/
+
     /*---------------------------------------*/
 
 
index 503e2357d5b630f2495b2aa661235b1973b053f6..0756879b4de4221dff2d6c130632cd0f1e9955d5 100644 (file)
@@ -1,7 +1,7 @@
 // ---------------------------------------------------------------------
 // $Id$
 //
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
 //
 // This file is part of the deal.II library.
 //
@@ -914,6 +914,72 @@ DoFHandler<dim, spacedim>::end_mg () const
 
 
 
+template <int dim, int spacedim>
+IteratorRange<typename DoFHandler<dim, spacedim>::cell_iterator>
+DoFHandler<dim, spacedim>::cell_iterators () const
+{
+  return
+    IteratorRange<typename DoFHandler<dim, spacedim>::cell_iterator>
+    (begin(), end());
+}
+
+
+template <int dim, int spacedim>
+IteratorRange<typename DoFHandler<dim, spacedim>::active_cell_iterator>
+DoFHandler<dim, spacedim>::active_cell_iterators () const
+{
+  return
+    IteratorRange<typename DoFHandler<dim, spacedim>::active_cell_iterator>
+    (begin_active(), end());
+}
+
+
+
+template <int dim, int spacedim>
+IteratorRange<typename DoFHandler<dim, spacedim>::level_cell_iterator>
+DoFHandler<dim, spacedim>::mg_cell_iterators () const
+{
+  return
+    IteratorRange<typename DoFHandler<dim, spacedim>::level_cell_iterator>
+    (begin_mg(), end_mg());
+}
+
+
+
+
+template <int dim, int spacedim>
+IteratorRange<typename DoFHandler<dim, spacedim>::cell_iterator>
+DoFHandler<dim, spacedim>::cell_iterators_on_level (const unsigned int level) const
+{
+  return
+    IteratorRange<typename DoFHandler<dim, spacedim>::cell_iterator>
+    (begin(level), end(level));
+}
+
+
+
+template <int dim, int spacedim>
+IteratorRange<typename DoFHandler<dim, spacedim>::active_cell_iterator>
+DoFHandler<dim, spacedim>::active_cell_iterators_on_level (const unsigned int level) const
+{
+  return
+    IteratorRange<typename DoFHandler<dim, spacedim>::active_cell_iterator>
+    (begin_active(level), end_active(level));
+}
+
+
+
+template <int dim, int spacedim>
+IteratorRange<typename DoFHandler<dim, spacedim>::level_cell_iterator>
+DoFHandler<dim, spacedim>::mg_cell_iterators_on_level (const unsigned int level) const
+{
+  return
+    IteratorRange<typename DoFHandler<dim, spacedim>::level_cell_iterator>
+    (begin_mg(level), end_mg(level));
+}
+
+
+
 //---------------------------------------------------------------------------
 
 
index 14da3cc2b9d25f74d7790335b33fc75c196ef030..ca640d4ed7831112d20a96cb5e86d112eddadfaa 100644 (file)
@@ -10567,6 +10567,49 @@ Triangulation<dim, spacedim>::end_active (const unsigned int level) const
 }
 
 
+
+template <int dim, int spacedim>
+IteratorRange<typename Triangulation<dim, spacedim>::cell_iterator>
+Triangulation<dim, spacedim>::cell_iterators () const
+{
+  return
+    IteratorRange<typename Triangulation<dim, spacedim>::cell_iterator>
+    (begin(), end());
+}
+
+
+template <int dim, int spacedim>
+IteratorRange<typename Triangulation<dim, spacedim>::active_cell_iterator>
+Triangulation<dim, spacedim>::active_cell_iterators () const
+{
+  return
+    IteratorRange<typename Triangulation<dim, spacedim>::active_cell_iterator>
+    (begin_active(), end());
+}
+
+
+
+template <int dim, int spacedim>
+IteratorRange<typename Triangulation<dim, spacedim>::cell_iterator>
+Triangulation<dim, spacedim>::cell_iterators_on_level (const unsigned int level) const
+{
+  return
+    IteratorRange<typename Triangulation<dim, spacedim>::cell_iterator>
+    (begin(level), end(level));
+}
+
+
+
+template <int dim, int spacedim>
+IteratorRange<typename Triangulation<dim, spacedim>::active_cell_iterator>
+Triangulation<dim, spacedim>::active_cell_iterators_on_level (const unsigned int level) const
+{
+  return
+    IteratorRange<typename Triangulation<dim, spacedim>::active_cell_iterator>
+    (begin_active(level), end_active(level));
+}
+
+
 /*------------------------ Face iterator functions ------------------------*/
 
 
index 2f271224d7dd89320fa48683269137af903eccd7..8c821f0143ee6039b452f42adc4831169769ba1f 100644 (file)
@@ -1740,6 +1740,49 @@ namespace hp
 
 
 
+  template <int dim, int spacedim>
+  IteratorRange<typename DoFHandler<dim, spacedim>::cell_iterator>
+  DoFHandler<dim, spacedim>::cell_iterators () const
+  {
+    return
+      IteratorRange<typename DoFHandler<dim, spacedim>::cell_iterator>
+      (begin(), end());
+  }
+
+
+  template <int dim, int spacedim>
+  IteratorRange<typename DoFHandler<dim, spacedim>::active_cell_iterator>
+  DoFHandler<dim, spacedim>::active_cell_iterators () const
+  {
+    return
+      IteratorRange<typename DoFHandler<dim, spacedim>::active_cell_iterator>
+      (begin_active(), end());
+  }
+
+
+
+  template <int dim, int spacedim>
+  IteratorRange<typename DoFHandler<dim, spacedim>::cell_iterator>
+  DoFHandler<dim, spacedim>::cell_iterators_on_level (const unsigned int level) const
+  {
+    return
+      IteratorRange<typename DoFHandler<dim, spacedim>::cell_iterator>
+      (begin(level), end(level));
+  }
+
+
+
+  template <int dim, int spacedim>
+  IteratorRange<typename DoFHandler<dim, spacedim>::active_cell_iterator>
+  DoFHandler<dim, spacedim>::active_cell_iterators_on_level (const unsigned int level) const
+  {
+    return
+      IteratorRange<typename DoFHandler<dim, spacedim>::active_cell_iterator>
+      (begin_active(level), end_active(level));
+  }
+  
+
+
 
 //------------------------------------------------------------------
 
diff --git a/tests/deal.II/range_based_for_tria.cc b/tests/deal.II/range_based_for_tria.cc
new file mode 100644 (file)
index 0000000..8c924ff
--- /dev/null
@@ -0,0 +1,86 @@
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// Check range-based for loops for triangulations
+
+#include "../tests.h"
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/base/logstream.h>
+
+#include <fstream>
+#include <string>
+
+
+template<int dim>
+void check()
+{
+  Triangulation<dim> tr;
+  GridGenerator::hyper_cube(tr);
+  tr.refine_global(2);
+
+
+  {
+    // set flags on active cells
+    tr.clear_user_flags ();
+    for (auto cell : tr.active_cell_iterators())
+      cell->set_user_flag();
+
+    // now verify that it is really only the active cells
+    for (auto cell : tr.cell_iterators())
+      Assert (cell->user_flag_set() == !cell->has_children(),
+             ExcInternalError());
+  }
+
+  // now do the same again for all levels of the triangulation
+  for (unsigned int l=0; l<tr.n_levels(); ++l)
+    {
+      tr.clear_user_flags ();
+      for (auto cell : tr.active_cell_iterators_on_level(l))
+       cell->set_user_flag();
+
+      for (auto cell : tr.cell_iterators_on_level(l))
+       Assert (cell->user_flag_set() == !cell->has_children(),
+               ExcInternalError());
+      
+      for (auto cell : tr.cell_iterators())
+       Assert ((cell->user_flag_set() == !cell->has_children())
+               ||
+               (l != cell->level()),
+               ExcInternalError());
+    }
+
+  deallog << "OK" << std::endl;
+}
+
+
+int main()
+{
+  deal_II_exceptions::disable_abort_on_exception();
+
+  std::ofstream logfile("output");
+  deallog.attach(logfile);
+  deallog.depth_console(0);
+  deallog.threshold_double(1.e-10);
+
+  check<2>();
+  check<3>();
+}
diff --git a/tests/deal.II/range_based_for_tria.with_cxx11=true.output b/tests/deal.II/range_based_for_tria.with_cxx11=true.output
new file mode 100644 (file)
index 0000000..8b3b075
--- /dev/null
@@ -0,0 +1,3 @@
+
+DEAL::OK
+DEAL::OK

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.