Skip to content
Snippets Groups Projects
SystemVector.h 13.55 KiB
// ============================================================================
// ==                                                                        ==
// == AMDiS - Adaptive multidimensional simulations                          ==
// ==                                                                        ==
// ============================================================================
// ==                                                                        ==
// ==  crystal growth group                                                  ==
// ==                                                                        ==
// ==  Stiftung caesar                                                       ==
// ==  Ludwig-Erhard-Allee 2                                                 ==
// ==  53175 Bonn                                                            ==
// ==  germany                                                               ==
// ==                                                                        ==
// ============================================================================
// ==                                                                        ==
// ==  http://www.caesar.de/cg/AMDiS                                         ==
// ==                                                                        ==
// ============================================================================

/** \file SystemVector.h */

#ifndef AMDIS_SYSTEMVECTOR_H
#define AMDIS_SYSTEMVECTOR_H

#include "MemoryManager.h"
#include "MatrixVector.h"
#include "DOFVector.h"
#include "CreatorInterface.h"
#include "Serializable.h"
#include "OpenMP.h"

namespace AMDiS {

  // ============================================================================
  // ===== class SystemVector ===================================================
  // ============================================================================

  /** \brief
   * A system vector is a vector of dof vectors used for vector valued
   * problems.
   */
  class SystemVector : public Serializable
  {
  public:
    MEMORY_MANAGED(SystemVector);

    /** \brief
     * Creator. 
     */
    class Creator 
      : public CreatorInterface<SystemVector> {
    public:
      MEMORY_MANAGED(Creator);

      /** \brief
       * Creators constructor.
       */
      Creator(const ::std::string &name_,
	      ::std::vector<FiniteElemSpace*> feSpace_, 
	      int size_) 
	: name(name_), feSpace(feSpace_), size(size_) 
      {};

      /** \brief
       * Destructor
       */
      virtual ~Creator() {};

      /** \brief
       * Implementation of CreatorInterface::create().
       */
      SystemVector *create() { 
	char number[10];
	::std::string numberedName;
	SystemVector *result = NEW SystemVector(name, feSpace, size);
	for (int i = 0; i < size; i++) {
	  sprintf(number, "[%d]", i);
	  numberedName = name + ::std::string(number);
	  result->setDOFVector(i, NEW DOFVector<double>(feSpace[i], numberedName));
	}
	return result; 
      };

      /** \brief
       * Implementation of CreatorInterface::free().
       */ 
      void free(SystemVector *vec) { 
	for (int i = 0; i < size; i++) {
	  DELETE vec->getDOFVector(i);
	  vec->setDOFVector(i, NULL);
	}
	DELETE vec;
      };

    private:
      /** \brief
       * Name of the system vector
       */
      ::std::string name;

      /** \brief
       * Finite element space used for creation.
       */
      ::std::vector<FiniteElemSpace*> feSpace;

      /** \brief
       * Number of component vectors to be created
       */
      int size;
    };

  public:
    /** \brief
     * Constructor.
     */
    SystemVector(const ::std::string& name_,
		 ::std::vector<FiniteElemSpace*> feSpace_, 
		 int size)
      : name(name_),
	feSpace(feSpace_),
	vectors(size)
      
    {
      vectors.set(NULL);
    };

    /** \brief
     * Copy Constructor.
     */
    SystemVector(const SystemVector& rhs)
      : name(rhs.name),
	feSpace(rhs.feSpace),
	vectors(rhs.vectors.getSize())
      
    {
      for (int i = 0; i < vectors.getSize();i++) {
	vectors[i] = new DOFVector<double>(*rhs.vectors[i]);
      }
    };
    virtual ~SystemVector() {};

    /** \brief
     * Sets \ref vectors[index] = vec.
     */ 
    inline void setDOFVector(int index, DOFVector<double> *vec) {
      TEST_EXIT_DBG(index < vectors.getSize())("invalid index\n");
      vectors[index] = vec;
    };

    /** \brief
     * Returns \ref vectors[index].
     */
    inline DOFVector<double> *getDOFVector(int index) {      
      TEST_EXIT_DBG(index < vectors.getSize())("invalid index\n");
      return vectors[index];
    };

    /** \brief
     * Returns \ref vectors[index].
     */
    inline const DOFVector<double> *getDOFVector(int index) const {
      TEST_EXIT_DBG(index < vectors.getSize())("invalid index\n");
      return vectors[index];
    };

    /** \brief
     * Returns sum of used vector sizes.
     */
    inline int getUsedSize() const {
      int i, totalSize = 0, size = vectors.getSize();
      for(i = 0; i < size; i++) {
	totalSize += vectors[i]->getUsedSize();
      }
      return totalSize;
    };

    /** \brief
     * Returns number of contained vectors.
     */
    inline int getNumVectors() const { 
      return vectors.getSize(); 
    };

    inline int getSize() const {
      return vectors.getSize();
    };

    /** \brief
     * Returns \ref feSpace.
     */
    inline FiniteElemSpace *getFESpace(int i) const { 
      return feSpace[i]; 
    };

    /** \brief
     * Here the system vector is interpreted as one large vector. The given
     * is used as a global index which indicates a local vector number and
     * a local index on this vector. The operator returns this local vector
     * at the local index.
     */
    inline double& operator[](int index) {
      int localIndex = index;
      int vectorIndex = 0;

      while(localIndex >= vectors[vectorIndex]->getUsedSize()) {
	localIndex -= vectors[vectorIndex++]->getUsedSize();
      }

      return (*(vectors[vectorIndex]))[localIndex];
    };

    /** \brief
     * For const access.
     */
    inline double operator[](int index) const {
      int localIndex = index;
      int vectorIndex = 0;

      while(localIndex >= vectors[vectorIndex]->getUsedSize()) {
	localIndex -= vectors[vectorIndex++]->getUsedSize();
      }

      return (*(vectors[vectorIndex]))[localIndex];
    };

    /** \brief
     * Sets all entries in all vectors to value.
     */
    inline void set(double value) {
      int size = vectors.getSize();
      for (int i = 0; i < size; i++) {
	vectors[i]->set(value);
      }
    };

    /** \brief
     * Sets all entries in all vectors to value.
     */
    inline SystemVector& operator=(double value) {
      int size = vectors.getSize();
      for (int i = 0; i < size; i++) {
	(*(vectors[i])) = value;
      }
      return *this;
    };

    /** \brief
     * Assignement operator.
     */
    inline SystemVector& operator=(const SystemVector& rhs) {
      TEST_EXIT_DBG(rhs.vectors.getSize() == vectors.getSize())("invalied sizes\n");
      int i, size = vectors.getSize();
      for(i = 0; i < size; i++) {
	(*(vectors[i])) = (*(rhs.getDOFVector(i)));
      }
      return *this;
    };

    void serialize(::std::ostream &out) {
      int i, size = vectors.getSize();
      out.write(reinterpret_cast<const char*>(&size), sizeof(int));
      for(i = 0; i < size; i++) {
	vectors[i]->serialize(out);
      }
    };

    void deserialize(::std::istream &in) {
      int i, size, oldSize = vectors.getSize();
      in.read(reinterpret_cast<char*>(&size), sizeof(int));
      vectors.resize(size);
      for(i = oldSize; i < size; i++) {
	vectors[i] = NEW DOFVector<double>(feSpace[i], "");
      }
      for(i = 0; i < size; i++) {
	vectors[i]->deserialize(in);
      }  
    };

    void copy(const SystemVector& rhs) {
      int i, size = vectors.getSize();
      TEST_EXIT_DBG(size == rhs.getNumVectors())("invalid sizes\n");
      for(i = 0; i < size; i++) {
	vectors[i]->copy(*(const_cast<SystemVector&>(rhs).getDOFVector(i)));
      }
    };

    void interpol(::std::vector<AbstractFunction<double, WorldVector<double> >*> *f) {
      int i, size = vectors.getSize();
      for(i = 0; i < size; i++) {
	vectors[i]->interpol((*f)[i]);
      }
    };

    void print() {
      int size = vectors.getSize();
      for (int i = 0; i < size; i++) {
	vectors[i]->print();
      }
    };



  protected:
    /** \brief
     * Name of the system vector
     */
    ::std::string name;

    /** \brief
     * Finite element space.
     */
    ::std::vector<FiniteElemSpace*> feSpace;

    /** \brief
     * Local dof vectors.
     */
    Vector<DOFVector<double>*> vectors;
  };

  /** \brief
   * multiplication with scalar
   */
  inline const SystemVector& operator*=(SystemVector& x, double d) {
    int size = x.getNumVectors();
    for (int i = 0; i < size; i++) {
      *(x.getDOFVector(i)) *= d;
    }
    return x;
  };

  /** \brief
   * scalar product
   */
  inline double operator*(SystemVector& x, SystemVector& y) {
    TEST_EXIT_DBG(x.getNumVectors() == y.getNumVectors())
          ("invalid size\n");
    double result = 0.0;
    int size = x.getNumVectors();
    for (int i = 0; i < size; i++) {
      result += (*x.getDOFVector(i)) * (*y.getDOFVector(i));
    };
    return result;
  };

  /** \brief
   * addition of two system vectors
   */
  inline const SystemVector& operator+=(SystemVector& x, 
					const SystemVector& y) 
  {
    TEST_EXIT_DBG(x.getNumVectors() == y.getNumVectors())
          ("invalid size\n");
    int size = x.getNumVectors();
    for (int i = 0; i < size; i++) {
      (*(x.getDOFVector(i))) += (*(y.getDOFVector(i)));
    }
    return x;
  };

  /**
   * subtraction of two system vectors.
   */
  inline const SystemVector& operator-=(SystemVector& x, 
					SystemVector& y) 
  {
    TEST_EXIT_DBG(x.getNumVectors() == y.getNumVectors())
          ("invalid size\n");
    int size = x.getNumVectors();
    for (int i = 0; i < size; i++) {
      (*(x.getDOFVector(i))) -= (*(y.getDOFVector(i)));
    }
    return x;
  };

  /** \brief
   * multiplication with a scalar
   */
  inline SystemVector operator*(SystemVector& x, double d) {
    SystemVector result = x;
    int size = x.getNumVectors();
    for (int i = 0; i < size; i++) {
      (*(result.getDOFVector(i))) *= d;
    }
    return result;
  };

  /** \brief
   * multiplication with a scalar
   */
  inline SystemVector operator*(double d, SystemVector& x) {
    SystemVector result = x;
    int size = x.getNumVectors();
    for (int i = 0; i < size; i++) {
      (*(result.getDOFVector(i))) *= d;
    }
    return result;
  };

  /** \brief
   * addition of two system vectors
   */
  inline SystemVector operator+(const SystemVector& x,
				const SystemVector& y)
  {
    TEST_EXIT_DBG(x.getNumVectors() == y.getNumVectors())
      ("invalid size\n");
    SystemVector result = x;
    int size = x.getNumVectors();
    for (int i = 0; i < size; i++) {
      (*(result.getDOFVector(i))) += (*(y.getDOFVector(i)));
    }
    return result;
  };

  /** \brief
   * Calls SystemVector::set(). Used for solving.
   */
  inline void set(SystemVector& x, double value) {
    x.set(value);
  }; 

  /** \brief
   * Calls SystemVector::set(). Used for solving.
   */
  inline void setValue(SystemVector& x, double value) {
    x.set(value);
  }; 

  /** \brief
   * Norm of system vector.
   */
  inline double norm(SystemVector* x) {
    double result = 0.0;
    int size = x->getNumVectors();
    for (int i = 0; i < size; i++) {
      result += x->getDOFVector(i)->squareNrm2();
    }
    return sqrt(result);
  };

  /** \brief
   * L2 norm of system vector.
   */
  inline double L2Norm(SystemVector* x) {
    double result = 0.0;
    int size = x->getNumVectors();
    for (int i = 0; i < size; i++) {
      result += x->getDOFVector(i)->L2NormSquare();
    }
    return sqrt(result);
  };

  /** \brief
   * H1 norm of system vector.
   */
  inline double H1Norm(SystemVector* x) {
    double result = 0.0;
    int size = x->getNumVectors();
    for (int i = 0; i < size; i++) {
      result += x->getDOFVector(i)->H1NormSquare();
    }
    return sqrt(result);
  };

  inline void mv(Matrix<DOFMatrix*> &matrix,
		 const SystemVector &x,
		 SystemVector       &result,
		 bool               add = false)
  {
    int size = x.getNumVectors();

    TEST_EXIT_DBG(size == result.getNumVectors())("incompatible sizes\n");
    TEST_EXIT_DBG(size == matrix.getNumRows())("incompatible sizes\n");
    TEST_EXIT_DBG(size == matrix.getNumCols())("incompatible sizes\n");
    
    for (int i = 0; i < size; i++) {
      if (!add) 
	result.getDOFVector(i)->set(0.0);

      for (int j = 0; j < size; j++) {
	if (matrix[i][j]) {
	  mv<double>(NoTranspose, 
		     *(matrix[i][j]), 
		     *(x.getDOFVector(j)), 
		     *(result.getDOFVector(i)),
		     true);
	}
      }
    }
  };

  /** \brief
   * y = a*x + y;
   */
  inline void axpy(double a, SystemVector& x, SystemVector& y)
  {
    TEST_EXIT_DBG(x.getNumVectors() == y.getNumVectors())
          ("invalid size\n");

    int size = x.getNumVectors();

    for (int i = 0; i < size; i++) {
      axpy(a, *(x.getDOFVector(i)), *(y.getDOFVector(i)));
    }
  };

  /** \brief
   * y = x + a*y
   */
  inline void xpay(double a, SystemVector& x, SystemVector& y)
  {
    TEST_EXIT_DBG(x.getNumVectors() == y.getNumVectors())
          ("invalid size\n");
    int size = x.getNumVectors();

    for (int i = 0; i < size; i++) {
      xpay(a, *(x.getDOFVector(i)), *(y.getDOFVector(i)));
    }
  }

  /** \brief
   * Returns SystemVector::getUsedSize().
   */
  inline int size(SystemVector* vec) {
    return vec->getUsedSize();
  };

  inline void print(SystemVector* vec) {
    vec->print();
  };

}

#endif // AMDIS_SYSTEMVECTOR_H