Changes in src/vector.cpp [edb93c:9c20aa]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/vector.cpp
redb93c r9c20aa 5 5 */ 6 6 7 8 7 #include "molecules.hpp" 9 8 … … 29 28 double Vector::DistanceSquared(const Vector *y) const 30 29 { 31 32 33 34 30 double res = 0.; 31 for (int i=NDIM;i--;) 32 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 33 return (res); 35 34 }; 36 35 … … 41 40 double Vector::Distance(const Vector *y) const 42 41 { 43 44 45 46 42 double res = 0.; 43 for (int i=NDIM;i--;) 44 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 45 return (sqrt(res)); 47 46 }; 48 47 … … 54 53 double Vector::PeriodicDistance(const Vector *y, const double *cell_size) const 55 54 { 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 55 double res = Distance(y), tmp, matrix[NDIM*NDIM]; 56 Vector Shiftedy, TranslationVector; 57 int N[NDIM]; 58 matrix[0] = cell_size[0]; 59 matrix[1] = cell_size[1]; 60 matrix[2] = cell_size[3]; 61 matrix[3] = cell_size[1]; 62 matrix[4] = cell_size[2]; 63 matrix[5] = cell_size[4]; 64 matrix[6] = cell_size[3]; 65 matrix[7] = cell_size[4]; 66 matrix[8] = cell_size[5]; 67 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells 68 for (N[0]=-1;N[0]<=1;N[0]++) 69 for (N[1]=-1;N[1]<=1;N[1]++) 70 for (N[2]=-1;N[2]<=1;N[2]++) { 71 // create the translation vector 72 TranslationVector.Zero(); 73 for (int i=NDIM;i--;) 74 TranslationVector.x[i] = (double)N[i]; 75 TranslationVector.MatrixMultiplication(matrix); 76 // add onto the original vector to compare with 77 Shiftedy.CopyVector(y); 78 Shiftedy.AddVector(&TranslationVector); 79 // get distance and compare with minimum so far 80 tmp = Distance(&Shiftedy); 81 if (tmp < res) res = tmp; 82 } 83 return (res); 85 84 }; 86 85 … … 92 91 double Vector::PeriodicDistanceSquared(const Vector *y, const double *cell_size) const 93 92 { 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 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); 123 122 }; 124 123 … … 129 128 void Vector::KeepPeriodic(ofstream *out, double *matrix) 130 129 { 131 // 132 // 133 134 135 // 136 // 137 // 138 // 139 140 141 142 if (TestVector.x[i] < 0) {// get every coefficient into the interval [0,1)143 144 145 146 147 148 149 150 // 151 // 152 // 153 // 130 // int N[NDIM]; 131 // bool flag = false; 132 //vector Shifted, TranslationVector; 133 Vector TestVector; 134 // *out << Verbose(1) << "Begin of KeepPeriodic." << endl; 135 // *out << Verbose(2) << "Vector is: "; 136 // Output(out); 137 // *out << endl; 138 TestVector.CopyVector(this); 139 TestVector.InverseMatrixMultiplication(matrix); 140 for(int i=NDIM;i--;) { // correct periodically 141 if (TestVector.x[i] < 0) { // get every coefficient into the interval [0,1) 142 TestVector.x[i] += ceil(TestVector.x[i]); 143 } else { 144 TestVector.x[i] -= floor(TestVector.x[i]); 145 } 146 } 147 TestVector.MatrixMultiplication(matrix); 148 CopyVector(&TestVector); 149 // *out << Verbose(2) << "New corrected vector is: "; 150 // Output(out); 151 // *out << endl; 152 // *out << Verbose(1) << "End of KeepPeriodic." << endl; 154 153 }; 155 154 … … 160 159 double Vector::ScalarProduct(const Vector *y) const 161 160 { 162 163 164 165 161 double res = 0.; 162 for (int i=NDIM;i--;) 163 res += x[i]*y->x[i]; 164 return (res); 166 165 }; 167 166 168 167 169 168 /** Calculates VectorProduct between this and another vector. 170 * 171 * 172 * 173 * 169 * -# returns the Product in place of vector from which it was initiated 170 * -# ATTENTION: Only three dim. 171 * \param *y array to vector with which to calculate crossproduct 172 * \return \f$ x \times y \f& 174 173 */ 175 174 void Vector::VectorProduct(const Vector *y) 176 175 { 177 178 179 180 181 176 Vector tmp; 177 tmp.x[0] = x[1]* (y->x[2]) - x[2]* (y->x[1]); 178 tmp.x[1] = x[2]* (y->x[0]) - x[0]* (y->x[2]); 179 tmp.x[2] = x[0]* (y->x[1]) - x[1]* (y->x[0]); 180 this->CopyVector(&tmp); 182 181 183 182 }; … … 190 189 void Vector::ProjectOntoPlane(const Vector *y) 191 190 { 192 Vector tmp; 193 tmp.CopyVector(y); 194 tmp.Normalize(); 195 tmp.Scale(ScalarProduct(&tmp)); 196 this->SubtractVector(&tmp); 197 }; 198 199 /** Calculates the intersection point between a line defined by \a *LineVector and \a *LineVector2 and a plane defined by \a *Normal and \a *PlaneOffset. 200 * According to [Bronstein] the vectorial plane equation is: 201 * -# \f$\stackrel{r}{\rightarrow} \cdot \stackrel{N}{\rightarrow} + D = 0\f$, 202 * where \f$\stackrel{r}{\rightarrow}\f$ is the vector to be testet, \f$\stackrel{N}{\rightarrow}\f$ is the plane's normal vector and 203 * \f$D = - \stackrel{a}{\rightarrow} \stackrel{N}{\rightarrow}\f$, the offset with respect to origin, if \f$\stackrel{a}{\rightarrow}\f$, 204 * is an offset vector onto the plane. The line is parametrized by \f$\stackrel{x}{\rightarrow} + k \stackrel{t}{\rightarrow}\f$, where 205 * \f$\stackrel{x}{\rightarrow}\f$ is the offset and \f$\stackrel{t}{\rightarrow}\f$ the directional vector (NOTE: No need to normalize 206 * the latter). Inserting the parametrized form into the plane equation and solving for \f$k\f$, which we insert then into the parametrization 207 * of the line yields the intersection point on the plane. 208 * \param *out output stream for debugging 209 * \param *PlaneNormal Plane's normal vector 210 * \param *PlaneOffset Plane's offset vector 211 * \param *LineVector first vector of line 212 * \param *LineVector2 second vector of line 213 * \return true - \a this contains intersection point on return, false - line is parallel to plane 214 */ 215 bool Vector::GetIntersectionWithPlane(ofstream *out, Vector *PlaneNormal, Vector *PlaneOffset, Vector *LineVector, Vector *LineVector2) 216 { 217 double factor; 218 Vector Direction; 219 220 // find intersection of a line defined by Offset and Direction with a plane defined by triangle 221 Direction.CopyVector(LineVector2); 222 Direction.SubtractVector(LineVector); 223 if (Direction.ScalarProduct(PlaneNormal) < MYEPSILON) 224 return false; 225 factor = LineVector->ScalarProduct(PlaneNormal)*(-PlaneOffset->ScalarProduct(PlaneNormal))/(Direction.ScalarProduct(PlaneNormal)); 226 Direction.Scale(factor); 227 CopyVector(LineVector); 228 SubtractVector(&Direction); 229 230 // test whether resulting vector really is on plane 231 Direction.CopyVector(this); 232 Direction.SubtractVector(PlaneOffset); 233 if (Direction.ScalarProduct(PlaneNormal) > MYEPSILON) 234 return true; 235 else 236 return false; 237 }; 238 239 /** Calculates the intersection of the two lines that are both on the same plane. 240 * Note that we do not check whether they are on the same plane. 241 * \param *out output stream for debugging 242 * \param *Line1a first vector of first line 243 * \param *Line1b second vector of first line 244 * \param *Line2a first vector of second line 245 * \param *Line2b second vector of second line 246 * \return true - \a this will contain the intersection on return, false - lines are parallel 247 */ 248 bool Vector::GetIntersectionOfTwoLinesOnPlane(ofstream *out, Vector *Line1a, Vector *Line1b, Vector *Line2a, Vector *Line2b) 249 { 250 double k1,a1,h1,b1,k2,a2,h2,b2; 251 // equation for line 1 252 if (fabs(Line1a->x[0] - Line2a->x[0]) < MYEPSILON) { 253 k1 = 0; 254 h1 = 0; 255 } else { 256 k1 = (Line1a->x[1] - Line2a->x[1])/(Line1a->x[0] - Line2a->x[0]); 257 h1 = (Line1a->x[2] - Line2a->x[2])/(Line1a->x[0] - Line2a->x[0]); 258 } 259 a1 = 0.5*((Line1a->x[1] + Line2a->x[1]) - k1*(Line1a->x[0] + Line2a->x[0])); 260 b1 = 0.5*((Line1a->x[2] + Line2a->x[2]) - h1*(Line1a->x[0] + Line2a->x[0])); 261 262 // equation for line 2 263 if (fabs(Line2a->x[0] - Line2a->x[0]) < MYEPSILON) { 264 k1 = 0; 265 h1 = 0; 266 } else { 267 k1 = (Line2a->x[1] - Line2a->x[1])/(Line2a->x[0] - Line2a->x[0]); 268 h1 = (Line2a->x[2] - Line2a->x[2])/(Line2a->x[0] - Line2a->x[0]); 269 } 270 a1 = 0.5*((Line2a->x[1] + Line2a->x[1]) - k1*(Line2a->x[0] + Line2a->x[0])); 271 b1 = 0.5*((Line2a->x[2] + Line2a->x[2]) - h1*(Line2a->x[0] + Line2a->x[0])); 272 273 // calculate cross point 274 if (fabs((a1-a2)*(h1-h2) - (b1-b2)*(k1-k2)) < MYEPSILON) { 275 x[0] = (a2-a1)/(k1-k2); 276 x[1] = (k1*a2-k2*a1)/(k1-k2); 277 x[2] = (h1*b2-h2*b1)/(h1-h2); 278 *out << Verbose(4) << "Lines do intersect at " << this << "." << endl; 279 return true; 280 } else { 281 *out << Verbose(4) << "Lines do not intersect." << endl; 282 return false; 283 } 191 Vector tmp; 192 tmp.CopyVector(y); 193 tmp.Normalize(); 194 tmp.Scale(ScalarProduct(&tmp)); 195 this->SubtractVector(&tmp); 284 196 }; 285 197 … … 290 202 double Vector::Projection(const Vector *y) const 291 203 { 292 204 return (ScalarProduct(y)); 293 205 }; 294 206 … … 298 210 double Vector::Norm() const 299 211 { 300 double res = 0.; 301 for (int i=NDIM;i--;) 302 res += this->x[i]*this->x[i]; 303 return (sqrt(res)); 304 }; 305 306 /** Calculates squared norm of this vector. 307 * \return \f$|x|^2\f$ 308 */ 309 double Vector::NormSquared() const 310 { 311 return (ScalarProduct(this)); 212 double res = 0.; 213 for (int i=NDIM;i--;) 214 res += this->x[i]*this->x[i]; 215 return (sqrt(res)); 312 216 }; 313 217 … … 316 220 void Vector::Normalize() 317 221 { 318 319 320 321 322 323 222 double res = 0.; 223 for (int i=NDIM;i--;) 224 res += this->x[i]*this->x[i]; 225 if (fabs(res) > MYEPSILON) 226 res = 1./sqrt(res); 227 Scale(&res); 324 228 }; 325 229 … … 328 232 void Vector::Zero() 329 233 { 330 331 234 for (int i=NDIM;i--;) 235 this->x[i] = 0.; 332 236 }; 333 237 … … 336 240 void Vector::One(double one) 337 241 { 338 339 242 for (int i=NDIM;i--;) 243 this->x[i] = one; 340 244 }; 341 245 … … 344 248 void Vector::Init(double x1, double x2, double x3) 345 249 { 346 x[0] = x1; 347 x[1] = x2; 348 x[2] = x3; 250 x[0] = x1; 251 x[1] = x2; 252 x[2] = x3; 253 }; 254 255 /** Checks whether vector has all components zero. 256 * @return true - vector is zero, false - vector is not 257 */ 258 bool Vector::IsNull() 259 { 260 return (fabs(x[0]+x[1]+x[2]) < MYEPSILON); 349 261 }; 350 262 … … 355 267 double Vector::Angle(const Vector *y) const 356 268 { 357 double norm1 = Norm(), norm2 = y->Norm(); 358 double angle = 1; 359 if ((fabs(norm1) > MYEPSILON) && (fabs(norm2) > MYEPSILON)) 360 angle = this->ScalarProduct(y)/norm1/norm2; 269 double angle = this->ScalarProduct(y)/Norm()/y->Norm(); 361 270 // -1-MYEPSILON occured due to numerical imprecision, catch ... 362 271 //cout << Verbose(2) << "INFO: acos(-1) = " << acos(-1) << ", acos(-1+MYEPSILON) = " << acos(-1+MYEPSILON) << ", acos(-1-MYEPSILON) = " << acos(-1-MYEPSILON) << "." << endl; … … 365 274 if (angle > 1) 366 275 angle = 1; 367 276 return acos(angle); 368 277 }; 369 278 … … 374 283 void Vector::RotateVector(const Vector *axis, const double alpha) 375 284 { 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 285 Vector a,y; 286 // normalise this vector with respect to axis 287 a.CopyVector(this); 288 a.Scale(Projection(axis)); 289 SubtractVector(&a); 290 // construct normal vector 291 y.MakeNormalVector(axis,this); 292 y.Scale(Norm()); 293 // scale normal vector by sine and this vector by cosine 294 y.Scale(sin(alpha)); 295 Scale(cos(alpha)); 296 // add scaled normal vector onto this vector 297 AddVector(&y); 298 // add part in axis direction 299 AddVector(&a); 391 300 }; 392 301 … … 398 307 Vector& operator+=(Vector& a, const Vector& b) 399 308 { 400 401 309 a.AddVector(&b); 310 return a; 402 311 }; 403 312 /** factor each component of \a a times a double \a m. … … 408 317 Vector& operator*=(Vector& a, const double m) 409 318 { 410 411 412 }; 413 414 /** Sums two vectors \a 319 a.Scale(m); 320 return a; 321 }; 322 323 /** Sums two vectors \a and \b component-wise. 415 324 * \param a first vector 416 325 * \param b second vector … … 419 328 Vector& operator+(const Vector& a, const Vector& b) 420 329 { 421 422 423 424 330 Vector *x = new Vector; 331 x->CopyVector(&a); 332 x->AddVector(&b); 333 return *x; 425 334 }; 426 335 … … 432 341 Vector& operator*(const Vector& a, const double m) 433 342 { 434 435 436 437 343 Vector *x = new Vector; 344 x->CopyVector(&a); 345 x->Scale(m); 346 return *x; 438 347 }; 439 348 … … 444 353 bool Vector::Output(ofstream *out) const 445 354 { 446 447 448 449 450 451 452 453 454 455 456 457 }; 458 459 ostream& operator<<(ostream& ost, Vector& m)460 { 461 462 463 464 465 466 467 468 355 if (out != NULL) { 356 *out << "("; 357 for (int i=0;i<NDIM;i++) { 358 *out << x[i]; 359 if (i != 2) 360 *out << ","; 361 } 362 *out << ")"; 363 return true; 364 } else 365 return false; 366 }; 367 368 ostream& operator<<(ostream& ost, const Vector& m) 369 { 370 ost << "("; 371 for (int i=0;i<NDIM;i++) { 372 ost << m.x[i]; 373 if (i != 2) 374 ost << ","; 375 } 376 ost << ")"; 377 return ost; 469 378 }; 470 379 … … 474 383 void Vector::Scale(double **factor) 475 384 { 476 477 385 for (int i=NDIM;i--;) 386 x[i] *= (*factor)[i]; 478 387 }; 479 388 480 389 void Vector::Scale(double *factor) 481 390 { 482 483 391 for (int i=NDIM;i--;) 392 x[i] *= *factor; 484 393 }; 485 394 486 395 void Vector::Scale(double factor) 487 396 { 488 489 397 for (int i=NDIM;i--;) 398 x[i] *= factor; 490 399 }; 491 400 … … 495 404 void Vector::Translate(const Vector *trans) 496 405 { 497 498 406 for (int i=NDIM;i--;) 407 x[i] += trans->x[i]; 499 408 }; 500 409 … … 504 413 void Vector::MatrixMultiplication(double *M) 505 414 { 506 507 508 509 510 511 512 513 514 }; 515 516 /** Calculate the inverse of a 3x3 matrix.415 Vector C; 416 // do the matrix multiplication 417 C.x[0] = M[0]*x[0]+M[3]*x[1]+M[6]*x[2]; 418 C.x[1] = M[1]*x[0]+M[4]*x[1]+M[7]*x[2]; 419 C.x[2] = M[2]*x[0]+M[5]*x[1]+M[8]*x[2]; 420 // transfer the result into this 421 for (int i=NDIM;i--;) 422 x[i] = C.x[i]; 423 }; 424 425 /** Do a matrix multiplication with \a *matrix' inverse. 517 426 * \param *matrix NDIM_NDIM array 518 427 */ 519 double * Vector::InverseMatrix(double *A)520 {521 double *B = (double *) Malloc(sizeof(double)*NDIM*NDIM, "Vector::InverseMatrix: *B");522 double detA = RDET3(A);523 double detAReci;524 525 for (int i=0;i<NDIM*NDIM;++i)526 B[i] = 0.;527 // calculate the inverse B528 if (fabs(detA) > MYEPSILON) {; // RDET3(A) yields precisely zero if A irregular529 detAReci = 1./detA;530 B[0] = detAReci*RDET2(A[4],A[5],A[7],A[8]); // A_11531 B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]); // A_12532 B[2] = detAReci*RDET2(A[1],A[2],A[4],A[5]); // A_13533 B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]); // A_21534 B[4] = detAReci*RDET2(A[0],A[2],A[6],A[8]); // A_22535 B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]); // A_23536 B[6] = detAReci*RDET2(A[3],A[4],A[6],A[7]); // A_31537 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]); // A_32538 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]); // A_33539 }540 return B;541 };542 543 /** Do a matrix multiplication with the \a *A' inverse.544 * \param *matrix NDIM_NDIM array545 */546 428 void Vector::InverseMatrixMultiplication(double *A) 547 429 { 548 549 550 551 552 553 554 if (fabs(detA) > MYEPSILON) {;// RDET3(A) yields precisely zero if A irregular555 556 B[0] = detAReci*RDET2(A[4],A[5],A[7],A[8]);// A_11557 B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]);// A_12558 B[2] = detAReci*RDET2(A[1],A[2],A[4],A[5]);// A_13559 B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]);// A_21560 B[4] = detAReci*RDET2(A[0],A[2],A[6],A[8]);// A_22561 B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]);// A_23562 B[6] = detAReci*RDET2(A[3],A[4],A[6],A[7]);// A_31563 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]);// A_32564 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]);// A_33565 566 567 568 569 570 571 572 573 574 cerr << "ERROR: inverse of matrix does not exists: det A = " << detA << "." << endl;575 430 Vector C; 431 double B[NDIM*NDIM]; 432 double detA = RDET3(A); 433 double detAReci; 434 435 // calculate the inverse B 436 if (fabs(detA) > MYEPSILON) {; // RDET3(A) yields precisely zero if A irregular 437 detAReci = 1./detA; 438 B[0] = detAReci*RDET2(A[4],A[5],A[7],A[8]); // A_11 439 B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]); // A_12 440 B[2] = detAReci*RDET2(A[1],A[2],A[4],A[5]); // A_13 441 B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]); // A_21 442 B[4] = detAReci*RDET2(A[0],A[2],A[6],A[8]); // A_22 443 B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]); // A_23 444 B[6] = detAReci*RDET2(A[3],A[4],A[6],A[7]); // A_31 445 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]); // A_32 446 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]); // A_33 447 448 // do the matrix multiplication 449 C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2]; 450 C.x[1] = B[1]*x[0]+B[4]*x[1]+B[7]*x[2]; 451 C.x[2] = B[2]*x[0]+B[5]*x[1]+B[8]*x[2]; 452 // transfer the result into this 453 for (int i=NDIM;i--;) 454 x[i] = C.x[i]; 455 } else { 456 cerr << "ERROR: inverse of matrix does not exists!" << endl; 457 } 576 458 }; 577 459 … … 586 468 void Vector::LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors) 587 469 { 588 589 470 for(int i=NDIM;i--;) 471 x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i]; 590 472 }; 591 473 … … 595 477 void Vector::Mirror(const Vector *n) 596 478 { 597 598 projection = ScalarProduct(n)/n->ScalarProduct(n);// remove constancy from n (keep as logical one)599 600 601 602 603 604 605 606 607 479 double projection; 480 projection = ScalarProduct(n)/n->ScalarProduct(n); // remove constancy from n (keep as logical one) 481 // withdraw projected vector twice from original one 482 cout << Verbose(1) << "Vector: "; 483 Output((ofstream *)&cout); 484 cout << "\t"; 485 for (int i=NDIM;i--;) 486 x[i] -= 2.*projection*n->x[i]; 487 cout << "Projected vector: "; 488 Output((ofstream *)&cout); 489 cout << endl; 608 490 }; 609 491 … … 617 499 bool Vector::MakeNormalVector(const Vector *y1, const Vector *y2, const Vector *y3) 618 500 { 619 620 621 622 623 624 625 626 627 628 629 // 630 // 631 // 632 // 633 // 634 // 635 636 637 638 639 640 641 501 Vector x1, x2; 502 503 x1.CopyVector(y1); 504 x1.SubtractVector(y2); 505 x2.CopyVector(y3); 506 x2.SubtractVector(y2); 507 if ((fabs(x1.Norm()) < MYEPSILON) || (fabs(x2.Norm()) < MYEPSILON) || (fabs(x1.Angle(&x2)) < MYEPSILON)) { 508 cout << Verbose(4) << "Given vectors are linear dependent." << endl; 509 return false; 510 } 511 // cout << Verbose(4) << "relative, first plane coordinates:"; 512 // x1.Output((ofstream *)&cout); 513 // cout << endl; 514 // cout << Verbose(4) << "second plane coordinates:"; 515 // x2.Output((ofstream *)&cout); 516 // cout << endl; 517 518 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]); 519 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]); 520 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]); 521 Normalize(); 522 523 return true; 642 524 }; 643 525 … … 653 535 bool Vector::MakeNormalVector(const Vector *y1, const Vector *y2) 654 536 { 655 656 657 658 659 660 661 662 663 // 664 // 665 // 666 // 667 // 668 // 669 670 671 672 673 674 675 537 Vector x1,x2; 538 x1.CopyVector(y1); 539 x2.CopyVector(y2); 540 Zero(); 541 if ((fabs(x1.Norm()) < MYEPSILON) || (fabs(x2.Norm()) < MYEPSILON) || (fabs(x1.Angle(&x2)) < MYEPSILON)) { 542 cout << Verbose(4) << "Given vectors are linear dependent." << endl; 543 return false; 544 } 545 // cout << Verbose(4) << "relative, first plane coordinates:"; 546 // x1.Output((ofstream *)&cout); 547 // cout << endl; 548 // cout << Verbose(4) << "second plane coordinates:"; 549 // x2.Output((ofstream *)&cout); 550 // cout << endl; 551 552 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]); 553 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]); 554 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]); 555 Normalize(); 556 557 return true; 676 558 }; 677 559 … … 683 565 bool Vector::MakeNormalVector(const Vector *y1) 684 566 { 685 686 687 688 689 690 691 692 693 567 bool result = false; 568 Vector x1; 569 x1.CopyVector(y1); 570 x1.Scale(x1.Projection(this)); 571 SubtractVector(&x1); 572 for (int i=NDIM;i--;) 573 result = result || (fabs(x[i]) > MYEPSILON); 574 575 return result; 694 576 }; 695 577 … … 702 584 bool Vector::GetOneNormalVector(const Vector *GivenVector) 703 585 { 704 705 int Last = 0;// count the number of non-zero entries in vector706 int j;// loop variables707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 case 3:// threecomponent system722 case 2:// two component system723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 586 int Components[NDIM]; // contains indices of non-zero components 587 int Last = 0; // count the number of non-zero entries in vector 588 int j; // loop variables 589 double norm; 590 591 cout << Verbose(4); 592 GivenVector->Output((ofstream *)&cout); 593 cout << endl; 594 for (j=NDIM;j--;) 595 Components[j] = -1; 596 // find two components != 0 597 for (j=0;j<NDIM;j++) 598 if (fabs(GivenVector->x[j]) > MYEPSILON) 599 Components[Last++] = j; 600 cout << Verbose(4) << Last << " Components != 0: (" << Components[0] << "," << Components[1] << "," << Components[2] << ")" << endl; 601 602 switch(Last) { 603 case 3: // threecomponent system 604 case 2: // two component system 605 norm = sqrt(1./(GivenVector->x[Components[1]]*GivenVector->x[Components[1]]) + 1./(GivenVector->x[Components[0]]*GivenVector->x[Components[0]])); 606 x[Components[2]] = 0.; 607 // in skp both remaining parts shall become zero but with opposite sign and third is zero 608 x[Components[1]] = -1./GivenVector->x[Components[1]] / norm; 609 x[Components[0]] = 1./GivenVector->x[Components[0]] / norm; 610 return true; 611 break; 612 case 1: // one component system 613 // set sole non-zero component to 0, and one of the other zero component pendants to 1 614 x[(Components[0]+2)%NDIM] = 0.; 615 x[(Components[0]+1)%NDIM] = 1.; 616 x[Components[0]] = 0.; 617 return true; 618 break; 619 default: 620 return false; 621 } 740 622 }; 741 623 … … 748 630 double Vector::CutsPlaneAt(Vector *A, Vector *B, Vector *C) 749 631 { 750 // 751 // 752 // 753 // 754 // 755 632 // cout << Verbose(3) << "For comparison: "; 633 // cout << "A " << A->Projection(this) << "\t"; 634 // cout << "B " << B->Projection(this) << "\t"; 635 // cout << "C " << C->Projection(this) << "\t"; 636 // cout << endl; 637 return A->Projection(this); 756 638 }; 757 639 … … 763 645 bool Vector::LSQdistance(Vector **vectors, int num) 764 646 { 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 647 int j; 648 649 for (j=0;j<num;j++) { 650 cout << Verbose(1) << j << "th atom's vector: "; 651 (vectors[j])->Output((ofstream *)&cout); 652 cout << endl; 653 } 654 655 int np = 3; 656 struct LSQ_params par; 657 658 const gsl_multimin_fminimizer_type *T = 659 gsl_multimin_fminimizer_nmsimplex; 660 gsl_multimin_fminimizer *s = NULL; 661 gsl_vector *ss, *y; 662 gsl_multimin_function minex_func; 663 664 size_t iter = 0, i; 665 int status; 666 double size; 667 668 /* Initial vertex size vector */ 669 ss = gsl_vector_alloc (np); 670 y = gsl_vector_alloc (np); 671 672 /* Set all step sizes to 1 */ 673 gsl_vector_set_all (ss, 1.0); 674 675 /* Starting point */ 676 par.vectors = vectors; 677 par.num = num; 678 679 for (i=NDIM;i--;) 680 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.); 681 682 /* Initialize method and iterate */ 683 minex_func.f = &LSQ; 684 minex_func.n = np; 685 minex_func.params = (void *)∥ 686 687 s = gsl_multimin_fminimizer_alloc (T, np); 688 gsl_multimin_fminimizer_set (s, &minex_func, y, ss); 689 690 do 691 { 692 iter++; 693 status = gsl_multimin_fminimizer_iterate(s); 694 695 if (status) 696 break; 697 698 size = gsl_multimin_fminimizer_size (s); 699 status = gsl_multimin_test_size (size, 1e-2); 700 701 if (status == GSL_SUCCESS) 702 { 703 printf ("converged to minimum at\n"); 704 } 705 706 printf ("%5d ", (int)iter); 707 for (i = 0; i < (size_t)np; i++) 708 { 709 printf ("%10.3e ", gsl_vector_get (s->x, i)); 710 } 711 printf ("f() = %7.3f size = %.3f\n", s->fval, size); 712 } 713 while (status == GSL_CONTINUE && iter < 100); 714 715 for (i=(size_t)np;i--;) 716 this->x[i] = gsl_vector_get(s->x, i); 717 gsl_vector_free(y); 718 gsl_vector_free(ss); 719 gsl_multimin_fminimizer_free (s); 720 721 return true; 840 722 }; 841 723 … … 845 727 void Vector::AddVector(const Vector *y) 846 728 { 847 848 729 for (int i=NDIM;i--;) 730 this->x[i] += y->x[i]; 849 731 } 850 732 … … 854 736 void Vector::SubtractVector(const Vector *y) 855 737 { 856 857 738 for (int i=NDIM;i--;) 739 this->x[i] -= y->x[i]; 858 740 } 859 741 … … 863 745 void Vector::CopyVector(const Vector *y) 864 746 { 865 866 747 for (int i=NDIM;i--;) 748 this->x[i] = y->x[i]; 867 749 } 868 750 … … 874 756 void Vector::AskPosition(double *cell_size, bool check) 875 757 { 876 877 878 879 880 881 882 883 884 758 char coords[3] = {'x','y','z'}; 759 int j = -1; 760 for (int i=0;i<3;i++) { 761 j += i+1; 762 do { 763 cout << Verbose(0) << coords[i] << "[0.." << cell_size[j] << "]: "; 764 cin >> x[i]; 765 } while (((x[i] < 0) || (x[i] >= cell_size[j])) && (check)); 766 } 885 767 }; 886 768 … … 902 784 bool Vector::SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c) 903 785 { 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 x[0] =A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 }; 786 double D1,D2,D3,E1,E2,F1,F2,F3,p,q=0., A, B1, B2, C; 787 double ang; // angle on testing 788 double sign[3]; 789 int i,j,k; 790 A = cos(alpha) * x1->Norm() * c; 791 B1 = cos(beta + M_PI/2.) * y->Norm() * c; 792 B2 = cos(beta) * x2->Norm() * c; 793 C = c * c; 794 cout << Verbose(2) << "A " << A << "\tB " << B1 << "\tC " << C << endl; 795 int flag = 0; 796 if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping 797 if (fabs(x1->x[1]) > MYEPSILON) { 798 flag = 1; 799 } else if (fabs(x1->x[2]) > MYEPSILON) { 800 flag = 2; 801 } else { 802 return false; 803 } 804 } 805 switch (flag) { 806 default: 807 case 0: 808 break; 809 case 2: 810 flip(&x1->x[0],&x1->x[1]); 811 flip(&x2->x[0],&x2->x[1]); 812 flip(&y->x[0],&y->x[1]); 813 //flip(&x[0],&x[1]); 814 flip(&x1->x[1],&x1->x[2]); 815 flip(&x2->x[1],&x2->x[2]); 816 flip(&y->x[1],&y->x[2]); 817 //flip(&x[1],&x[2]); 818 case 1: 819 flip(&x1->x[0],&x1->x[1]); 820 flip(&x2->x[0],&x2->x[1]); 821 flip(&y->x[0],&y->x[1]); 822 //flip(&x[0],&x[1]); 823 flip(&x1->x[1],&x1->x[2]); 824 flip(&x2->x[1],&x2->x[2]); 825 flip(&y->x[1],&y->x[2]); 826 //flip(&x[1],&x[2]); 827 break; 828 } 829 // now comes the case system 830 D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1]; 831 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2]; 832 D3 = y->x[0]/x1->x[0]*A-B1; 833 cout << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n"; 834 if (fabs(D1) < MYEPSILON) { 835 cout << Verbose(2) << "D1 == 0!\n"; 836 if (fabs(D2) > MYEPSILON) { 837 cout << Verbose(3) << "D2 != 0!\n"; 838 x[2] = -D3/D2; 839 E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2; 840 E2 = -x1->x[1]/x1->x[0]; 841 cout << Verbose(3) << "E1 " << E1 << "\tE2 " << E2 << "\n"; 842 F1 = E1*E1 + 1.; 843 F2 = -E1*E2; 844 F3 = E1*E1 + D3*D3/(D2*D2) - C; 845 cout << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 846 if (fabs(F1) < MYEPSILON) { 847 cout << Verbose(4) << "F1 == 0!\n"; 848 cout << Verbose(4) << "Gleichungssystem linear\n"; 849 x[1] = F3/(2.*F2); 850 } else { 851 p = F2/F1; 852 q = p*p - F3/F1; 853 cout << Verbose(4) << "p " << p << "\tq " << q << endl; 854 if (q < 0) { 855 cout << Verbose(4) << "q < 0" << endl; 856 return false; 857 } 858 x[1] = p + sqrt(q); 859 } 860 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2]; 861 } else { 862 cout << Verbose(2) << "Gleichungssystem unterbestimmt\n"; 863 return false; 864 } 865 } else { 866 E1 = A/x1->x[0]+x1->x[1]/x1->x[0]*D3/D1; 867 E2 = x1->x[1]/x1->x[0]*D2/D1 - x1->x[2]; 868 cout << Verbose(2) << "E1 " << E1 << "\tE2 " << E2 << "\n"; 869 F1 = E2*E2 + D2*D2/(D1*D1) + 1.; 870 F2 = -(E1*E2 + D2*D3/(D1*D1)); 871 F3 = E1*E1 + D3*D3/(D1*D1) - C; 872 cout << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 873 if (fabs(F1) < MYEPSILON) { 874 cout << Verbose(3) << "F1 == 0!\n"; 875 cout << Verbose(3) << "Gleichungssystem linear\n"; 876 x[2] = F3/(2.*F2); 877 } else { 878 p = F2/F1; 879 q = p*p - F3/F1; 880 cout << Verbose(3) << "p " << p << "\tq " << q << endl; 881 if (q < 0) { 882 cout << Verbose(3) << "q < 0" << endl; 883 return false; 884 } 885 x[2] = p + sqrt(q); 886 } 887 x[1] = (-D2 * x[2] - D3)/D1; 888 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2]; 889 } 890 switch (flag) { // back-flipping 891 default: 892 case 0: 893 break; 894 case 2: 895 flip(&x1->x[0],&x1->x[1]); 896 flip(&x2->x[0],&x2->x[1]); 897 flip(&y->x[0],&y->x[1]); 898 flip(&x[0],&x[1]); 899 flip(&x1->x[1],&x1->x[2]); 900 flip(&x2->x[1],&x2->x[2]); 901 flip(&y->x[1],&y->x[2]); 902 flip(&x[1],&x[2]); 903 case 1: 904 flip(&x1->x[0],&x1->x[1]); 905 flip(&x2->x[0],&x2->x[1]); 906 flip(&y->x[0],&y->x[1]); 907 //flip(&x[0],&x[1]); 908 flip(&x1->x[1],&x1->x[2]); 909 flip(&x2->x[1],&x2->x[2]); 910 flip(&y->x[1],&y->x[2]); 911 flip(&x[1],&x[2]); 912 break; 913 } 914 // one z component is only determined by its radius (without sign) 915 // thus check eight possible sign flips and determine by checking angle with second vector 916 for (i=0;i<8;i++) { 917 // set sign vector accordingly 918 for (j=2;j>=0;j--) { 919 k = (i & pot(2,j)) << j; 920 cout << Verbose(2) << "k " << k << "\tpot(2,j) " << pot(2,j) << endl; 921 sign[j] = (k == 0) ? 1. : -1.; 922 } 923 cout << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n"; 924 // apply sign matrix 925 for (j=NDIM;j--;) 926 x[j] *= sign[j]; 927 // calculate angle and check 928 ang = x2->Angle (this); 929 cout << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t"; 930 if (fabs(ang - cos(beta)) < MYEPSILON) { 931 break; 932 } 933 // unapply sign matrix (is its own inverse) 934 for (j=NDIM;j--;) 935 x[j] *= sign[j]; 936 } 937 return true; 938 };
Note:
See TracChangeset
for help on using the changeset viewer.