diff --git a/applications/test/Circulator/Make/files b/applications/test/Circulator/Make/files
new file mode 100644
index 0000000000..b6a4e63dc2
--- /dev/null
+++ b/applications/test/Circulator/Make/files
@@ -0,0 +1,3 @@
+Test-Circulator.C
+
+EXE = $(FOAM_USER_APPBIN)/Test-Circulator
diff --git a/applications/test/Circulator/Make/options b/applications/test/Circulator/Make/options
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/applications/test/Circulator/Test-Circulator.C b/applications/test/Circulator/Test-Circulator.C
new file mode 100644
index 0000000000..19a21f6b79
--- /dev/null
+++ b/applications/test/Circulator/Test-Circulator.C
@@ -0,0 +1,268 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+Application
+ Test-circulator
+
+Description
+
+\*---------------------------------------------------------------------------*/
+
+#include "List.H"
+#include "ListOps.H"
+#include "face.H"
+#include "circulator.H"
+#include "const_circulator.H"
+
+
+using namespace Foam;
+
+
+// return
+// 0: no match
+// +1: identical
+// -1: same face, but different orientation
+label compare(const face& a, const face& b)
+{
+ // Basic rule: we assume that the sequence of labels in each list
+ // will be circular in the same order (but not necessarily in the
+ // same direction or from the same starting point).
+
+ // Trivial reject: faces are different size
+ label sizeA = a.size();
+ label sizeB = b.size();
+
+ if (sizeA != sizeB || sizeA == 0)
+ {
+ return 0;
+ }
+
+ const_circulator aCirc(a);
+ const_circulator bCirc(b);
+
+ // Rotate face b until its element matches the starting element of face a.
+ do
+ {
+ if (aCirc() == bCirc())
+ {
+ // Set bCirc fulcrum to its iterator and increment the iterators
+ bCirc.setFulcrumToIterator();
+ ++aCirc;
+ ++bCirc;
+
+ break;
+ }
+ } while (bCirc.circulate(CirculatorBase::CLOCKWISE));
+
+ // Look forwards around the faces for a match
+ do
+ {
+ if (aCirc() != bCirc())
+ {
+ break;
+ }
+ }
+ while
+ (
+ aCirc.circulate(CirculatorBase::CLOCKWISE),
+ bCirc.circulate(CirculatorBase::CLOCKWISE)
+ );
+
+ // If the circulator has stopped then faces a and b matched.
+ if (!aCirc.circulate())
+ {
+ return 1;
+ }
+ else
+ {
+ // Reset the circulators back to their fulcrum
+ aCirc.setIteratorToFulcrum();
+ bCirc.setIteratorToFulcrum();
+ ++aCirc;
+ --bCirc;
+ }
+
+ // Look backwards around the faces for a match
+ do
+ {
+ if (aCirc() != bCirc())
+ {
+ break;
+ }
+ }
+ while
+ (
+ aCirc.circulate(CirculatorBase::CLOCKWISE),
+ bCirc.circulate(CirculatorBase::ANTICLOCKWISE)
+ );
+
+ // If the circulator has stopped then faces a and b matched.
+ if (!aCirc.circulate())
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// Main program:
+
+int main(int argc, char *argv[])
+{
+ Info<< "Test the implementation of a circular iterator" << nl << endl;
+
+ Info<< "Test const circulator. First go forwards, then backwards."
+ << nl << endl;
+
+ face f(identity(4));
+
+ const_circulator cStart(f);
+
+ if (cStart.size()) do
+ {
+ Info<< "Iterate forwards over face (prev/curr/next) : "
+ << cStart.prev() << " / " << cStart() << " / " << cStart.next()
+ << endl;
+
+ } while (cStart.circulate(CirculatorBase::CLOCKWISE));
+
+ if (cStart.size()) do
+ {
+ Info<< "Iterate backwards over face : " << cStart() << endl;
+
+ } while (cStart.circulate(CirculatorBase::ANTICLOCKWISE));
+
+
+ Info<< nl << nl << "Test non-const circulator" << nl << endl;
+
+ circulator cStart2(f);
+
+ Info<< "Face before : " << f << endl;
+
+ if (cStart2.size()) do
+ {
+ Info<< "Iterate forwards over face (prev/curr/next) : "
+ << cStart2.prev() << " / " << cStart2() << " / " << cStart2.next()
+ << endl;
+
+ } while (cStart2.circulate(CirculatorBase::CLOCKWISE));
+
+ if (cStart2.size()) do
+ {
+ Info<< "Iterate forwards over face, adding 1 to each element : "
+ << cStart2();
+
+ cStart2() += 1;
+
+ Info<< " -> " << cStart2() << endl;
+ } while (cStart2.circulate(CirculatorBase::CLOCKWISE));
+
+ Info<< "Face after : " << f << endl;
+
+
+ Info<< nl << nl << "Compare two faces: " << endl;
+ face a(identity(5));
+ Info<< "Compare " << a << " and " << a << " Match = " << compare(a, a)
+ << endl;
+
+ face b(reverseList(a));
+ Info<< "Compare " << a << " and " << b << " Match = " << compare(a, b)
+ << endl;
+
+ face c(a);
+ c[4] = 3;
+ Info<< "Compare " << a << " and " << c << " Match = " << compare(a, c)
+ << endl;
+
+ face d(rotateList(a, 2));
+ Info<< "Compare " << a << " and " << d << " Match = " << compare(a, d)
+ << endl;
+
+ face g(labelList(5, 1));
+ face h(g);
+ Info<< "Compare " << g << " and " << h << " Match = " << compare(g, h)
+ << endl;
+
+ g[0] = 2;
+ h[3] = 2;
+ Info<< "Compare " << g << " and " << h << " Match = " << compare(g, h)
+ << endl;
+
+ g[4] = 3;
+ h[4] = 3;
+ Info<< "Compare " << g << " and " << h << " Match = " << compare(g, h)
+ << endl;
+
+ face face1(identity(1));
+ Info<< "Compare " << face1 << " and " << face1
+ << " Match = " << compare(face1, face1) << endl;
+
+ Info<< nl << nl << "Zero face" << nl << endl;
+
+ face fZero;
+ circulator cZero(fZero);
+
+ if (cZero.size()) do
+ {
+ Info<< "Iterate forwards over face : " << cZero() << endl;
+
+ } while (cZero.circulate(CirculatorBase::CLOCKWISE));
+
+ fZero = face(identity(5));
+
+ // circulator was invalidated so reset
+ cZero = circulator(fZero);
+
+ do
+ {
+ Info<< "Iterate forwards over face : " << cZero() << endl;
+
+ } while (cZero.circulate(CirculatorBase::CLOCKWISE));
+
+
+ Info<< nl << nl << "Simultaneously go forwards/backwards over face " << f
+ << nl << endl;
+
+ const_circulator circForward(f);
+ const_circulator circBackward(f);
+
+ if (circForward.size() && circBackward.size()) do
+ {
+ Info<< "Iterate over face forwards : " << circForward()
+ << ", backwards : " << circBackward() << endl;
+ }
+ while
+ (
+ circForward.circulate(CirculatorBase::CLOCKWISE),
+ circBackward.circulate(CirculatorBase::ANTICLOCKWISE)
+ );
+
+ Info<< "\nEnd\n" << endl;
+
+ return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/containers/Circulators/CirculatorBase/CirculatorBase.H b/src/OpenFOAM/containers/Circulators/CirculatorBase/CirculatorBase.H
new file mode 100644
index 0000000000..d1ab166bab
--- /dev/null
+++ b/src/OpenFOAM/containers/Circulators/CirculatorBase/CirculatorBase.H
@@ -0,0 +1,77 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+Class
+ Foam::CirculatorBase
+
+Description
+ Base class for circulators
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef CirculatorBase_H
+#define CirculatorBase_H
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+
+/*---------------------------------------------------------------------------*\
+ Class CirculatorBase Declaration
+\*---------------------------------------------------------------------------*/
+
+class CirculatorBase
+{
+public:
+
+ // Public data
+
+ //- Direction type enumeration
+ enum direction
+ {
+ NONE,
+ CLOCKWISE,
+ ANTICLOCKWISE
+ };
+
+
+ // Constructors
+
+ //- Construct null
+ CirculatorBase(){};
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/containers/Circulators/circulator/circulator.H b/src/OpenFOAM/containers/Circulators/circulator/circulator.H
new file mode 100644
index 0000000000..15188df982
--- /dev/null
+++ b/src/OpenFOAM/containers/Circulators/circulator/circulator.H
@@ -0,0 +1,227 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+Class
+ Foam::circulator
+
+Description
+ Walks over a container as if it were circular. The container must have the
+ following members defined:
+ - value_type
+ - size_type
+ - difference_type
+ - iterator
+ - reference
+
+ Examples
+
+ \code
+ face f(identity(5));
+
+ // Construct circulator from the face
+ circulator circ(f);
+
+ // First check that the circulator has a size to iterate over.
+ // Then circulate around the list starting and finishing at the fulcrum.
+ if (circ.size()) do
+ {
+ circ() += 1;
+
+ Info<< "Iterate forwards over face : " << circ() << endl;
+
+ } while (circ.circulate(CirculatorBase::CLOCKWISE));
+ \endcode
+
+SourceFiles
+ circulatorI.H
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef circulator_H
+#define circulator_H
+
+#include "CirculatorBase.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+
+/*---------------------------------------------------------------------------*\
+ Class circulator Declaration
+\*---------------------------------------------------------------------------*/
+
+template
+class circulator
+:
+ public CirculatorBase
+{
+
+protected:
+
+ // Protected data
+
+ //- Iterator pointing to the beginning of the container
+ typename ContainerType::iterator begin_;
+
+ //- Iterator pointing to the end of the container
+ typename ContainerType::iterator end_;
+
+ //- Random access iterator for traversing ContainerType.
+ typename ContainerType::iterator iter_;
+
+ //- Iterator holding the location of the fulcrum (start and end) of
+ // the container. Used to decide when the iterator should stop
+ // circulating over the container
+ typename ContainerType::iterator fulcrum_;
+
+
+public:
+
+ // STL type definitions
+
+ //- Type of values ContainerType contains.
+ typedef typename ContainerType::value_type value_type;
+
+ //- The type that can represent the size of ContainerType
+ typedef typename ContainerType::size_type size_type;
+
+ //- The type that can represent the difference between any two
+ // iterator objects.
+ typedef typename ContainerType::difference_type difference_type;
+
+ //- Random access iterator for traversing ContainerType.
+ typedef typename ContainerType::iterator iterator;
+
+ //- Type that can be used for storing into
+ // ContainerType::value_type objects.
+ typedef typename ContainerType::reference reference;
+
+
+ // Constructors
+
+ //- Construct null
+ inline circulator();
+
+ //- Construct from a container.
+ inline explicit circulator(ContainerType& container);
+
+ //- Construct from two iterators
+ inline circulator(const iterator& begin, const iterator& end);
+
+ //- Construct as copy
+ inline circulator(const circulator&);
+
+
+ //- Destructor
+ ~circulator();
+
+
+ // Member Functions
+
+ //- Return the range of the iterator
+ inline size_type size() const;
+
+ //- Circulate around the list in the given direction
+ inline bool circulate(const CirculatorBase::direction dir = NONE);
+
+ //- Set the fulcrum to the current position of the iterator
+ inline void setFulcrumToIterator();
+
+ //- Set the iterator to the current position of the fulcrum
+ inline void setIteratorToFulcrum();
+
+ //- Return the distance between the iterator and the fulcrum. This is
+ // equivalent to the number of rotations of the circulator.
+ inline difference_type nRotations() const;
+
+ //- Dereference the next iterator and return
+ inline reference next() const;
+
+ //- Dereference the previous iterator and return
+ inline reference prev() const;
+
+
+ // Member Operators
+
+ //- Assignment operator for circulators that operate on the same
+ // container type
+ inline void operator=(const circulator&);
+
+ //- Prefix increment. Increments the iterator.
+ // Sets the iterator to the beginning of the container if it reaches
+ // the end
+ inline circulator& operator++();
+
+ //- Postfix increment. Increments the iterator.
+ // Sets the iterator to the beginning of the container if it reaches
+ // the end
+ inline circulator operator++(int);
+
+ //- Prefix decrement. Decrements the iterator.
+ // Sets the iterator to the end of the container if it reaches
+ // the beginning
+ inline circulator& operator--();
+
+ //- Postfix decrement. Decrements the iterator.
+ // Sets the iterator to the end of the container if it reaches
+ // the beginning
+ inline circulator operator--(int);
+
+ //- Check for equality of this iterator with another iterator that
+ // operate on the same container type
+ inline bool operator==(const circulator& c) const;
+
+ //- Check for inequality of this iterator with another iterator that
+ // operate on the same container type
+ inline bool operator!=(const circulator& c) const;
+
+ //- Dereference the iterator and return
+ inline reference operator*() const;
+
+ //- Dereference the iterator and return
+ inline reference operator()() const;
+
+ //- Return the difference between this iterator and another iterator
+ // that operate on the same container type
+ inline difference_type operator-
+ (
+ const circulator& c
+ ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "circulatorI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/containers/Circulators/circulator/circulatorI.H b/src/OpenFOAM/containers/Circulators/circulator/circulatorI.H
new file mode 100644
index 0000000000..e39f1fa27d
--- /dev/null
+++ b/src/OpenFOAM/containers/Circulators/circulator/circulatorI.H
@@ -0,0 +1,290 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+\*---------------------------------------------------------------------------*/
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+template
+Foam::circulator::circulator()
+:
+ CirculatorBase(),
+ begin_(0),
+ end_(0),
+ iter_(0),
+ fulcrum_(0)
+{}
+
+
+template
+Foam::circulator::circulator(ContainerType& container)
+:
+ CirculatorBase(),
+ begin_(container.begin()),
+ end_(container.end()),
+ iter_(begin_),
+ fulcrum_(begin_)
+{}
+
+
+template
+Foam::circulator::circulator
+(
+ const iterator& begin,
+ const iterator& end
+)
+:
+ CirculatorBase(),
+ begin_(begin),
+ end_(end),
+ iter_(begin),
+ fulcrum_(begin)
+{}
+
+
+template
+Foam::circulator::circulator
+(
+ const circulator& rhs
+)
+:
+ CirculatorBase(),
+ begin_(rhs.begin_),
+ end_(rhs.end_),
+ iter_(rhs.iter_),
+ fulcrum_(rhs.fulcrum_)
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * //
+
+template
+Foam::circulator::~circulator()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+template
+typename Foam::circulator::size_type
+Foam::circulator::size() const
+{
+ return end_ - begin_;
+}
+
+
+template
+bool Foam::circulator::circulate
+(
+ const CirculatorBase::direction dir
+)
+{
+ if (dir == CirculatorBase::CLOCKWISE)
+ {
+ operator++();
+ }
+ else if (dir == CirculatorBase::ANTICLOCKWISE)
+ {
+ operator--();
+ }
+
+ return !(iter_ == fulcrum_);
+}
+
+
+template
+void Foam::circulator::setFulcrumToIterator()
+{
+ fulcrum_ = iter_;
+}
+
+
+template
+void Foam::circulator::setIteratorToFulcrum()
+{
+ iter_ = fulcrum_;
+}
+
+
+template
+typename Foam::circulator::difference_type
+Foam::circulator::nRotations() const
+{
+ return (iter_ - fulcrum_);
+}
+
+
+template
+typename Foam::circulator::reference
+Foam::circulator::next() const
+{
+ if (iter_ == end_ - 1)
+ {
+ return *begin_;
+ }
+
+ return *(iter_ + 1);
+}
+
+
+template
+typename Foam::circulator::reference
+Foam::circulator::prev() const
+{
+ if (iter_ == begin_)
+ {
+ return *(end_ - 1);
+ }
+
+ return *(iter_ - 1);
+}
+
+
+// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
+
+template
+void Foam::circulator::operator=
+(
+ const circulator& rhs
+)
+{
+ // Check for assignment to self
+ if (this == &rhs)
+ {
+ FatalErrorIn
+ (
+ "Foam::circulator::operator="
+ "(const Foam::circulator&)"
+ ) << "Attempted assignment to self"
+ << abort(FatalError);
+ }
+
+ begin_ = rhs.begin_;
+ end_ = rhs.end_;
+ iter_ = rhs.iter_;
+ fulcrum_ = rhs.fulcrum_;
+}
+
+
+template
+Foam::circulator&
+Foam::circulator::operator++()
+{
+ ++iter_;
+ if (iter_ == end_)
+ {
+ iter_ = begin_;
+ }
+
+ return *this;
+}
+
+
+template
+Foam::circulator
+Foam::circulator::operator++(int)
+{
+ circulator tmp = *this;
+ ++(*this);
+ return tmp;
+}
+
+
+template
+Foam::circulator&
+Foam::circulator::operator--()
+{
+ if (iter_ == begin_)
+ {
+ iter_ = end_;
+ }
+ --iter_;
+
+ return *this;
+}
+
+
+template
+Foam::circulator
+Foam::circulator::operator--(int)
+{
+ circulator tmp = *this;
+ --(*this);
+ return tmp;
+}
+
+
+template
+bool Foam::circulator::operator==
+(
+ const circulator& c
+) const
+{
+ return
+ (
+ begin_ == c.begin_
+ && end_ == c.end_
+ && iter_ == c.iter_
+ && fulcrum_ == c.fulcrum_
+ );
+}
+
+
+template
+bool Foam::circulator::operator!=
+(
+ const circulator& c
+) const
+{
+ return !(*this == c);
+}
+
+
+template
+typename Foam::circulator::reference
+Foam::circulator::operator*() const
+{
+ return *iter_;
+}
+
+
+template
+typename Foam::circulator::reference
+Foam::circulator::operator()() const
+{
+ return operator*();
+}
+
+
+template
+typename Foam::circulator::difference_type
+Foam::circulator::operator-
+(
+ const circulator& c
+) const
+{
+ return iter_ - c.iter_;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/containers/Circulators/const_circulator/const_circulator.H b/src/OpenFOAM/containers/Circulators/const_circulator/const_circulator.H
new file mode 100644
index 0000000000..fc8ba633aa
--- /dev/null
+++ b/src/OpenFOAM/containers/Circulators/const_circulator/const_circulator.H
@@ -0,0 +1,247 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+Class
+ Foam::const_circulator
+
+Description
+ Walks over a container as if it were circular. The container must have the
+ following members defined:
+ - value_type
+ - size_type
+ - difference_type
+ - const_iterator
+ - const_reference
+
+ Examples:
+
+ \code
+ face f(identity(5));
+
+ // Construct circulator from the face
+ const_circulator circ(f);
+
+ // First check that the circulator has a size to iterate over.
+ // Then circulate around the list starting and finishing at the fulcrum.
+ if (circ.size()) do
+ {
+ Info<< "Iterate forwards over face : " << circ() << endl;
+
+ } while (circ.circulate(CirculatorBase::CLOCKWISE));
+ \endcode
+
+ \code
+ face f(identity(5));
+
+ const_circulator circClockwise(f);
+ const_circulator circAnticlockwise(f);
+
+ if (circClockwise.size() && circAnticlockwise.size()) do
+ {
+ Info<< "Iterate forward over face :" << circClockwise() << endl;
+ Info<< "Iterate backward over face:" << circAnticlockwise() << endl;
+ }
+ while
+ (
+ circClockwise.circulate(CirculatorBase::CLOCKWISE),
+ circAnticlockwise.circulate(CirculatorBase::ANTICLOCKWISE)
+ );
+ \endcode
+
+SourceFiles
+ const_circulatorI.H
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef const_circulator_H
+#define const_circulator_H
+
+#include "CirculatorBase.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+
+/*---------------------------------------------------------------------------*\
+ Class const_circulator Declaration
+\*---------------------------------------------------------------------------*/
+
+template
+class const_circulator
+:
+ public CirculatorBase
+{
+
+protected:
+
+ // Protected data
+
+ //- Iterator pointing to the beginning of the container
+ typename ContainerType::const_iterator begin_;
+
+ //- Iterator pointing to the end of the container
+ typename ContainerType::const_iterator end_;
+
+ //- Iterator
+ typename ContainerType::const_iterator iter_;
+
+ //- Iterator holding the location of the fulcrum (start and end) of
+ // the container. Used to decide when the iterator should stop
+ // circulating over the container
+ typename ContainerType::const_iterator fulcrum_;
+
+
+public:
+
+ // STL type definitions
+
+ //- Type of values ContainerType contains.
+ typedef typename ContainerType::value_type value_type;
+
+ //- The type that can represent the size of ContainerType
+ typedef typename ContainerType::size_type size_type;
+
+ //- The type that can represent the difference between any two
+ // iterator objects.
+ typedef typename ContainerType::difference_type difference_type;
+
+ //- Random access iterator for traversing ContainerType.
+ typedef typename ContainerType::const_iterator const_iterator;
+
+ //- Type that can be used for storing into
+ // const ContainerType::value_type objects.
+ typedef typename ContainerType::const_reference const_reference;
+
+
+ // Constructors
+
+ //- Construct null
+ inline const_circulator();
+
+ //- Construct from a container.
+ inline explicit const_circulator(const ContainerType& container);
+
+ //- Construct from two iterators
+ inline const_circulator
+ (
+ const const_iterator& begin,
+ const const_iterator& end
+ );
+
+ //- Construct as copy
+ inline const_circulator(const const_circulator&);
+
+
+ //- Destructor
+ ~const_circulator();
+
+
+ // Member Functions
+
+ //- Return the range of the iterator
+ inline size_type size() const;
+
+ //- Circulate around the list in the given direction
+ inline bool circulate(const CirculatorBase::direction dir = NONE);
+
+ //- Set the fulcrum to the current position of the iterator
+ inline void setFulcrumToIterator();
+
+ //- Set the iterator to the current position of the fulcrum
+ inline void setIteratorToFulcrum();
+
+ //- Return the distance between the iterator and the fulcrum. This is
+ // equivalent to the number of rotations of the circulator.
+ inline difference_type nRotations() const;
+
+ //- Dereference the next iterator and return
+ inline const_reference next() const;
+
+ //- Dereference the previous iterator and return
+ inline const_reference prev() const;
+
+
+ // Member Operators
+
+ //- Assignment operator for circulators that operate on the same
+ // container type
+ inline void operator=(const const_circulator&);
+
+ //- Prefix increment. Increments the iterator.
+ // Sets the iterator to the beginning of the container if it reaches
+ // the end
+ inline const_circulator& operator++();
+
+ //- Postfix increment. Increments the iterator.
+ // Sets the iterator to the beginning of the container if it reaches
+ // the end
+ inline const_circulator operator++(int);
+
+ //- Prefix decrement. Decrements the iterator.
+ // Sets the iterator to the end of the container if it reaches
+ // the beginning
+ inline const_circulator& operator--();
+
+ //- Postfix decrement. Decrements the iterator.
+ // Sets the iterator to the end of the container if it reaches
+ // the beginning
+ inline const_circulator operator--(int);
+
+ //- Check for equality of this iterator with another iterator that
+ // operate on the same container type
+ inline bool operator==(const const_circulator& c) const;
+
+ //- Check for inequality of this iterator with another iterator that
+ // operate on the same container type
+ inline bool operator!=(const const_circulator& c) const;
+
+ //- Dereference the iterator and return
+ inline const_reference operator*() const;
+
+ //- Dereference the iterator and return
+ inline const_reference operator()() const;
+
+ //- Return the difference between this iterator and another iterator
+ // that operate on the same container type
+ inline difference_type operator-
+ (
+ const const_circulator& c
+ ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "const_circulatorI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/containers/Circulators/const_circulator/const_circulatorI.H b/src/OpenFOAM/containers/Circulators/const_circulator/const_circulatorI.H
new file mode 100644
index 0000000000..47cdb69f06
--- /dev/null
+++ b/src/OpenFOAM/containers/Circulators/const_circulator/const_circulatorI.H
@@ -0,0 +1,293 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+\*---------------------------------------------------------------------------*/
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+template
+Foam::const_circulator::const_circulator()
+:
+ CirculatorBase(),
+ begin_(0),
+ end_(0),
+ iter_(0),
+ fulcrum_(0)
+{}
+
+
+template
+Foam::const_circulator::const_circulator
+(
+ const ContainerType& container
+)
+:
+ CirculatorBase(),
+ begin_(container.begin()),
+ end_(container.end()),
+ iter_(begin_),
+ fulcrum_(begin_)
+{}
+
+
+template
+Foam::const_circulator::const_circulator
+(
+ const const_iterator& begin,
+ const const_iterator& end
+)
+:
+ CirculatorBase(),
+ begin_(begin),
+ end_(end),
+ iter_(begin),
+ fulcrum_(begin)
+{}
+
+
+template
+Foam::const_circulator::const_circulator
+(
+ const const_circulator& rhs
+)
+:
+ CirculatorBase(),
+ begin_(rhs.begin_),
+ end_(rhs.end_),
+ iter_(rhs.iter_),
+ fulcrum_(rhs.fulcrum_)
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * //
+
+template
+Foam::const_circulator::~const_circulator()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+template
+typename Foam::const_circulator::size_type
+Foam::const_circulator::size() const
+{
+ return end_ - begin_;
+}
+
+
+template
+bool Foam::const_circulator::circulate
+(
+ const CirculatorBase::direction dir
+)
+{
+ if (dir == CirculatorBase::CLOCKWISE)
+ {
+ operator++();
+ }
+ else if (dir == CirculatorBase::ANTICLOCKWISE)
+ {
+ operator--();
+ }
+
+ return !(iter_ == fulcrum_);
+}
+
+
+template
+void Foam::const_circulator::setFulcrumToIterator()
+{
+ fulcrum_ = iter_;
+}
+
+
+template
+void Foam::const_circulator::setIteratorToFulcrum()
+{
+ iter_ = fulcrum_;
+}
+
+
+template
+typename Foam::const_circulator::difference_type
+Foam::const_circulator::nRotations() const
+{
+ return (iter_ - fulcrum_);
+}
+
+
+template
+typename Foam::const_circulator::const_reference
+Foam::const_circulator::next() const
+{
+ if (iter_ == end_ - 1)
+ {
+ return *begin_;
+ }
+
+ return *(iter_ + 1);
+}
+
+
+template
+typename Foam::const_circulator::const_reference
+Foam::const_circulator::prev() const
+{
+ if (iter_ == begin_)
+ {
+ return *(end_ - 1);
+ }
+
+ return *(iter_ - 1);
+}
+
+
+// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
+
+template
+void Foam::const_circulator::operator=
+(
+ const const_circulator& rhs
+)
+{
+ // Check for assignment to self
+ if (this == &rhs)
+ {
+ FatalErrorIn
+ (
+ "Foam::const_circulator::operator="
+ "(const Foam::const_circulator&)"
+ ) << "Attempted assignment to self"
+ << abort(FatalError);
+ }
+
+ begin_ = rhs.begin_;
+ end_ = rhs.end_;
+ iter_ = rhs.iter_;
+ fulcrum_ = rhs.fulcrum_;
+}
+
+
+template
+Foam::const_circulator&
+Foam::const_circulator::operator++()
+{
+ ++iter_;
+ if (iter_ == end_)
+ {
+ iter_ = begin_;
+ }
+
+ return *this;
+}
+
+
+template
+Foam::const_circulator
+Foam::const_circulator::operator++(int)
+{
+ const_circulator tmp = *this;
+ ++(*this);
+ return tmp;
+}
+
+
+template
+Foam::const_circulator&
+Foam::const_circulator::operator--()
+{
+ if (iter_ == begin_)
+ {
+ iter_ = end_;
+ }
+ --iter_;
+
+ return *this;
+}
+
+
+template
+Foam::const_circulator
+Foam::const_circulator::operator--(int)
+{
+ const_circulator tmp = *this;
+ --(*this);
+ return tmp;
+}
+
+
+template
+bool Foam::const_circulator::operator==
+(
+ const const_circulator& c
+) const
+{
+ return
+ (
+ begin_ == c.begin_
+ && end_ == c.end_
+ && iter_ == c.iter_
+ && fulcrum_ == c.fulcrum_
+ );
+}
+
+
+template
+bool Foam::const_circulator::operator!=
+(
+ const const_circulator& c
+) const
+{
+ return !(*this == c);
+}
+
+
+template
+typename Foam::const_circulator::const_reference
+Foam::const_circulator::operator*() const
+{
+ return *iter_;
+}
+
+
+template
+typename Foam::const_circulator::const_reference
+Foam::const_circulator::operator()() const
+{
+ return operator*();
+}
+
+
+template
+typename Foam::const_circulator::difference_type
+Foam::const_circulator::operator-
+(
+ const const_circulator& c
+) const
+{
+ return iter_ - c.iter_;
+}
+
+
+// ************************************************************************* //