OOF2: The Manual

Name

DoubleVec — A vector of double precision numbers

Synopses

C++ Synopsis

#include "common/doublevec.h" 
class DoubleVec {
  DoubleVec();
  DoubleVec(int size,
            double value= 0);

  DoubleVec(const DoubleVec& other);
  DoubleVec(DoubleVec&& other);
  DoubleVec(const std::initializer_list<double>& values);
// Assignment and initialization   DoubleVec& operator=(const DoubleVec& other);
  void zero();
  void clear();
  void unit();
  void resize(std::size_t size,
              double value= 0);

// Comparison   bool operator==(const DoubleVec& other) const;
  bool operator!=(const DoubleVec& other) const;
// Data access   int size() const;
  double& operator[](std::size_t index);
  double operator[](std::size_t index) const;
  DoubleVec subvec(std::size_t start,
                   std::size_t end) const;

  void subvec_copy(std::size_t destination,
                   const DoubleVec& other,
                   std::size_t pos,
                   std::size_t size);

// In-place arithmetic operators   DoubleVec& operator+=(const DoubleVec& other);
  DoubleVec& operator-=(const DoubleVec& other);
  DoubleVec& operator*=(double factor);
  DoubleVec& operator/=(double divisor);
  void axpy(double alpha,
            const DoubleVec& x);

// Non-in-place arithmetic operators   DoubleVec operator+(const DoubleVec& other) const;
  DoubleVec operator-(const DoubleVec& other) const;
  DoubleVec operator-() const;
  DoubleVec operator*(double factor) const;
  DoubleVec operator/(double divisor) const;
  friend DoubleVec operator*(double factor,
                             const DoubleVec& vector);

  double dot(const DoubleVec& other) const;
  double operator*(const DoubleVec& other) const;
  double norm();
// iterators typedef Eigen::VectorXd::iterator iterator; typedef Eigen::VectorXd::const_iterator const_iterator;   iterator begin();
  iterator end();
  const_iterator begin() const;
  const_iterator end() const;
}

Source Files

  • SRC/common/doublevec.C: C++ source code
  • SRC/common/doublevec.h: C++ header file
  • SRC/common/doublevec.swg: SWIG source code
  • SRC/common/doublvec.spy: Python code inserted into SWIG output

Description

DoubleVec is the class that OOF2 uses internally for vectors of double precision numbers. It is basically a wrapper for Eigen::vectorXd. It suppports all the usual arithmetic methods as well as STL style iteration in C++.

Python vs C++

A DoubleVec can be created in Python or returned from C++ to Python, and bulk operations (like adding two vectors) can be performed from Python. Element-by-element access is available in Python, but is discouraged, because it is slow.

In Python, import DoubleVec like this:

from ooflib.SWIG.common.doublevec import DoubleVec

The Python class wraps all of the members of the C++ class, and works identically, with the following exceptions:

  • The null constructor is not provided. An initial size must be provided. An initial value is optional:

    vec = doublevec.DoubleVec(10)    # ten zeros
    vac = doublevec.DoubleVec(10, 2) # ten twos
    voc = doublevec.DoubleVec()      # not allowed

  • There are no Python equivalents to the C++ iterator methods. This is because accessing indiviual vector elements from Python is inefficient and should be avoided. __getitem__ and __setitem__ are provided but should only be used for debugging.

  • The difference between C++ assignment (copying values) and Python assignment (reassigning references) shows up in a few important ways:

    • To make an independent copy of a DoubleVec, use the clone method:

      vec = DoubleVec(10)
      not_a_copy = vec        # refers to the same data as vec
      is_a_copy = vec.clone() # contains its own copy of vec's data 

      copy=vec.clone() in Python is the equivalent of copy=vec in C++.

      To copy the contents of a DoubleVec to an existing DoubleVec, use the copy_inplace method:

      this = doublevec.DoubleVec(10, 1)
      that = doublevec.DoubleVec(10, 2)
      this.copy_inplace(that) 

    • In Python, the relationship between in-place and not-in-place arithmetic operators is not the same as in C++. In C++, A = A+B and A += B have the same effect for two DoubleVecs A and B. In Python A+=B adds the contents of B to the vector A, and all other references to A will see the new values, just like they would in C++. However, in Python A = A+B creates a new vector A containing the sum of the old A and B. Other references to A will not see the new values.

Constructors

DoubleVec::DoubleVec(); 

The default constructor creates a zero length vector. It will need to resized in order to be useful.

DoubleVec(int size, double value=0); 

Create a vector of length size, initializing each entry to value. The initial value is 0 if it's not specified.

DoubleVec(const DoubleVec&);                      // copy constructor
DoubleVec(DoubleVec&&);                           // move constructor
DoubleVec(const std::initializer_list<double>&);  // initialization list constructor 

The copy, move, and initialization list constructors are inherited from the underlying Eigen::vectorXd class.

Methods

Assignment

DoubleVec& operator=(const DoubleVec&) 

The assignment operator is inherited from the underlying Eigen::vectorXd class.

Comparison

bool DoubleVec::operator==(const DoubleVec& other) const;
bool DoubleVec::operator!=(const DoubleVec& other) const; 

The comparison operators compare each data element individually.

Initialization

void DoubleVec::zero();
void DoubleVec::clear(); 

Set all vector entries to zero. The two forms are identical.

void DoubleVec::unit();

Set all vector entries to one.

void DoubleVec::resize(size_type size, double value=0); 

Resize the vector and set all entries to value, which defaults to 0. The previous contents of the vector will be lost.

Data Access

int DoubleVec::size() const; 

Return the number of components in the vector.

double& DoubleVec::operator[](std::size_t index);
double DoubleVec::operator[](std::size_t index) const;
double& DoubleVec::operator[](const DoubleVec::iterator&);
double DoubleVec::operator[](const DoubleVec::const_iterator&) const;
      

Return the contents at location index, or a reference to it if the DoubleVec is not const.

DoubleVec subvec(std::size_t start, std::size_t end) const;
void subvec_copy(std::size_t destination, const DoubleVec& other,
                 std::size_t pos, std::size_t size); 

The first form returns a new DoubleVec containing the data from *this from position start to end.

The second form copies data from the given DoubleVec other to *this. The data will be extracted from positions pos to pos+size in other, and will be inserted at positions destination to destination+size in *this.

Arithmetic

DoubleVec& DoubleVec::operator+=(const DoubleVec&);
DoubleVec& DoubleVec::operator-=(const DoubleVec&);
DoubleVec& DoubleVec::operator*=(double);
DoubleVec& DoubleVec::operator/=(double);
void DoubleVec::axpy(double alpha, const DoubleVec& x); 

These are the in-place arithmetic operators. axpy() multiplies vector x by alpha and adds it to *this.

DoubleVec DoubleVec::operator+(const DoubleVec& other) const;
DoubleVec DoubleVec::operator-(const DoubleVec& other) const;
DoubleVec DoubleVec::operator-() const;
DoubleVec DoubleVec::operator*(double factor) const;
DoubleVec operator*(double factor, const DoubleVec& other);
DoubleVec DoubleVec::operator/(double divisor) const; 

These out-of-place arithmetic operators return a new object. Scalar multiplication can be done from either the left or the right.

Dot Product and Norm

double DoubleVec::dot(const DoubleVec&) const;
double DoubleVec::operator*(const DoubleVec&) const; 

The dot product of two DoubleVecs A and B can be computed either as A.dot(B) or A*B.

double DoubleVec::norm() const { return data.norm(); } 

A.norm() is the L2 norm of A, or sqrt(A*A).

Iterators

DoubleVec::iterator DoubleVec::begin();
DoubleVec::iterator DoubleVec::end();
DoubleVec::const_iterator DoubleVec::begin() const;
DoubleVec::const_iterator DoubleVec::end() const; 

The iterator classes are typedefs of the Eigen iterators, and can be used like normal STL iterators. These loops are functionally identical:

DoubleVec A(10);

// Use a std::size_t (or int) index
for(std::size_t i=0; i<A.size(); i++)  
   A[i] = 2;

// Use an iterator as an index
for(DoubleVec::iterator i=A.begin(); i<A.end(); i++)
   A[i] = 2;

// Use an iterator as a pointer
for(DoubleVec::iterator i=A.begin(); i<A.end(); i++)
   *i = 2;

// Use a range-based loop
for(double& x : A)
   x = 2;