Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/vector.cpp

    rce5ac3 r042f82  
    4949 * \param *y array to second vector
    5050 * \param *cell_size 6-dimensional array with (xx, xy, yy, xz, yz, zz) entries specifying the periodic cell
    51  * \return \f$| x - y |^2\f$
     51 * \return \f$| x - y |\f$
    5252 */
    5353double Vector::PeriodicDistance(const Vector *y, const double *cell_size) const
     
    8484};
    8585
     86/** Calculates distance between this and another vector in a periodic cell.
     87 * \param *y array to second vector
     88 * \param *cell_size 6-dimensional array with (xx, xy, yy, xz, yz, zz) entries specifying the periodic cell
     89 * \return \f$| x - y |^2\f$
     90 */
     91double Vector::PeriodicDistanceSquared(const Vector *y, const double *cell_size) const
     92{
     93  double res = DistanceSquared(y), tmp, matrix[NDIM*NDIM];
     94  Vector Shiftedy, TranslationVector;
     95  int N[NDIM];
     96  matrix[0] = cell_size[0];
     97  matrix[1] = cell_size[1];
     98  matrix[2] = cell_size[3];
     99  matrix[3] = cell_size[1];
     100  matrix[4] = cell_size[2];
     101  matrix[5] = cell_size[4];
     102  matrix[6] = cell_size[3];
     103  matrix[7] = cell_size[4];
     104  matrix[8] = cell_size[5];
     105  // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells
     106  for (N[0]=-1;N[0]<=1;N[0]++)
     107    for (N[1]=-1;N[1]<=1;N[1]++)
     108      for (N[2]=-1;N[2]<=1;N[2]++) {
     109        // create the translation vector
     110        TranslationVector.Zero();
     111        for (int i=NDIM;i--;)
     112          TranslationVector.x[i] = (double)N[i];
     113        TranslationVector.MatrixMultiplication(matrix);
     114        // add onto the original vector to compare with
     115        Shiftedy.CopyVector(y);
     116        Shiftedy.AddVector(&TranslationVector);
     117        // get distance and compare with minimum so far
     118        tmp = DistanceSquared(&Shiftedy);
     119        if (tmp < res) res = tmp;
     120      }
     121  return (res);
     122};
     123
    86124/** Keeps the vector in a periodic cell, defined by the symmetric \a *matrix.
    87125 * \param *out ofstream for debugging messages
     
    221259double Vector::Angle(const Vector *y) const
    222260{
    223   return acos(this->ScalarProduct(y)/Norm()/y->Norm());
     261  double angle = this->ScalarProduct(y)/Norm()/y->Norm();
     262  // -1-MYEPSILON occured due to numerical imprecision, catch ...
     263  //cout << Verbose(2) << "INFO: acos(-1) = " << acos(-1) << ", acos(-1+MYEPSILON) = " << acos(-1+MYEPSILON) << ", acos(-1-MYEPSILON) = " << acos(-1-MYEPSILON) << "." << endl;
     264  if (angle < -1)
     265    angle = -1;
     266  if (angle > 1)
     267    angle = 1;
     268  return acos(angle);
    224269};
    225270
     
    313358};
    314359
    315 /** Prints a 3dim vector to a stream.
    316  * \param ost output stream
    317  * \param v Vector to be printed
    318  * \return output stream
    319  */
    320360ostream& operator<<(ostream& ost,Vector& m)
    321361{
     
    375415};
    376416
    377 /** Do a matrix multiplication with \a *matrix' inverse.
     417/** Calculate the inverse of a 3x3 matrix.
    378418 * \param *matrix NDIM_NDIM array
    379419 */
    380 void Vector::InverseMatrixMultiplication(double *A)
    381 {
    382   Vector C;
    383   double B[NDIM*NDIM];
     420double * Vector::InverseMatrix(double *A)
     421{
     422  double *B = (double *) Malloc(sizeof(double)*NDIM*NDIM, "Vector::InverseMatrix: *B");
    384423  double detA = RDET3(A);
    385424  double detAReci;
    386425
     426  for (int i=0;i<NDIM*NDIM;++i)
     427    B[i] = 0.;
    387428  // calculate the inverse B
    388429  if (fabs(detA) > MYEPSILON) {;  // RDET3(A) yields precisely zero if A irregular
     
    397438    B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]);    // A_32
    398439    B[8] =  detAReci*RDET2(A[0],A[1],A[3],A[4]);    // A_33
     440  }
     441  return B;
     442};
     443
     444/** Do a matrix multiplication with \a *matrix' inverse.
     445 * \param *matrix NDIM_NDIM array
     446 */
     447void Vector::InverseMatrixMultiplication(double *A)
     448{
     449  Vector C;
     450  double B[NDIM*NDIM];
     451  double detA = RDET3(A);
     452  double detAReci;
     453
     454  // calculate the inverse B
     455  if (fabs(detA) > MYEPSILON) {;  // RDET3(A) yields precisely zero if A irregular
     456    detAReci = 1./detA;
     457    B[0] =  detAReci*RDET2(A[4],A[5],A[7],A[8]);    // A_11
     458    B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]);    // A_12
     459    B[2] =  detAReci*RDET2(A[1],A[2],A[4],A[5]);    // A_13
     460    B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]);    // A_21
     461    B[4] =  detAReci*RDET2(A[0],A[2],A[6],A[8]);    // A_22
     462    B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]);    // A_23
     463    B[6] =  detAReci*RDET2(A[3],A[4],A[6],A[7]);    // A_31
     464    B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]);    // A_32
     465    B[8] =  detAReci*RDET2(A[0],A[1],A[3],A[4]);    // A_33
    399466
    400467    // do the matrix multiplication
     
    457524  x2.CopyVector(y3);
    458525  x2.SubtractVector(y2);
    459   if ((x1.Norm()==0) || (x2.Norm()==0)) {
     526  if ((fabs(x1.Norm()) < MYEPSILON) || (fabs(x2.Norm()) < MYEPSILON) || (fabs(x1.Angle(&x2)) < MYEPSILON)) {
    460527    cout << Verbose(4) << "Given vectors are linear dependent." << endl;
    461528    return false;
     
    491558  x2.CopyVector(y2);
    492559  Zero();
    493   if ((x1.Norm()==0) || (x2.Norm()==0)) {
     560  if ((fabs(x1.Norm()) < MYEPSILON) || (fabs(x2.Norm()) < MYEPSILON) || (fabs(x1.Angle(&x2)) < MYEPSILON)) {
    494561    cout << Verbose(4) << "Given vectors are linear dependent." << endl;
    495562    return false;
Note: See TracChangeset for help on using the changeset viewer.