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