/** \mainpage The Rice Veector Library
Authors: Anthony D. Padula, Shannon D. Scott, and William W. Symes
Other contributors: Hala Dajani, Marco Enriquez, Dong Sun
RVL defines computational types realizing the principal concepts of calculus in vector spaces, in the form of C++ classes. Brief descriptions of the main classes follow. For a more complete description of each, and for a list of auxiliary classes and functions, see the TOMS paper and the class documentation.
- Vector spaces: mathematically, a set and a number field, together with a linear combination operation, satisfying certain axioms. The computational realization of an (infinite) set is a factory, that is, a object (RVL::Space) which will return a dynamically allocated data structure necessary to describe a vector, upon request. The linear combination operation is an attribute of the space. The vector spaces emulated by RVL are also equipped with an inner product, that is, are Hilbert spaces. The only coordinate-invariant choice of vector is the zero vector. Thus RVL::Space has four major attributes: a protected method building vector data, and three public methods: inner, linComb, and zero. The number field associated with the space is a template parameter of RVL::Space. RVL::Space is an abstract (pure virtual) base class. In principle, defining a usable (concrete) subclass involves implementing all four basic method, but RVL provides an partially implemented RVL::StdSpace subclass which takes care of most of this: the principal work involved in implementing a new space is the definition of the vector instance data structure (RVL::DataContainer, see below) appropriate to the space.
- Vectors: vector are members of spaces, hence are meaningless in themselves. Thus RVL::Vector is a concrete (fully implemented) class whose instances own (i) a reference to the RVL::Space of which the vector is a member, and (ii) instance data in the form of an RVL::DataContainer. RVL::Vector construction uses the RVL::Space method to acquire its RVL::DataContainer member, and delegates linear algebra methods to the RVL::Space of which it is a "member". Note that RVL::Vector is a concrete, non-virtual class, and the user will not need to implement subclasses - us as is!
- Linear Operators: a linear operator is a function. A function has a domain and a range, and a rule for assigning members of the former to members of the latter. A linear operator on a Hilbert space has an adjoint operator. [Strictly speaking, densely defined linear operators have well-defined adjoints, but for technical reasons all linear operators constructable in RVL are densely defined.] For these reasons, the RVL::LinearOp type has four key attributes: (i) getDomain() returns an RVL::Space, as does (ii) getRange(); (iii) applyOp takes input and output Vector arguments, as does (iv) applyAdjOp. RVL::LinearOp is a pure virtual base class, and all four main methods need to be implemented to create a usable subclass.
- Nonlinear Functions and Operators: these work roughly the same way. RVL uses "Functional" to describe scalar-valued functions, and "Operator" to describe vector-valued functions. Being functions, both RVL::Functional and RVL::Operator have a getDomain() method, and RVL::Operator has a getRange() method - the range of an RVL::Functional being the scalar field passed via template parameter. Those are the only public methods. Computation of value, derivative, adjoint derivative, etc. must be supplied to create a usable subclass, but these methods are protected, and user code does not access them directly. Instead, access to these computations proceeds through an evaluation class. RVL::FunctionalEvaluation and RVL::OperatorEvaluation combine a function and a vector, and return the value of the function at that vector, the value of its derivative (a linear operator), and (optionally) the value of the second derivative (as a bilinear operator), each these encapsulated as an appropriate RVL object. This device (introduced in the Hilbert Class Library and further developed in RVL) ensures that the various objects attached to a function at a point of its domain (value, derivative,...) remain coherent, and avoids a great deal of redundant effort otherwise necessary for correct programming. The evaluation technique has various consequences for the construction of functions, described in the TOMS paper. RVL::Functional and RVL::Operator are abstract base classes, and the various apply methods must be implemented to build instantiable subclasses. The evaluation classes are fully implemented.
- Data structures and low-level functions: RVL::DataContainers typically do not expose their data - otherwise, out-of-core data, or data distributed over the net, would not be representable. Instead, interaction with data occurs through evaluation of function objects (functions with persistent state). RVL supplies two hierarchies of function objects, based at RVL::FunctionObject and RVL::FunctionObjectConstEval (according to whether evaluation changes the RVL::DataContainer doing the evaluating, or not). RVL::DataContainer is also an abstract base, for which evaluation of the two types of function object must be defined in subclasses. These three hierarchies form an instance of the acyclic Visitor design pattern, with RVL::DataContainer as the Element type and the two function object classes as the Visitor type. Much of the programming effort in building an RVL application goes into designing and implementing RVL::DataContainer subclasses encapsulating various concrete data structures, and RVL::FunctionObject and RVL::FunctionObjectConstEval types to manipulate these data structures.
*/