]> https://gitweb.dealii.org/ - dealii-svn.git/commitdiff
FilteredIterator class
authorwolf <wolf@0785d39b-7218-0410-832d-ea1e28bc413d>
Mon, 7 Jan 2002 09:40:29 +0000 (09:40 +0000)
committerwolf <wolf@0785d39b-7218-0410-832d-ea1e28bc413d>
Mon, 7 Jan 2002 09:40:29 +0000 (09:40 +0000)
git-svn-id: https://svn.dealii.org/trunk@5346 0785d39b-7218-0410-832d-ea1e28bc413d

deal.II/deal.II/include/grid/filtered_iterator.h [new file with mode: 0644]
deal.II/doc/news/2001/c-3-2.html
tests/deal.II/filtered_iterator.cc [new file with mode: 0644]
tests/deal.II/filtered_iterator.checked [new file with mode: 0644]

diff --git a/deal.II/deal.II/include/grid/filtered_iterator.h b/deal.II/deal.II/include/grid/filtered_iterator.h
new file mode 100644 (file)
index 0000000..3242582
--- /dev/null
@@ -0,0 +1,1042 @@
+//------------------------ filtered_iterator.h -----------------------
+//    $Id$
+//    Version: $Name$
+//
+//    Copyright (C) 2002 by the deal.II authors
+//
+//    This file is subject to QPL and may not be  distributed
+//    without copyright and license information. Please refer
+//    to the file deal.II/doc/license.html for the  text  and
+//    further information on this license.
+//
+//------------------------ filtered_iterator.h -----------------------
+#ifndef __deal2__filtered_iterator_h
+#define __deal2__filtered_iterator_h
+
+
+
+/**
+ * In this namespace a number of classes is declared that may be used
+ * as filters in the @ref{FilteredIterator} class. The filters either
+ * check for binary information (for example, the @p{Active} filter
+ * class checks whether the object pointed to is active), or for
+ * valued information by comparison with prescribed values (for
+ * example, the @ref{LevelEqualTo} filter class checks whether the
+ * level of the object pointed to by the iterator under consideration
+ * is equal to a value that was given to the filter upon construction.
+ *
+ * For examples of use of these classes as well as requirements on
+ * filters see the general description of the @ref{FilteredIterator}
+ * class.
+ *
+ * @author Wolfgang Bangerth, 2002
+ */
+namespace IteratorFilters
+{
+                                  /**
+                                   * Filter that evaluates to true if
+                                   * either the iterator points to an
+                                   * active object or an iterator
+                                   * past the end.
+                                   */
+  class Active 
+  {
+    public:
+                                      /**
+                                       * Evaluate the iterator and
+                                       * return true if the object is
+                                       * active or past the end.
+                                       */
+      template <class Iterator>
+      bool operator () (const Iterator &i) const;
+  };
+  
+                                  /**
+                                   * Filter that evaluates to true if
+                                   * either the iterator points to an
+                                   * object for which the user flag
+                                   * is set or an iterator past the
+                                   * end.
+                                   */
+  class UserFlagSet
+  {
+    public:
+                                      /**
+                                       * Evaluate the iterator and
+                                       * return true if the object
+                                       * has a set user flag or past
+                                       * the end.
+                                       */
+      template <class Iterator>
+      bool operator () (const Iterator &i) const;
+  };
+  
+
+                                  /**
+                                   * Filter that evaluates to true if
+                                   * either the iterator points to an
+                                   * object for which the user flag
+                                   * is not set or an iterator past
+                                   * the end. Inverse filter to the
+                                   * previous class.
+                                   */
+  class UserFlagNotSet
+  {
+    public:
+                                      /**
+                                       * Evaluate the iterator and
+                                       * return true if the object
+                                       * has an unset user flag or
+                                       * past the end.
+                                       */
+      template <class Iterator>
+      bool operator () (const Iterator &i) const;
+  };
+
+  
+                                  /**
+                                   * Filter for iterators that
+                                   * evaluates to true if either the
+                                   * iterator is past the end or the
+                                   * level of the object pointed to
+                                   * is equal to a value given to the
+                                   * constructor.
+                                   */
+  class LevelEqualTo 
+  {
+    public:
+                                      /**
+                                       * Constructor. Store the level
+                                       * which iterators shall have
+                                       * to be evaluated to true.
+                                       */
+      LevelEqualTo (const unsigned int level);
+
+                                      /**
+                                       * Evaluation operator. Returns
+                                       * true if either the level of
+                                       * the object pointed to is
+                                       * equal to the stored value or
+                                       * the iterator is past the
+                                       * end.
+                                       */
+      template <class Iterator>
+      bool operator () (const Iterator &i) const;
+
+    protected:
+                                      /**
+                                       * Stored value to compare the
+                                       * level with.
+                                       */
+      const unsigned int level;
+  };
+
+
+
+                                  /**
+                                   * Filter for iterators that
+                                   * evaluates to true if either the
+                                   * iterator is past the end or the
+                                   * subdomain id of the object
+                                   * pointed to is equal to a value
+                                   * given to the constructor,
+                                   * assuming that the iterator
+                                   * allows querying for a subdomain
+                                   * id).
+                                   */
+  class SubdomainEqualTo 
+  {
+    public:
+                                      /**
+                                       * Constructor. Store the
+                                       * subdomain which iterators
+                                       * shall have to be evaluated
+                                       * to true.
+                                       */
+      SubdomainEqualTo (const unsigned int subdomain_id);
+
+                                      /**
+                                       * Evaluation operator. Returns
+                                       * true if either the subdomain
+                                       * of the object pointed to is
+                                       * equal to the stored value or
+                                       * the iterator is past the
+                                       * end.
+                                       */
+      template <class Iterator>
+      bool operator () (const Iterator &i) const;
+
+    protected:
+                                      /**
+                                       * Stored value to compare the
+                                       * subdomain with.
+                                       */
+      const unsigned int subdomain_id;
+  };
+};
+
+
+/**
+ * This class provides a certain view on a range of triangulation or
+ * DoFHandler iterators by only iterating over elements that satisfy a
+ * given filter (called a @em{predicate}, following the notation of
+ * the C++ standard library). Once initialized with a predicate and a
+ * value for the iterator, a filtered iterator hops to the next or
+ * previous element that satisfies the predicate if operators ++ or --
+ * are invoked. Intermediate iterator values that lie in between but
+ * do not satisfy the predicate are skipped. It is thus very simple to
+ * write loops over a certain class of objects without the need to
+ * explicitely write down the condition they have to satisfy in each
+ * loop iteration. This in particular is helpful if functions are
+ * called with a pair of iterators denoting a range on which they
+ * shall act, by choosing a filtered iterator instead of usual ones.
+ *
+ *
+ * @sect3{Predicates}
+ *
+ * The object that represent the condition an iterator has to satisfy
+ * only have to provide an interface that allows to call the
+ * evaluation operator, i.e. @p{operator()}. This includes function
+ * pointers as well as classes that implement an @p{operator ()}.
+ *
+ * An example of a simple valid predicate is the following: given the function
+ * @begin{verbatim}
+ *   template <typename Iterator>
+ *   bool level_equal_to_3 (const Iterator c)
+ *   {
+ *     return (static_cast<unsigned int>(c->level()) == 3);
+ *   };
+ * @end{verbatim} 
+ * then
+ * @begin{verbatim}
+ *   &level_equal_to_3<typename Triangulation<dim>::active_cell_iterator>
+ * @end{verbatim}
+ * is a valid predicate.
+ *
+ * Likewise, given the following binary function
+ * @begin{verbatim}
+ *   template <typename Iterator>
+ *   bool level_equal_to (const Iterator     c,
+ *                        const unsigned int level)
+ *   {
+ *     return (static_cast<unsigned int>(c->level()) == level);
+ *   };
+ * @end{verbatim} 
+ * then
+ * @begin{verbatim}
+ *   std::bind2nd (std::ptr_fun(&level_equal_to<active_cell_iterator>), 3)
+ * @end{verbatim}
+ * is another valid predicate (here: a function that returns true if
+ * either the iterator is past the end or the level is equal to the
+ * second argument; this second argument is bound to a fixed value
+ * using the @p{std::bind2nd} function).
+ *
+ * Finally, classes can be predicates. The following class is one:
+ * @begin{verbatim}
+ *   class Active 
+ *   {
+ *     public:
+ *       template <class Iterator>
+ *       bool operator () (const Iterator &i) const {
+ *         return (i->active());
+ *       }
+ *   };
+ * @end{verbatim}
+ * and objects of this type can be used as predicates. Likewise, this
+ * more complicated one can also be used:
+ * @begin{verbatim}
+ *   class SubdomainEqualTo
+ *   {
+ *     public:
+ *       SubdomainEqualTo (const unsigned int subdomain_id)
+ *                   : subdomain_id (subdomain_id) {};
+ *
+ *       template <class Iterator>
+ *       bool operator () (const Iterator &i) const {
+ *         return (i->subdomain_id() == subdomain_id);
+ *       }
+ *
+ *     private:
+ *       const unsigned int subdomain_id;
+ *   };
+ * @end{verbatim}
+ * Objects like @p{SubdomainEqualTo(3)} can then be used as predicates.
+ *
+ * Since whenever a predicate is evaluated it is checked that the
+ * iterator checked is actually valid (i.e. not past the end), no
+ * checks for this case have to be performed inside predicates.
+ *
+ * A number of filter classes are already implemented in the
+ * @ref{IteratorFilters} namespace, but writing different ones is
+ * simple following the examples above.
+ *
+ *
+ * @sect3{Initialization of filtered iterators}
+ *
+ * Filtered iterators are given a predicate at construction time which
+ * cannot be changed any more. This behaviour would be expected if the
+ * predicate would have been given as a template parameter to the
+ * class, but since that would make the declaration of filtered
+ * iterators a nightmare, we rather give the predicate as an
+ * unchangeable entity to the constructor. Note that one can assign a
+ * filtered iterator with one predicate to another filtered iterator
+ * with another type; yet, this does @em{not} change the predicate of
+ * the assigned-to iterator, only the pointer indicating the iterator
+ * is changed.
+ *
+ * If a filtered iterator is not assigned a value of the underlying
+ * (unfiltered) iterator type, the default value is taken. If,
+ * however, a value is given to the constructor, that value has either
+ * to be past the end, or has to satisfy the predicate. For example,
+ * if the predicate only evaluates to true if the level of an object
+ * is equal to three, then @p{tria.begin_active(3)} would be a valid
+ * choice while @p{tria.begin()} would not since the latter also
+ * returns iterators to non-active cells which always start at level
+ * 0.
+ *
+ * Since one often only has some iterator and wants to set a filtered
+ * iterator to the first one that satisfies a predicate (for example,
+ * the first one for which the user flag is set, or the first one with
+ * a given subdomain id), there are assignement functions
+ * @p{set_to_next_positive} and @p{set_to_previous_positive} that
+ * assign the next or last previous iterator that satisfies the
+ * predicate, i.e. they follow the list of iterators in either
+ * direction until they find a matching one (or the past-the-end
+ * iterator). Like the @p{operator=} they return the resulting value
+ * of the filtered iterator.
+ *
+ *
+ * @sect3{Examples}
+ *
+ * The following call counts the number of active cells that
+ * have a set user flag:
+ * @begin{verbatim}
+ *   FilteredIterator<typename Triangulation<dim>::active_cell_iterator>
+ *      begin (IteratorFilters::UserFlagSet()),
+ *      end (IteratorFilters::UserFlagSet());
+ *   begin.set_to_next_positive(tria.begin_active());
+ *   end = tria.end();
+ *   n_flagged_cells = std::distance (begin, end);
+ * @begin{verbatim}
+ * Note that by the @p{set_to_next_positive} call the first cell with
+ * a set user flag was assigned to the @p{begin} iterator. For the
+ * @{end} iterator, no such call was necessary, since the past-the-end
+ * iterator always satisfies all predicates.
+ *
+ * The same can be achieved by the following snippet, though harder to read:
+ * @begin{verbatim}
+ *   typedef FilteredIterator<typename Triangulation<dim>::active_cell_iterator> FI;
+ *   n_flagged_cells =
+ *      std::distance (FI(IteratorFilters::UserFlagSet())
+ *                            .set_to_next_positive(tria.begin_active()),
+ *                     FI(IteratorFilters::UserFlagSet(), tria.end()));
+ * @begin{verbatim}
+ * It relies on the fact that if we create an unnamed filtered
+ * iterator with a given predicate but no iterator value and assign it
+ * the next positive value with respect to this predicate, it returns
+ * itself which is then used as the first parameter to the
+ * @p{std::distance} function. This procedure is not necessary for the
+ * end element to this function here, since the past-the-end iterator
+ * always satisfies the predicate so that we can assign this value to
+ * the filtered iterator directly in the constructor.
+ *
+ * Finally, the following loop only assembles the matrix on cells with
+ * subdomain id equal to three:
+ * @begin{verbatim}
+ * FilteredIterator<typename Triangulation<dim>::active_cell_iterator>
+ *   cell (FilteredIterator::SubdomainEqualTo(3)),
+ *   endc (FilteredIterator::SubdomainEqualTo(3), tria.end());
+ * cell.set_to_next_positive (tria.begin_active());
+ * for (; cell!=endc; ++cell)
+ *   assemble_local_matrix (cell);
+ * @end{verbatim}
+ *
+ * Since comparison between filtered and unfiltered iterators is
+ * defined, we could as well have let the @p{endc} variable in the
+ * last example be of type
+ * @p{Triangulation<dim>::active_cell_iterator} since it is unchanged
+ * and its value does not depend on the filter.
+ *
+ * @author Wolfgang Bangerth, 2002
+ */
+template <typename BaseIterator>
+class FilteredIterator : public BaseIterator
+{
+  public:
+                                    /**
+                                     * Typedef to the accessor type
+                                     * of the underlying iterator.
+                                     */
+    typedef typename BaseIterator::AccessorType AccessorType;
+
+                                    /**
+                                     * Constructor. Set the iterator
+                                     * to the default state and use
+                                     * the given predicate for
+                                     * filtering subsequent
+                                     * assignement and iteration.
+                                     */
+    template <typename Predicate>
+    FilteredIterator (Predicate p);
+
+                                    /**
+                                     * Constructor. Use the given
+                                     * predicate for filtering and
+                                     * initialize the iterator with
+                                     * the given value. This initial
+                                     * value has to satisfy the
+                                     * predicate.
+                                     */
+    template <typename Predicate>    
+    FilteredIterator (Predicate           p,
+                     const BaseIterator &bi);
+
+                                    /**
+                                     * Copy constructor. Copy the
+                                     * predicate and iterator value
+                                     * of the given argument.
+                                     */
+    FilteredIterator (const FilteredIterator &fi);
+
+                                    /**
+                                     * Destructor.
+                                     */
+    ~FilteredIterator ();
+    
+                                    /**
+                                     * Assignment operator. Copy the
+                                     * iterator value of the
+                                     * argument, but as discussed in
+                                     * the class documentation, the
+                                     * predicate of the argument is
+                                     * not copied. The iterator value
+                                     * underlying the argument has to
+                                     * satisfy the predicate of the
+                                     * object assigned to, as given
+                                     * at its construction time.
+                                     */
+    FilteredIterator & operator = (const FilteredIterator &fi);
+
+                                    /**
+                                     * Assignment operator. Copy the
+                                     * iterator value of the
+                                     * argument, and keep the
+                                     * predicate of this object. The
+                                     * given iterator value has to
+                                     * satisfy the predicate of the
+                                     * object assigned to, as given
+                                     * at its construction time.
+                                     */
+    FilteredIterator & operator = (const BaseIterator &fi);
+
+                                    /**
+                                     * Search for the next iterator
+                                     * from @p{bi} onwards that
+                                     * satisfies the predicate of
+                                     * this object and assign it to
+                                     * this object.
+                                     *
+                                     * Since filtered iterators are
+                                     * automatically converted to the
+                                     * underlying base iterator type,
+                                     * you can also give a filtered
+                                     * iterator as argument to this
+                                     * function.
+                                     */
+    FilteredIterator &
+    set_to_next_positive (const BaseIterator &bi);
+    
+                                    /**
+                                     * As above, but search for the
+                                     * previous iterator from @p{bi}
+                                     * backwards that satisfies the
+                                     * predicate of this object and
+                                     * assign it to this object.
+                                     *
+                                     * Since filtered iterators are
+                                     * automatically converted to the
+                                     * underlying base iterator type,
+                                     * you can also give a filtered
+                                     * iterator as argument to this
+                                     * function.
+                                     */
+    FilteredIterator &
+    set_to_previous_positive (const BaseIterator &bi);
+    
+                                    /**
+                                     * Compare for equality of the
+                                     * underlying iterator values of
+                                     * this and the given object.
+                                     *
+                                     * We do not compare for equality
+                                     * of the predicates.
+                                     */
+    bool operator == (const FilteredIterator &fi) const;
+
+                                    /**
+                                     * Compare for equality of the
+                                     * underlying iterator value of
+                                     * this object with the given
+                                     * object.
+                                     *
+                                     * The predicate of this object
+                                     * is irrelevant for this
+                                     * operation.
+                                     */
+    bool operator == (const BaseIterator &fi) const;
+
+                                    /**
+                                     * Compare for inequality of the
+                                     * underlying iterator values of
+                                     * this and the given object.
+                                     *
+                                     * We do not compare for equality
+                                     * of the predicates.
+                                     */
+    bool operator != (const FilteredIterator &fi) const;
+
+                                    /**
+                                     * Compare for inequality of the
+                                     * underlying iterator value of
+                                     * this object with the given
+                                     * object.
+                                     *
+                                     * The predicate of this object
+                                     * is irrelevant for this
+                                     * operation.
+                                     */
+    bool operator != (const BaseIterator &fi) const;
+
+                                    /**
+                                     * Compare for ordering of the
+                                     * underlying iterator values of
+                                     * this and the given object.
+                                     *
+                                     * We do not compare the
+                                     * predicates.
+                                     */    
+    bool operator <  (const FilteredIterator &fi) const;
+
+                                    /**
+                                     * Compare for ordering of the
+                                     * underlying iterator value of
+                                     * this object with the given
+                                     * object.
+                                     *
+                                     * The predicate of this object
+                                     * is irrelevant for this
+                                     * operation.
+                                     */
+    bool operator <  (const BaseIterator &fi) const;
+
+                                    /**
+                                     * Prefix advancement operator:
+                                     * move to the next iterator
+                                     * value satisfying the predicate
+                                     * and return the new iterator
+                                     * value.
+                                     */
+    FilteredIterator & operator ++ ();
+
+                                    /**
+                                     * Postfix advancement operator:
+                                     * move to the next iterator
+                                     * value satisfying the predicate
+                                     * and return the old iterator
+                                     * value.
+                                     */
+    FilteredIterator   operator ++ (int);
+
+                                    /**
+                                     * Prefix decrement operator:
+                                     * move to the previous iterator
+                                     * value satisfying the predicate
+                                     * and return the new iterator
+                                     * value.
+                                     */
+    FilteredIterator & operator -- ();
+
+                                    /**
+                                     * Postfix advancement operator:
+                                     * move to the previous iterator
+                                     * value satisfying the predicate
+                                     * and return the old iterator
+                                     * value.
+                                     */
+    FilteredIterator   operator -- (int);
+
+                                    /**
+                                     * Exception.
+                                     */
+    DeclException1 (ExcInvalidElement,
+                   BaseIterator,
+                   << "The element " << arg1
+                   << " with which you want to compare or which you want to"
+                   << " assign is invalid since it does not satisfy the predicate.");
+    
+  private:
+
+                                    /**
+                                     * Base class to encapsulate a
+                                     * predicate object. Since
+                                     * predicates can be of different
+                                     * types and we do not want to
+                                     * code these types into the
+                                     * template parameter list of the
+                                     * filtered iterator class, we
+                                     * use a base class with an
+                                     * abstract function and
+                                     * templatized derived classes
+                                     * that implement the use of
+                                     * actual predicate types through
+                                     * the virtual function.
+                                     */
+    class PredicateBase
+    {
+      public:
+                                        /**
+                                         * Mark the destructor
+                                         * virtual to allow
+                                         * destruction through
+                                         * pointers to the base
+                                         * class.
+                                         */
+       virtual ~PredicateBase () {};
+
+                                        /**
+                                         * Abstract function which in
+                                         * derived classes denotes
+                                         * the evaluation of the
+                                         * predicate on the give
+                                         * iterator.
+                                         */
+       virtual bool operator () (const BaseIterator &bi) const = 0;
+
+                                        /**
+                                         * Generate a copy of this
+                                         * object, i.e. of the actual
+                                         * type of this pointer.
+                                         */
+       virtual PredicateBase * clone () const = 0;
+    };
+
+
+                                    /**
+                                     * Actual implementation of the
+                                     * above abstract base class. Use
+                                     * a template parameter to denote
+                                     * the actual type of the
+                                     * predicate and store a copy of
+                                     * it. When the virtual function
+                                     * is called evaluate the given
+                                     * iterator with the stored copy
+                                     * of the predicate.
+                                     */
+    template <typename Predicate>
+    class PredicateTemplate : public PredicateBase
+    {
+      public:
+                                        /**
+                                         * Constructor. Take a
+                                         * predicate and store a copy
+                                         * of it.
+                                         */
+       PredicateTemplate (const Predicate &predicate);
+
+                                        /**
+                                         * Evaluate the iterator with
+                                         * the stored copy of the
+                                         * predicate.
+                                         */
+       virtual bool operator () (const BaseIterator &bi) const;
+
+                                        /**
+                                         * Generate a copy of this
+                                         * object, i.e. of the actual
+                                         * type of this pointer.
+                                         */
+       virtual PredicateBase * clone () const;
+       
+      private:
+                                        /**
+                                         * Copy of the predicate.
+                                         */
+       const Predicate predicate;
+    };
+
+                                    /**
+                                     * Pointer to an object that
+                                     * encapsulated the actual data
+                                     * type of the predicate given to
+                                     * the constructor.
+                                     */
+    const PredicateBase * predicate;
+};
+
+
+
+/* ------------------ Inline functions and templates ------------ */
+
+
+template <typename BaseIterator>
+template <typename Predicate>
+inline
+FilteredIterator<BaseIterator>::
+FilteredIterator (Predicate p)
+               :
+               predicate (new PredicateTemplate<Predicate>(p))
+{};
+
+
+
+template <typename BaseIterator>
+template <typename Predicate>
+inline
+FilteredIterator<BaseIterator>::
+FilteredIterator (Predicate          p,
+                 const BaseIterator &bi)
+               :
+               BaseIterator (bi),
+               predicate (new PredicateTemplate<Predicate>(p))
+{
+  Assert ((state() != IteratorState::valid) || (*predicate) (*this),
+         ExcInvalidElement(bi));
+};
+
+
+
+template <typename BaseIterator>
+inline
+FilteredIterator<BaseIterator>::
+FilteredIterator (const FilteredIterator &fi)
+               :
+               BaseIterator (static_cast<BaseIterator>(fi)),
+               predicate (fi.predicate->clone ())
+{};
+
+
+
+template <typename BaseIterator>
+inline
+FilteredIterator<BaseIterator>::
+~FilteredIterator ()
+{
+  delete predicate;
+  predicate = 0;
+};
+
+
+
+template <typename BaseIterator>
+inline
+FilteredIterator<BaseIterator> &
+FilteredIterator<BaseIterator>::
+operator = (const FilteredIterator &fi)
+{
+  Assert ((fi.state() != IteratorState::valid) || (*predicate)(fi),
+         ExcInvalidElement(fi));
+  BaseIterator::operator = (fi);
+  return *this;
+};
+
+
+
+template <typename BaseIterator>
+inline
+FilteredIterator<BaseIterator> &
+FilteredIterator<BaseIterator>::
+operator = (const BaseIterator &bi)
+{
+  Assert ((bi.state() != IteratorState::valid) || (*predicate)(bi),
+         ExcInvalidElement(bi));  
+  BaseIterator::operator = (bi);
+  return *this;
+};
+
+
+
+template <typename BaseIterator>
+inline
+FilteredIterator<BaseIterator> &
+FilteredIterator<BaseIterator>::
+set_to_next_positive (const BaseIterator &bi)
+{
+  BaseIterator::operator = (bi);
+  while ((state() == IteratorState::valid) &&
+        ( ! (*predicate)(*this)))
+    BaseIterator::operator++ ();
+  
+  return *this;
+};
+
+
+
+template <typename BaseIterator>
+inline
+FilteredIterator<BaseIterator> &
+FilteredIterator<BaseIterator>::
+set_to_previous_positive (const BaseIterator &bi)
+{
+  BaseIterator::operator = (bi);
+  while ((state() == IteratorState::valid) &&
+        ( ! predicate(*this)))
+    BaseIterator::operator-- ();
+  
+  return *this;
+};
+
+
+
+template <typename BaseIterator>
+inline
+bool
+FilteredIterator<BaseIterator>::
+operator == (const FilteredIterator &fi) const
+{
+  return (static_cast<const BaseIterator &>(*this)
+         ==
+         static_cast<const BaseIterator &>(fi));
+};
+
+
+
+template <typename BaseIterator>
+inline
+bool
+FilteredIterator<BaseIterator>::
+operator != (const FilteredIterator &fi) const
+{
+  return (static_cast<const BaseIterator &>(*this)
+         !=
+         static_cast<const BaseIterator &>(fi));
+};
+
+
+
+template <typename BaseIterator>
+inline
+bool
+FilteredIterator<BaseIterator>::
+operator < (const FilteredIterator &fi) const
+{
+  return (static_cast<const BaseIterator &>(*this)
+         <
+         static_cast<const BaseIterator &>(fi));
+};
+
+
+
+
+template <typename BaseIterator>
+inline
+bool
+FilteredIterator<BaseIterator>::
+operator == (const BaseIterator &bi) const
+{
+  return (static_cast<const BaseIterator &>(*this) == bi);
+};
+
+
+
+template <typename BaseIterator>
+inline
+bool
+FilteredIterator<BaseIterator>::
+operator != (const BaseIterator &bi) const
+{
+  return (static_cast<const BaseIterator &>(*this) != bi);
+};
+
+
+
+template <typename BaseIterator>
+inline
+bool
+FilteredIterator<BaseIterator>::
+operator < (const BaseIterator &bi) const
+{
+  return (static_cast<const BaseIterator &>(*this) < bi);
+};
+
+
+template <typename BaseIterator>
+inline
+FilteredIterator<BaseIterator> &
+FilteredIterator<BaseIterator>::
+operator ++ ()
+{
+  if (state() == IteratorState::valid)
+    do
+      BaseIterator::operator++ ();
+    while ((state() == IteratorState::valid) &&
+          !(*predicate) (*this));
+  return *this;
+};
+
+
+
+template <typename BaseIterator>
+inline
+FilteredIterator<BaseIterator>
+FilteredIterator<BaseIterator>::
+operator ++ (int)
+{
+  const FilteredIterator old_state = *this;
+  
+  if (state() == IteratorState::valid)
+    do
+      BaseIterator::operator++ ();
+    while ((state() == IteratorState::valid) &&
+          !(*predicate) (*this));
+  return old_state;
+};
+
+
+
+
+template <typename BaseIterator>
+inline
+FilteredIterator<BaseIterator> &
+FilteredIterator<BaseIterator>::
+operator -- ()
+{
+  if (state() == IteratorState::valid)
+    do
+      BaseIterator::operator-- ();
+    while ((state() == IteratorState::valid) &&
+          !(*predicate) (*this));
+  return *this;
+};
+
+
+
+template <typename BaseIterator>
+inline
+FilteredIterator<BaseIterator>
+FilteredIterator<BaseIterator>::
+operator -- (int)
+{
+  const FilteredIterator old_state = *this;
+  
+  if (state() == IteratorState::valid)
+    do
+      BaseIterator::operator-- ();
+    while ((state() == IteratorState::valid) &&
+          !(*predicate) (*this));
+  return old_state;
+};
+
+
+
+template <typename BaseIterator>
+template <typename Predicate>
+inline
+FilteredIterator<BaseIterator>::PredicateTemplate<Predicate>::
+PredicateTemplate (const Predicate &predicate)
+               :
+               predicate (predicate)
+{};
+
+
+
+template <typename BaseIterator>
+template <typename Predicate>
+bool
+FilteredIterator<BaseIterator>::PredicateTemplate<Predicate>::
+operator () (const BaseIterator &bi) const
+{
+  return predicate(bi);
+};
+
+
+
+template <typename BaseIterator>
+template <typename Predicate>
+FilteredIterator<BaseIterator>::PredicateBase *
+FilteredIterator<BaseIterator>::PredicateTemplate<Predicate>::
+clone () const
+{
+  return new PredicateTemplate (predicate);
+};
+
+
+
+namespace IteratorFilters 
+{
+
+// ---------------- IteratorFilters::Active ---------
+
+  template <class Iterator>
+  inline
+  bool
+  Active::operator () (const Iterator &i) const
+  {
+    return (i->active());
+  };
+
+
+// ---------------- IteratorFilters::UserFlagSet ---------
+
+  template <class Iterator>
+  inline
+  bool
+  UserFlagSet::operator () (const Iterator &i) const
+  {
+    return (i->user_flag_set());
+  };
+
+
+// ---------------- IteratorFilters::UserFlagNotSet ---------
+
+  template <class Iterator>
+  inline
+  bool
+  UserFlagNotSet::operator () (const Iterator &i) const
+  {
+    return (! i->user_flag_set());
+  };
+
+
+// ---------------- IteratorFilters::LevelEqualTo ---------  
+  inline
+  LevelEqualTo::LevelEqualTo (const unsigned int level)
+                 :
+                 level (level)
+  {};
+
+
+
+  template <class Iterator>
+  inline
+  bool
+  LevelEqualTo::operator () (const Iterator &i) const
+  {
+    return (static_cast<unsigned int>(i->level()) == level);
+  };
+
+
+
+// ---------------- IteratorFilters::SubdomainEqualTo ---------
+  inline
+  SubdomainEqualTo::SubdomainEqualTo (const unsigned int subdomain_id)
+                 :
+                 subdomain_id (subdomain_id)
+  {};
+
+
+
+  template <class Iterator>
+  inline
+  bool
+  SubdomainEqualTo::operator () (const Iterator &i) const
+  {
+    return (static_cast<unsigned int>(i->subdomain_id()) == subdomain_id);
+  };
+};
+
+
+/*------------------------- filtered_iterator.h ------------------------*/
+#endif
+/*------------------------- filtered_iterator.h ------------------------*/
+
+
index 2645479070f8295cb39fae5a240eb385c5ed8cb6..9c668991a6719088296de67ef5613911a9066fba 100644 (file)
@@ -259,6 +259,14 @@ documentation, etc</a>.
 <h3>deal.II</h3>
 
 <ol>
+  <li> <p>
+       New: The <code class="class">FilteredIterator</code> class
+       provides a view on ranges of iterators by iterating over only
+       those objects that satisfy a certain predicate.
+       <br>
+       (GK 2002/01/07)
+       </p>
+
   <li> <p>
        Improved: It is now possible to read in unconnected domains
        through the <code class="class">GridIn</code> class, since
@@ -286,7 +294,6 @@ documentation, etc</a>.
        (GK 2001/12/07)
        </p>
 
-
   <li> <p>
        New: <code class="class">FiniteElement</code>::<code
        class="member">has_support_on_face</code> allows to check
diff --git a/tests/deal.II/filtered_iterator.cc b/tests/deal.II/filtered_iterator.cc
new file mode 100644 (file)
index 0000000..5f7ff76
--- /dev/null
@@ -0,0 +1,222 @@
+//-------------------------  filtered_iterator.cc  ------------------------
+//    $Id$
+//    Version: $Name$
+//
+//    Copyright (C) 2001, 2002 by the deal.II authors
+//
+//    This file is subject to QPL and may not be  distributed
+//    without copyright and license information. Please refer
+//    to the file deal.II/doc/license.html for the  text  and
+//    further information on this license.
+//
+//-------------------------  filtered_iterator.cc  ------------------------
+
+// check filtered iterators
+
+
+#include <base/logstream.h>
+#include <grid/tria.h>
+#include <grid/grid_generator.h>
+#include <grid/tria_iterator.h>
+#include <grid/tria_accessor.h>
+#include <grid/filtered_iterator.h>
+
+#include <fstream>
+#include <algorithm>
+#include <numeric>
+#include <cmath>
+
+
+std::ofstream logfile("filtered_iterator.output");
+
+
+DeclException2 (ExcNumberMismatch,
+               int, int,
+               << "The numbers " << arg1 << " and " << arg2
+               << " should be equation, but are not.");
+
+
+
+typedef Triangulation<2>::active_cell_iterator active_cell_iterator;
+
+template <typename Iterator>
+bool level_equal_to_3 (const Iterator c)
+{
+  return (static_cast<unsigned int>(c->level()) == 3);
+};
+
+
+
+template <typename Iterator>
+bool level_equal_to (const Iterator     c,
+                    const unsigned int level)
+{
+  return (static_cast<unsigned int>(c->level()) == level);
+};
+
+
+void test ()
+{
+  Triangulation<2> tria;
+  GridGenerator::hyper_cube(tria, -1, 1);
+  tria.refine_global (1);
+  tria.begin_active()->set_refine_flag ();
+  tria.execute_coarsening_and_refinement ();
+  tria.refine_global (2);
+
+                                  // we now have a number of cells,
+                                  // flag them with some subdomain
+                                  // ids based on their position, in
+                                  // particular we take the quadrant
+                                  // (octant)
+  active_cell_iterator cell = tria.begin_active (),
+                      endc = tria.end ();
+  for (; cell!=endc; ++cell)
+    {
+      unsigned int subdomain = 0;
+      for (unsigned int d=0; d<2; ++d)
+       if (cell->center()(d) > 0)
+         subdomain |= (1<<d);
+      Assert (subdomain < (1<<2), ExcInternalError());
+
+      cell->set_subdomain_id (subdomain);
+    };
+
+
+                                  // check 1: count number of cells
+                                  // on some level
+  if (true)
+    {
+      const IteratorFilters::LevelEqualTo predicate(3);
+      FilteredIterator<active_cell_iterator>
+       begin (predicate),
+       end   (predicate, tria.end());
+      begin.set_to_next_positive (tria.begin_active ());
+      
+      Assert (std::distance (begin, end) ==
+             static_cast<signed int>(tria.n_active_cells (3)),
+             ExcInternalError());
+      logfile << "Check 1: "
+             << (std::distance (begin, end) ==
+                 static_cast<signed int>(tria.n_active_cells (3))
+                 ?
+                 "OK" : "Failed")
+             << std::endl;
+    };
+
+
+                                  // check 2: count number of cells
+                                  // on some level in a different way
+  if (true)
+    {
+      FilteredIterator<active_cell_iterator>
+       begin (&level_equal_to_3<active_cell_iterator>,
+              tria.begin_active (3)),
+       end   (&level_equal_to_3<active_cell_iterator>,
+              tria.end());
+      
+      Assert (std::distance (begin, end) ==
+             static_cast<signed int>(tria.n_active_cells (3)),
+             ExcInternalError());
+      logfile << "Check 2: "
+             << (std::distance (begin, end) ==
+                 static_cast<signed int>(tria.n_active_cells (3))
+                 ?
+                 "OK" : "Failed")
+             << std::endl;
+    };
+
+
+                                  // check 3: count number of cells
+                                  // on some level in yet a different
+                                  // way
+  if (true)
+    {
+      FilteredIterator<active_cell_iterator>
+       begin (std::bind2nd (std::ptr_fun(&level_equal_to<active_cell_iterator>), 3),
+              tria.begin_active (3)),
+       end   (std::bind2nd (std::ptr_fun(&level_equal_to<active_cell_iterator>), 3),
+              tria.end());
+      
+      Assert (std::distance (begin, end) ==
+             static_cast<signed int>(tria.n_active_cells (3)),
+             ExcInternalError());
+      logfile << "Check 3: "
+             << (std::distance (begin, end) ==
+                 static_cast<signed int>(tria.n_active_cells (3))
+                 ?
+                 "OK" : "Failed")
+             << std::endl;
+    };
+
+
+                                  // check 4: and yet another possibility
+  if (true)
+    {
+      typedef FilteredIterator<active_cell_iterator> FI;
+            
+      Assert (std::distance (FI(std::bind2nd (std::ptr_fun(&level_equal_to<active_cell_iterator>), 3)).set_to_next_positive(tria.begin_active()),
+                            FI(std::bind2nd (std::ptr_fun(&level_equal_to<active_cell_iterator>), 3), tria.end())) ==
+             static_cast<signed int>(tria.n_active_cells (3)),
+             ExcInternalError());
+      logfile << "Check 4: "
+             << (std::distance (FI(std::bind2nd (std::ptr_fun(&level_equal_to<active_cell_iterator>), 3)).set_to_next_positive(tria.begin_active()),
+                                FI(std::bind2nd (std::ptr_fun(&level_equal_to<active_cell_iterator>), 3), tria.end())) ==
+                 static_cast<signed int>(tria.n_active_cells (3))
+                 ?
+                 "OK" : "Failed")
+             << std::endl;
+    };
+
+
+                                  // check 5: check that we loop over
+                                  // all cells with a given subdomain
+                                  // id
+  if (true)
+    {
+      typedef FilteredIterator<active_cell_iterator> FI;
+      const IteratorFilters::SubdomainEqualTo predicate(1);
+      FI cell (predicate);
+      cell.set_to_next_positive (tria.begin_active());
+      active_cell_iterator endc (tria.end());
+      active_cell_iterator cell1 = tria.begin_active ();
+      
+      while (cell1->subdomain_id () != 1)
+       ++cell1;
+
+      while (true)
+       {
+                                          // move filtered iterator ahead
+         ++cell;
+                                          // move unfiltered iterator
+                                          // ahead
+         ++cell1;
+         while ((cell1 != endc) &&
+                (cell1->subdomain_id () != 1))
+           ++cell1;
+
+         Assert (cell == cell1, ExcInternalError());
+         Assert (cell1 == cell, ExcInternalError());
+
+         if (cell.state() != IteratorState::valid)
+           break;
+       };
+      Assert (cell == endc, ExcInternalError());
+      Assert (cell1 == endc, ExcInternalError());
+      
+      logfile << "Check 5: OK" << std::endl;
+    };
+};
+
+
+int main ()
+{
+  logfile.precision(4);
+  deallog.attach(logfile);
+  deallog.depth_console(0);
+
+  test ();
+  
+  return 0;
+};
+
diff --git a/tests/deal.II/filtered_iterator.checked b/tests/deal.II/filtered_iterator.checked
new file mode 100644 (file)
index 0000000..81c0478
--- /dev/null
@@ -0,0 +1,6 @@
+
+Check 1: OK
+Check 2: OK
+Check 3: OK
+Check 4: OK
+Check 5: 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.