OOF2: The Manual

8.2. Indices and Iterators

[Warning] Warning

This section has not yet been updated for OOF2 version 2.1. A partial discussion of the differences between the 2.0 and 2.1 extension APIs may be found at http://www.ctcms.nist.gov/oof/oof2/property_api_21.html.

Before proceeding, it's necessary to take a diversion on the topic of indices and iterators.

It is often necessary to refer to the components of Fields, Fluxes, and Equations. OOF2's fieldindex module provides a generic mechanism for doing this, so that it's possible to loop over all of the components of an object without even having to know how many indices are required to specify a component. For example, it takes one index to specify a vector component, two for a tensor, and zero for a scalar, but all three cases can be handled identically.

Every Field, Flux, and Equation class has a function iterator() which returns an IteratorP object. The IteratorP can be used to refer to components of the compound object, and can also be incremented to refer to the next component. Some types of iterators take a Planarity argument which determines which components will be included when incrementing.

IteratorP is actually derived from a base class, IndexP, which can refer to a component but cannot be incremented or looped over components. It is used in situations in which the Planarity is unknown.

As an example, this OOF2 session prints all of the indices of a vector and a symmetric tensor:

% oof2 --text
>>> from oof2.SWIG.engine.planarity import ALL_INDICES
>>> it = Displacement.iterator(ALL_INDICES)
>>> while not it.end():
...    print it.components()
...    it.next()
>>> it = Stress.iterator(ALL_INDICES)
>>> while not it.end():
...    print it.components()
...    it.next()
[0, 0]
[1, 1]
[2, 2]
[1, 2]
[0, 2]
[0, 1]

The same task could be accomplished in C++ like this:[49]

for(IteratorP it = displacement->iterator(); !it.end(); ++it)
  std::cerr << it.components() << std::endl;

for(IteratorP it = stress.iterator(); !it.end(); ++it)
  std::cerr << it.components() << std::endl; 

IteratorP and IndexP actually are just wrappers for subclasses of FieldIterator and FieldIndex. The wrappers free the user from having to know the actual class being used, and handle memory allocation tasks. In some situations it's necessary and/or convenient to use the underlying class directly. The FieldIterator subclasses are:

[49] This is an irresponsible example because IteratorP::components() returns a std::vector<int>* that ought to be to be deleted.