Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/vector.cpp

    r112b09 r9d5ddf  
    88
    99#include "vector.hpp"
     10#include "VectorContent.hpp"
    1011#include "verbose.hpp"
    1112#include "World.hpp"
    1213#include "Helpers/Assert.hpp"
    1314#include "Helpers/fast_functions.hpp"
     15#include "Exceptions/MathException.hpp"
    1416
    1517#include <iostream>
     18#include <gsl/gsl_blas.h>
     19
    1620
    1721using namespace std;
     
    2428Vector::Vector()
    2529{
    26   x[0] = x[1] = x[2] = 0.;
     30  content = new VectorContent();
    2731};
    2832
     
    3337Vector::Vector(const Vector& src)
    3438{
    35   x[0] = src[0];
    36   x[1] = src[1];
    37   x[2] = src[2];
     39  content = new VectorContent();
     40  gsl_vector_memcpy(content->content, src.content->content);
    3841}
    3942
     
    4245Vector::Vector(const double x1, const double x2, const double x3)
    4346{
    44   x[0] = x1;
    45   x[1] = x2;
    46   x[2] = x3;
    47 };
     47  content = new VectorContent();
     48  gsl_vector_set(content->content,0,x1);
     49  gsl_vector_set(content->content,1,x2);
     50  gsl_vector_set(content->content,2,x3);
     51};
     52
     53Vector::Vector(VectorContent *_content) :
     54  content(_content)
     55{}
    4856
    4957/**
     
    5361  // check for self assignment
    5462  if(&src!=this){
    55     x[0] = src[0];
    56     x[1] = src[1];
    57     x[2] = src[2];
     63    gsl_vector_memcpy(content->content, src.content->content);
    5864  }
    5965  return *this;
     
    6268/** Desctructor of class vector.
    6369 */
    64 Vector::~Vector() {};
     70Vector::~Vector() {
     71  delete content;
     72};
    6573
    6674/** Calculates square of distance between this and another vector.
     
    7280  double res = 0.;
    7381  for (int i=NDIM;i--;)
    74     res += (x[i]-y[i])*(x[i]-y[i]);
     82    res += (at(i)-y[i])*(at(i)-y[i]);
    7583  return (res);
    7684};
     
    9098}
    9199
    92 /** Calculates distance between this and another vector in a periodic cell.
    93  * \param *y array to second vector
    94  * \param *cell_size 6-dimensional array with (xx, xy, yy, xz, yz, zz) entries specifying the periodic cell
    95  * \return \f$| x - y |\f$
    96  */
    97 double Vector::PeriodicDistance(const Vector &y, const double * const cell_size) const
    98 {
    99   double res = distance(y), tmp, matrix[NDIM*NDIM];
    100     Vector Shiftedy, TranslationVector;
    101     int N[NDIM];
    102     matrix[0] = cell_size[0];
    103     matrix[1] = cell_size[1];
    104     matrix[2] = cell_size[3];
    105     matrix[3] = cell_size[1];
    106     matrix[4] = cell_size[2];
    107     matrix[5] = cell_size[4];
    108     matrix[6] = cell_size[3];
    109     matrix[7] = cell_size[4];
    110     matrix[8] = cell_size[5];
    111     // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells
    112     for (N[0]=-1;N[0]<=1;N[0]++)
    113       for (N[1]=-1;N[1]<=1;N[1]++)
    114         for (N[2]=-1;N[2]<=1;N[2]++) {
    115           // create the translation vector
    116           TranslationVector.Zero();
    117           for (int i=NDIM;i--;)
    118             TranslationVector[i] = (double)N[i];
    119           TranslationVector.MatrixMultiplication(matrix);
    120           // add onto the original vector to compare with
    121           Shiftedy = y + TranslationVector;
    122           // get distance and compare with minimum so far
    123           tmp = distance(Shiftedy);
    124           if (tmp < res) res = tmp;
    125         }
    126     return (res);
    127 };
    128 
    129 /** Calculates distance between this and another vector in a periodic cell.
    130  * \param *y array to second vector
    131  * \param *cell_size 6-dimensional array with (xx, xy, yy, xz, yz, zz) entries specifying the periodic cell
    132  * \return \f$| x - y |^2\f$
    133  */
    134 double Vector::PeriodicDistanceSquared(const Vector &y, const double * const cell_size) const
    135 {
    136   double res = DistanceSquared(y), tmp, matrix[NDIM*NDIM];
    137     Vector Shiftedy, TranslationVector;
    138     int N[NDIM];
    139     matrix[0] = cell_size[0];
    140     matrix[1] = cell_size[1];
    141     matrix[2] = cell_size[3];
    142     matrix[3] = cell_size[1];
    143     matrix[4] = cell_size[2];
    144     matrix[5] = cell_size[4];
    145     matrix[6] = cell_size[3];
    146     matrix[7] = cell_size[4];
    147     matrix[8] = cell_size[5];
    148     // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells
    149     for (N[0]=-1;N[0]<=1;N[0]++)
    150       for (N[1]=-1;N[1]<=1;N[1]++)
    151         for (N[2]=-1;N[2]<=1;N[2]++) {
    152           // create the translation vector
    153           TranslationVector.Zero();
    154           for (int i=NDIM;i--;)
    155             TranslationVector[i] = (double)N[i];
    156           TranslationVector.MatrixMultiplication(matrix);
    157           // add onto the original vector to compare with
    158           Shiftedy = y + TranslationVector;
    159           // get distance and compare with minimum so far
    160           tmp = DistanceSquared(Shiftedy);
    161           if (tmp < res) res = tmp;
    162         }
    163     return (res);
    164 };
    165 
    166 /** Keeps the vector in a periodic cell, defined by the symmetric \a *matrix.
    167  * \param *out ofstream for debugging messages
    168  * Tries to translate a vector into each adjacent neighbouring cell.
    169  */
    170 void Vector::KeepPeriodic(const double * const matrix)
    171 {
    172   //  int N[NDIM];
    173   //  bool flag = false;
    174     //vector Shifted, TranslationVector;
    175   //  Log() << Verbose(1) << "Begin of KeepPeriodic." << endl;
    176   //  Log() << Verbose(2) << "Vector is: ";
    177   //  Output(out);
    178   //  Log() << Verbose(0) << endl;
    179     InverseMatrixMultiplication(matrix);
    180     for(int i=NDIM;i--;) { // correct periodically
    181       if (at(i) < 0) {  // get every coefficient into the interval [0,1)
    182         at(i) += ceil(at(i));
    183       } else {
    184         at(i) -= floor(at(i));
    185       }
    186     }
    187     MatrixMultiplication(matrix);
    188   //  Log() << Verbose(2) << "New corrected vector is: ";
    189   //  Output(out);
    190   //  Log() << Verbose(0) << endl;
    191   //  Log() << Verbose(1) << "End of KeepPeriodic." << endl;
    192 };
    193 
    194100/** Calculates scalar product between this and another vector.
    195101 * \param *y array to second vector
     
    199105{
    200106  double res = 0.;
    201   for (int i=NDIM;i--;)
    202     res += x[i]*y[i];
     107  gsl_blas_ddot(content->content, y.content->content, &res);
    203108  return (res);
    204109};
     
    214119{
    215120  Vector tmp;
    216   tmp[0] = x[1]* y[2] - x[2]* y[1];
    217   tmp[1] = x[2]* y[0] - x[0]* y[2];
    218   tmp[2] = x[0]* y[1] - x[1]* y[0];
     121  for(int i=NDIM;i--;)
     122    tmp[i] = at((i+1)%NDIM)*y[(i+2)%NDIM] - at((i+2)%NDIM)*y[(i+1)%NDIM];
    219123  (*this) = tmp;
    220124};
     
    309213bool Vector::IsZero() const
    310214{
    311   return (fabs(x[0])+fabs(x[1])+fabs(x[2]) < MYEPSILON);
     215  return (fabs(at(0))+fabs(at(1))+fabs(at(2)) < MYEPSILON);
    312216};
    313217
     
    338242  bool status = true;
    339243  for (int i=0;i<NDIM;i++) {
    340     if (fabs(x[i] - a[i]) > MYEPSILON)
     244    if (fabs(at(i) - a[i]) > MYEPSILON)
    341245      status = false;
    342246  }
     
    366270double& Vector::operator[](size_t i){
    367271  ASSERT(i<=NDIM && i>=0,"Vector Index out of Range");
    368   return x[i];
     272  return *gsl_vector_ptr (content->content, i);
    369273}
    370274
    371275const double& Vector::operator[](size_t i) const{
    372276  ASSERT(i<=NDIM && i>=0,"Vector Index out of Range");
    373   return x[i];
     277  return *gsl_vector_ptr (content->content, i);
    374278}
    375279
     
    382286}
    383287
    384 double* Vector::get(){
    385   return x;
     288VectorContent* Vector::get(){
     289  return content;
    386290}
    387291
     
    498402{
    499403  for (int i=NDIM;i--;)
    500     x[i] *= factor[i];
    501 };
    502 
     404    at(i) *= factor[i];
     405};
     406
     407void Vector::ScaleAll(const Vector &factor){
     408  gsl_vector_mul(content->content, factor.content->content);
     409}
    503410
    504411
    505412void Vector::Scale(const double factor)
    506413{
    507   for (int i=NDIM;i--;)
    508     x[i] *= factor;
    509 };
    510 
    511 /** Given a box by its matrix \a *M and its inverse *Minv the vector is made to point within that box.
    512  * \param *M matrix of box
    513  * \param *Minv inverse matrix
    514  */
    515 void Vector::WrapPeriodically(const double * const M, const double * const Minv)
    516 {
    517   MatrixMultiplication(Minv);
    518   // truncate to [0,1] for each axis
    519   for (int i=0;i<NDIM;i++) {
    520     //x[i] += 0.5;  // set to center of box
    521     while (x[i] >= 1.)
    522       x[i] -= 1.;
    523     while (x[i] < 0.)
    524       x[i] += 1.;
    525   }
    526   MatrixMultiplication(M);
     414  gsl_vector_scale(content->content,factor);
    527415};
    528416
     
    544432}
    545433
    546 /** Do a matrix multiplication.
    547  * \param *matrix NDIM_NDIM array
    548  */
    549 void Vector::MatrixMultiplication(const double * const M)
    550 {
    551   // do the matrix multiplication
    552   at(0) = M[0]*x[0]+M[3]*x[1]+M[6]*x[2];
    553   at(1) = M[1]*x[0]+M[4]*x[1]+M[7]*x[2];
    554   at(2) = M[2]*x[0]+M[5]*x[1]+M[8]*x[2];
    555 };
    556 
    557 /** Do a matrix multiplication with the \a *A' inverse.
    558  * \param *matrix NDIM_NDIM array
    559  */
    560 bool Vector::InverseMatrixMultiplication(const double * const A)
    561 {
    562   double B[NDIM*NDIM];
    563   double detA = RDET3(A);
    564   double detAReci;
    565 
    566   // calculate the inverse B
    567   if (fabs(detA) > MYEPSILON) {;  // RDET3(A) yields precisely zero if A irregular
    568     detAReci = 1./detA;
    569     B[0] =  detAReci*RDET2(A[4],A[5],A[7],A[8]);    // A_11
    570     B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]);    // A_12
    571     B[2] =  detAReci*RDET2(A[1],A[2],A[4],A[5]);    // A_13
    572     B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]);    // A_21
    573     B[4] =  detAReci*RDET2(A[0],A[2],A[6],A[8]);    // A_22
    574     B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]);    // A_23
    575     B[6] =  detAReci*RDET2(A[3],A[4],A[6],A[7]);    // A_31
    576     B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]);    // A_32
    577     B[8] =  detAReci*RDET2(A[0],A[1],A[3],A[4]);    // A_33
    578 
    579     // do the matrix multiplication
    580     at(0) = B[0]*x[0]+B[3]*x[1]+B[6]*x[2];
    581     at(1) = B[1]*x[0]+B[4]*x[1]+B[7]*x[2];
    582     at(2) = B[2]*x[0]+B[5]*x[1]+B[8]*x[2];
    583 
    584     return true;
    585   } else {
    586     return false;
    587   }
    588 };
    589 
    590 
    591434/** Creates this vector as the b y *factors' components scaled linear combination of the given three.
    592435 * this vector = x1*factors[0] + x2* factors[1] + x3*factors[2]
     
    616459  SubtractVector(x1);
    617460  for (int i=NDIM;i--;)
    618     result = result || (fabs(x[i]) > MYEPSILON);
     461    result = result || (fabs(at(i)) > MYEPSILON);
    619462
    620463  return result;
     
    677520void Vector::AddVector(const Vector &y)
    678521{
    679   for(int i=NDIM;i--;)
    680     x[i] += y[i];
     522  gsl_vector_add(content->content, y.content->content);
    681523}
    682524
     
    686528void Vector::SubtractVector(const Vector &y)
    687529{
    688   for(int i=NDIM;i--;)
    689     x[i] -= y[i];
    690 }
    691 
    692 /**
    693  * Checks whether this vector is within the parallelepiped defined by the given three vectors and
    694  * their offset.
    695  *
    696  * @param offest for the origin of the parallelepiped
    697  * @param three vectors forming the matrix that defines the shape of the parallelpiped
    698  */
    699 bool Vector::IsInParallelepiped(const Vector &offset, const double * const parallelepiped) const
    700 {
    701   Vector a = (*this)-offset;
    702   a.InverseMatrixMultiplication(parallelepiped);
    703   bool isInside = true;
    704 
    705   for (int i=NDIM;i--;)
    706     isInside = isInside && ((a[i] <= 1) && (a[i] >= 0));
    707 
    708   return isInside;
     530  gsl_vector_sub(content->content, y.content->content);
    709531}
    710532
Note: See TracChangeset for help on using the changeset viewer.