source: src/vector.cpp@ 273382

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 Candidate_v1.7.0 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 273382 was 273382, checked in by Tillmann Crueger <crueger@…>, 16 years ago

Prepared interface of Vector Class for transition to VectorComposites

  • Property mode set to 100644
File size: 24.9 KB
RevLine 
[6ac7ee]1/** \file vector.cpp
2 *
3 * Function implementations for the class vector.
4 *
5 */
6
[edb93c]7
[54a746]8#include "defs.hpp"
[9d6308]9#include "gslmatrix.hpp"
[54a746]10#include "leastsquaremin.hpp"
[97498a]11#include "memoryallocator.hpp"
[54a746]12#include "vector.hpp"
[0a4f7f]13#include "Helpers/fast_functions.hpp"
14#include "Helpers/Assert.hpp"
15#include "Plane.hpp"
16#include "Exceptions/LinearDependenceException.hpp"
[6ac7ee]17
[97498a]18#include <gsl/gsl_linalg.h>
19#include <gsl/gsl_matrix.h>
20#include <gsl/gsl_permutation.h>
21#include <gsl/gsl_vector.h>
22
[6ac7ee]23/************************************ Functions for class vector ************************************/
24
25/** Constructor of class vector.
26 */
[0a4f7f]27Vector::Vector()
28{
29 x[0] = x[1] = x[2] = 0.;
30};
[6ac7ee]31
32/** Constructor of class vector.
33 */
[0a4f7f]34Vector::Vector(const double x1, const double x2, const double x3)
35{
36 x[0] = x1;
37 x[1] = x2;
38 x[2] = x3;
39};
40
41/**
42 * Copy constructor
43 */
44Vector::Vector(const Vector& src)
45{
46 x[0] = src[0];
47 x[1] = src[1];
48 x[2] = src[2];
49}
50
51/**
52 * Assignment operator
53 */
54Vector& Vector::operator=(const Vector& src){
55 // check for self assignment
56 if(&src!=this){
57 x[0] = src[0];
58 x[1] = src[1];
59 x[2] = src[2];
60 }
61 return *this;
62}
[6ac7ee]63
64/** Desctructor of class vector.
65 */
66Vector::~Vector() {};
67
68/** Calculates square of distance between this and another vector.
69 * \param *y array to second vector
70 * \return \f$| x - y |^2\f$
71 */
[273382]72double Vector::DistanceSquared(const Vector &y) const
[6ac7ee]73{
[042f82]74 double res = 0.;
75 for (int i=NDIM;i--;)
[273382]76 res += (x[i]-y[i])*(x[i]-y[i]);
[042f82]77 return (res);
[6ac7ee]78};
79
80/** Calculates distance between this and another vector.
81 * \param *y array to second vector
82 * \return \f$| x - y |\f$
83 */
[273382]84double Vector::Distance(const Vector &y) const
[6ac7ee]85{
[273382]86 return (sqrt(DistanceSquared(y)));
[6ac7ee]87};
88
89/** Calculates distance between this and another vector in a periodic cell.
90 * \param *y array to second vector
91 * \param *cell_size 6-dimensional array with (xx, xy, yy, xz, yz, zz) entries specifying the periodic cell
92 * \return \f$| x - y |\f$
93 */
[273382]94double Vector::PeriodicDistance(const Vector &y, const double * const cell_size) const
[6ac7ee]95{
[042f82]96 double res = Distance(y), tmp, matrix[NDIM*NDIM];
97 Vector Shiftedy, TranslationVector;
98 int N[NDIM];
99 matrix[0] = cell_size[0];
100 matrix[1] = cell_size[1];
101 matrix[2] = cell_size[3];
102 matrix[3] = cell_size[1];
103 matrix[4] = cell_size[2];
104 matrix[5] = cell_size[4];
105 matrix[6] = cell_size[3];
106 matrix[7] = cell_size[4];
107 matrix[8] = cell_size[5];
108 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells
109 for (N[0]=-1;N[0]<=1;N[0]++)
110 for (N[1]=-1;N[1]<=1;N[1]++)
111 for (N[2]=-1;N[2]<=1;N[2]++) {
112 // create the translation vector
113 TranslationVector.Zero();
114 for (int i=NDIM;i--;)
115 TranslationVector.x[i] = (double)N[i];
116 TranslationVector.MatrixMultiplication(matrix);
117 // add onto the original vector to compare with
[273382]118 Shiftedy = y + TranslationVector;
[042f82]119 // get distance and compare with minimum so far
[273382]120 tmp = Distance(Shiftedy);
[042f82]121 if (tmp < res) res = tmp;
122 }
123 return (res);
[6ac7ee]124};
125
126/** Calculates distance between this and another vector in a periodic cell.
127 * \param *y array to second vector
128 * \param *cell_size 6-dimensional array with (xx, xy, yy, xz, yz, zz) entries specifying the periodic cell
129 * \return \f$| x - y |^2\f$
130 */
[273382]131double Vector::PeriodicDistanceSquared(const Vector &y, const double * const cell_size) const
[6ac7ee]132{
[042f82]133 double res = DistanceSquared(y), tmp, matrix[NDIM*NDIM];
134 Vector Shiftedy, TranslationVector;
135 int N[NDIM];
136 matrix[0] = cell_size[0];
137 matrix[1] = cell_size[1];
138 matrix[2] = cell_size[3];
139 matrix[3] = cell_size[1];
140 matrix[4] = cell_size[2];
141 matrix[5] = cell_size[4];
142 matrix[6] = cell_size[3];
143 matrix[7] = cell_size[4];
144 matrix[8] = cell_size[5];
145 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells
146 for (N[0]=-1;N[0]<=1;N[0]++)
147 for (N[1]=-1;N[1]<=1;N[1]++)
148 for (N[2]=-1;N[2]<=1;N[2]++) {
149 // create the translation vector
150 TranslationVector.Zero();
151 for (int i=NDIM;i--;)
152 TranslationVector.x[i] = (double)N[i];
153 TranslationVector.MatrixMultiplication(matrix);
154 // add onto the original vector to compare with
[273382]155 Shiftedy = y + TranslationVector;
[042f82]156 // get distance and compare with minimum so far
[273382]157 tmp = DistanceSquared(Shiftedy);
[042f82]158 if (tmp < res) res = tmp;
159 }
160 return (res);
[6ac7ee]161};
162
163/** Keeps the vector in a periodic cell, defined by the symmetric \a *matrix.
164 * \param *out ofstream for debugging messages
165 * Tries to translate a vector into each adjacent neighbouring cell.
166 */
[e138de]167void Vector::KeepPeriodic(const double * const matrix)
[6ac7ee]168{
[042f82]169// int N[NDIM];
170// bool flag = false;
171 //vector Shifted, TranslationVector;
172 Vector TestVector;
[e138de]173// Log() << Verbose(1) << "Begin of KeepPeriodic." << endl;
174// Log() << Verbose(2) << "Vector is: ";
[042f82]175// Output(out);
[e138de]176// Log() << Verbose(0) << endl;
[273382]177 TestVector = (*this);
[042f82]178 TestVector.InverseMatrixMultiplication(matrix);
179 for(int i=NDIM;i--;) { // correct periodically
180 if (TestVector.x[i] < 0) { // get every coefficient into the interval [0,1)
181 TestVector.x[i] += ceil(TestVector.x[i]);
182 } else {
183 TestVector.x[i] -= floor(TestVector.x[i]);
184 }
185 }
186 TestVector.MatrixMultiplication(matrix);
[273382]187 (*this) = TestVector;
[e138de]188// Log() << Verbose(2) << "New corrected vector is: ";
[042f82]189// Output(out);
[e138de]190// Log() << Verbose(0) << endl;
191// Log() << Verbose(1) << "End of KeepPeriodic." << endl;
[6ac7ee]192};
193
194/** Calculates scalar product between this and another vector.
195 * \param *y array to second vector
196 * \return \f$\langle x, y \rangle\f$
197 */
[273382]198double Vector::ScalarProduct(const Vector &y) const
[6ac7ee]199{
[042f82]200 double res = 0.;
201 for (int i=NDIM;i--;)
[273382]202 res += x[i]*y[i];
[042f82]203 return (res);
[6ac7ee]204};
205
206
207/** Calculates VectorProduct between this and another vector.
[042f82]208 * -# returns the Product in place of vector from which it was initiated
209 * -# ATTENTION: Only three dim.
210 * \param *y array to vector with which to calculate crossproduct
211 * \return \f$ x \times y \f&
[6ac7ee]212 */
[273382]213void Vector::VectorProduct(const Vector &y)
[6ac7ee]214{
[042f82]215 Vector tmp;
[273382]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]);
219 (*this) = tmp;
[6ac7ee]220};
221
222
223/** projects this vector onto plane defined by \a *y.
224 * \param *y normal vector of plane
225 * \return \f$\langle x, y \rangle\f$
226 */
[273382]227void Vector::ProjectOntoPlane(const Vector &y)
[6ac7ee]228{
[273382]229 Vector tmp = y;
[042f82]230 tmp.Normalize();
[273382]231 tmp *= ScalarProduct(tmp);
232 (*this) -= tmp;
[6ac7ee]233};
234
[c4d4df]235/** Calculates the minimum distance of this vector to the plane.
236 * \param *out output stream for debugging
237 * \param *PlaneNormal normal of plane
238 * \param *PlaneOffset offset of plane
239 * \return distance to plane
240 */
[273382]241double Vector::DistanceToPlane(const Vector &PlaneNormal, const Vector &PlaneOffset) const
[c4d4df]242{
243 // first create part that is orthonormal to PlaneNormal with withdraw
[273382]244 Vector temp = (*this) - PlaneOffset;
245 temp.MakeNormalTo(PlaneNormal);
246 temp *= -1.;
[c4d4df]247 // then add connecting vector from plane to point
[273382]248 temp += (*this);
249 temp -= PlaneOffset;
[99593f]250 double sign = temp.ScalarProduct(PlaneNormal);
[7ea9e6]251 if (fabs(sign) > MYEPSILON)
252 sign /= fabs(sign);
253 else
254 sign = 0.;
[c4d4df]255
[99593f]256 return (temp.Norm()*sign);
[c4d4df]257};
258
[6ac7ee]259/** Calculates the projection of a vector onto another \a *y.
260 * \param *y array to second vector
261 */
[273382]262void Vector::ProjectIt(const Vector &y)
[6ac7ee]263{
[273382]264 Vector helper = y;
[ef9df36]265 helper.Scale(-(ScalarProduct(y)));
[273382]266 AddVector(helper);
[ef9df36]267};
268
269/** Calculates the projection of a vector onto another \a *y.
270 * \param *y array to second vector
271 * \return Vector
272 */
[273382]273Vector Vector::Projection(const Vector &y) const
[ef9df36]274{
[273382]275 Vector helper = y;
276 helper.Scale((ScalarProduct(y)/y.NormSquared()));
[ef9df36]277
278 return helper;
[6ac7ee]279};
280
281/** Calculates norm of this vector.
282 * \return \f$|x|\f$
283 */
284double Vector::Norm() const
285{
[273382]286 return (sqrt(NormSquared()));
[6ac7ee]287};
288
[d4d0dd]289/** Calculates squared norm of this vector.
290 * \return \f$|x|^2\f$
291 */
292double Vector::NormSquared() const
293{
[273382]294 return (ScalarProduct(*this));
[d4d0dd]295};
296
[6ac7ee]297/** Normalizes this vector.
298 */
299void Vector::Normalize()
300{
[042f82]301 double res = 0.;
302 for (int i=NDIM;i--;)
303 res += this->x[i]*this->x[i];
304 if (fabs(res) > MYEPSILON)
305 res = 1./sqrt(res);
306 Scale(&res);
[6ac7ee]307};
308
309/** Zeros all components of this vector.
310 */
311void Vector::Zero()
312{
[042f82]313 for (int i=NDIM;i--;)
314 this->x[i] = 0.;
[6ac7ee]315};
316
317/** Zeros all components of this vector.
318 */
[776b64]319void Vector::One(const double one)
[6ac7ee]320{
[042f82]321 for (int i=NDIM;i--;)
322 this->x[i] = one;
[6ac7ee]323};
324
325/** Initialises all components of this vector.
326 */
[776b64]327void Vector::Init(const double x1, const double x2, const double x3)
[6ac7ee]328{
[042f82]329 x[0] = x1;
330 x[1] = x2;
331 x[2] = x3;
[6ac7ee]332};
333
[9c20aa]334/** Checks whether vector has all components zero.
335 * @return true - vector is zero, false - vector is not
336 */
[54a746]337bool Vector::IsZero() const
[9c20aa]338{
[54a746]339 return (fabs(x[0])+fabs(x[1])+fabs(x[2]) < MYEPSILON);
340};
341
342/** Checks whether vector has length of 1.
343 * @return true - vector is normalized, false - vector is not
344 */
345bool Vector::IsOne() const
346{
347 return (fabs(Norm() - 1.) < MYEPSILON);
[9c20aa]348};
349
[ef9df36]350/** Checks whether vector is normal to \a *normal.
351 * @return true - vector is normalized, false - vector is not
352 */
[273382]353bool Vector::IsNormalTo(const Vector &normal) const
[ef9df36]354{
355 if (ScalarProduct(normal) < MYEPSILON)
356 return true;
357 else
358 return false;
359};
360
[b998c3]361/** Checks whether vector is normal to \a *normal.
362 * @return true - vector is normalized, false - vector is not
363 */
[273382]364bool Vector::IsEqualTo(const Vector &a) const
[b998c3]365{
366 bool status = true;
367 for (int i=0;i<NDIM;i++) {
[273382]368 if (fabs(x[i] - a[i]) > MYEPSILON)
[b998c3]369 status = false;
370 }
371 return status;
372};
373
[6ac7ee]374/** Calculates the angle between this and another vector.
375 * \param *y array to second vector
376 * \return \f$\acos\bigl(frac{\langle x, y \rangle}{|x||y|}\bigr)\f$
377 */
[273382]378double Vector::Angle(const Vector &y) const
[6ac7ee]379{
[273382]380 double norm1 = Norm(), norm2 = y.Norm();
[ef9df36]381 double angle = -1;
[d4d0dd]382 if ((fabs(norm1) > MYEPSILON) && (fabs(norm2) > MYEPSILON))
383 angle = this->ScalarProduct(y)/norm1/norm2;
[02da9e]384 // -1-MYEPSILON occured due to numerical imprecision, catch ...
[e138de]385 //Log() << Verbose(2) << "INFO: acos(-1) = " << acos(-1) << ", acos(-1+MYEPSILON) = " << acos(-1+MYEPSILON) << ", acos(-1-MYEPSILON) = " << acos(-1-MYEPSILON) << "." << endl;
[02da9e]386 if (angle < -1)
387 angle = -1;
388 if (angle > 1)
389 angle = 1;
[042f82]390 return acos(angle);
[6ac7ee]391};
392
[0a4f7f]393
394double& Vector::operator[](size_t i){
395 ASSERT(i<=NDIM && i>=0,"Vector Index out of Range");
396 return x[i];
397}
398
399const double& Vector::operator[](size_t i) const{
400 ASSERT(i<=NDIM && i>=0,"Vector Index out of Range");
401 return x[i];
402}
403
404double& Vector::at(size_t i){
405 return (*this)[i];
406}
407
408const double& Vector::at(size_t i) const{
409 return (*this)[i];
410}
411
412double* Vector::get(){
413 return x;
414}
[6ac7ee]415
[ef9df36]416/** Compares vector \a to vector \a b component-wise.
417 * \param a base vector
418 * \param b vector components to add
419 * \return a == b
420 */
[72e7fa]421bool Vector::operator==(const Vector& b) const
[ef9df36]422{
423 bool status = true;
424 for (int i=0;i<NDIM;i++)
[72e7fa]425 status = status && (fabs((*this)[i] - b[i]) < MYEPSILON);
[ef9df36]426 return status;
427};
428
[6ac7ee]429/** Sums vector \a to this lhs component-wise.
430 * \param a base vector
431 * \param b vector components to add
432 * \return lhs + a
433 */
[72e7fa]434const Vector& Vector::operator+=(const Vector& b)
[6ac7ee]435{
[273382]436 this->AddVector(b);
[72e7fa]437 return *this;
[6ac7ee]438};
[54a746]439
440/** Subtracts vector \a from this lhs component-wise.
441 * \param a base vector
442 * \param b vector components to add
443 * \return lhs - a
444 */
[72e7fa]445const Vector& Vector::operator-=(const Vector& b)
[54a746]446{
[273382]447 this->SubtractVector(b);
[72e7fa]448 return *this;
[54a746]449};
450
[6ac7ee]451/** factor each component of \a a times a double \a m.
452 * \param a base vector
453 * \param m factor
454 * \return lhs.x[i] * m
455 */
[b84d5d]456const Vector& operator*=(Vector& a, const double m)
[6ac7ee]457{
[042f82]458 a.Scale(m);
459 return a;
[6ac7ee]460};
461
[042f82]462/** Sums two vectors \a and \b component-wise.
[6ac7ee]463 * \param a first vector
464 * \param b second vector
465 * \return a + b
466 */
[72e7fa]467Vector const Vector::operator+(const Vector& b) const
[6ac7ee]468{
[72e7fa]469 Vector x = *this;
[273382]470 x.AddVector(b);
[b84d5d]471 return x;
[6ac7ee]472};
473
[54a746]474/** Subtracts vector \a from \b component-wise.
475 * \param a first vector
476 * \param b second vector
477 * \return a - b
478 */
[72e7fa]479Vector const Vector::operator-(const Vector& b) const
[54a746]480{
[72e7fa]481 Vector x = *this;
[273382]482 x.SubtractVector(b);
[b84d5d]483 return x;
[54a746]484};
485
[6ac7ee]486/** Factors given vector \a a times \a m.
487 * \param a vector
488 * \param m factor
[54a746]489 * \return m * a
[6ac7ee]490 */
[b84d5d]491Vector const operator*(const Vector& a, const double m)
[6ac7ee]492{
[b84d5d]493 Vector x(a);
494 x.Scale(m);
495 return x;
[6ac7ee]496};
497
[54a746]498/** Factors given vector \a a times \a m.
499 * \param m factor
500 * \param a vector
501 * \return m * a
502 */
[b84d5d]503Vector const operator*(const double m, const Vector& a )
[54a746]504{
[b84d5d]505 Vector x(a);
506 x.Scale(m);
507 return x;
[54a746]508};
509
[9c20aa]510ostream& operator<<(ostream& ost, const Vector& m)
[6ac7ee]511{
[042f82]512 ost << "(";
513 for (int i=0;i<NDIM;i++) {
[0a4f7f]514 ost << m[i];
[042f82]515 if (i != 2)
516 ost << ",";
517 }
518 ost << ")";
519 return ost;
[6ac7ee]520};
521
522/** Scales each atom coordinate by an individual \a factor.
523 * \param *factor pointer to scaling factor
524 */
[776b64]525void Vector::Scale(const double ** const factor)
[6ac7ee]526{
[042f82]527 for (int i=NDIM;i--;)
528 x[i] *= (*factor)[i];
[6ac7ee]529};
530
[776b64]531void Vector::Scale(const double * const factor)
[6ac7ee]532{
[042f82]533 for (int i=NDIM;i--;)
534 x[i] *= *factor;
[6ac7ee]535};
536
[776b64]537void Vector::Scale(const double factor)
[6ac7ee]538{
[042f82]539 for (int i=NDIM;i--;)
540 x[i] *= factor;
[6ac7ee]541};
542
543/** Translate atom by given vector.
544 * \param trans[] translation vector.
545 */
[273382]546void Vector::Translate(const Vector &trans)
[6ac7ee]547{
[042f82]548 for (int i=NDIM;i--;)
[273382]549 x[i] += trans[i];
[6ac7ee]550};
551
[d09ff7]552/** Given a box by its matrix \a *M and its inverse *Minv the vector is made to point within that box.
553 * \param *M matrix of box
554 * \param *Minv inverse matrix
555 */
[776b64]556void Vector::WrapPeriodically(const double * const M, const double * const Minv)
[d09ff7]557{
558 MatrixMultiplication(Minv);
559 // truncate to [0,1] for each axis
560 for (int i=0;i<NDIM;i++) {
561 x[i] += 0.5; // set to center of box
562 while (x[i] >= 1.)
563 x[i] -= 1.;
564 while (x[i] < 0.)
565 x[i] += 1.;
566 }
567 MatrixMultiplication(M);
568};
569
[6ac7ee]570/** Do a matrix multiplication.
571 * \param *matrix NDIM_NDIM array
572 */
[776b64]573void Vector::MatrixMultiplication(const double * const M)
[6ac7ee]574{
[042f82]575 Vector C;
576 // do the matrix multiplication
577 C.x[0] = M[0]*x[0]+M[3]*x[1]+M[6]*x[2];
578 C.x[1] = M[1]*x[0]+M[4]*x[1]+M[7]*x[2];
579 C.x[2] = M[2]*x[0]+M[5]*x[1]+M[8]*x[2];
580 // transfer the result into this
581 for (int i=NDIM;i--;)
582 x[i] = C.x[i];
[6ac7ee]583};
584
[2319ed]585/** Do a matrix multiplication with the \a *A' inverse.
[6ac7ee]586 * \param *matrix NDIM_NDIM array
587 */
[0a4f7f]588bool Vector::InverseMatrixMultiplication(const double * const A)
[6ac7ee]589{
[042f82]590 Vector C;
591 double B[NDIM*NDIM];
592 double detA = RDET3(A);
593 double detAReci;
594
595 // calculate the inverse B
596 if (fabs(detA) > MYEPSILON) {; // RDET3(A) yields precisely zero if A irregular
597 detAReci = 1./detA;
598 B[0] = detAReci*RDET2(A[4],A[5],A[7],A[8]); // A_11
599 B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]); // A_12
600 B[2] = detAReci*RDET2(A[1],A[2],A[4],A[5]); // A_13
601 B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]); // A_21
602 B[4] = detAReci*RDET2(A[0],A[2],A[6],A[8]); // A_22
603 B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]); // A_23
604 B[6] = detAReci*RDET2(A[3],A[4],A[6],A[7]); // A_31
605 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]); // A_32
606 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]); // A_33
607
608 // do the matrix multiplication
609 C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2];
610 C.x[1] = B[1]*x[0]+B[4]*x[1]+B[7]*x[2];
611 C.x[2] = B[2]*x[0]+B[5]*x[1]+B[8]*x[2];
612 // transfer the result into this
613 for (int i=NDIM;i--;)
614 x[i] = C.x[i];
[0a4f7f]615 return true;
[042f82]616 } else {
[0a4f7f]617 return false;
[042f82]618 }
[6ac7ee]619};
620
621
622/** Creates this vector as the b y *factors' components scaled linear combination of the given three.
623 * this vector = x1*factors[0] + x2* factors[1] + x3*factors[2]
624 * \param *x1 first vector
625 * \param *x2 second vector
626 * \param *x3 third vector
627 * \param *factors three-component vector with the factor for each given vector
628 */
[273382]629void Vector::LinearCombinationOfVectors(const Vector &x1, const Vector &x2, const Vector &x3, const double * const factors)
[6ac7ee]630{
[273382]631 (*this) = (factors[0]*x1) +
632 (factors[1]*x2) +
633 (factors[2]*x3);
[6ac7ee]634};
635
636/** Mirrors atom against a given plane.
637 * \param n[] normal vector of mirror plane.
638 */
[273382]639void Vector::Mirror(const Vector &n)
[6ac7ee]640{
[042f82]641 double projection;
[273382]642 projection = ScalarProduct(n)/n.NormSquared(); // remove constancy from n (keep as logical one)
[042f82]643 // withdraw projected vector twice from original one
644 for (int i=NDIM;i--;)
[273382]645 x[i] -= 2.*projection*n[i];
[6ac7ee]646};
647
648
[0a4f7f]649/** Calculates orthonormal vector to one given vector.
[6ac7ee]650 * Just subtracts the projection onto the given vector from this vector.
[ef9df36]651 * The removed part of the vector is Vector::Projection()
[6ac7ee]652 * \param *x1 vector
653 * \return true - success, false - vector is zero
654 */
[0a4f7f]655bool Vector::MakeNormalTo(const Vector &y1)
[6ac7ee]656{
[042f82]657 bool result = false;
[273382]658 double factor = y1.ScalarProduct(*this)/y1.NormSquared();
659 Vector x1 = factor * y1 ;
660 SubtractVector(x1);
[042f82]661 for (int i=NDIM;i--;)
662 result = result || (fabs(x[i]) > MYEPSILON);
[6ac7ee]663
[042f82]664 return result;
[6ac7ee]665};
666
667/** Creates this vector as one of the possible orthonormal ones to the given one.
668 * Just scan how many components of given *vector are unequal to zero and
669 * try to get the skp of both to be zero accordingly.
670 * \param *vector given vector
671 * \return true - success, false - failure (null vector given)
672 */
[273382]673bool Vector::GetOneNormalVector(const Vector &GivenVector)
[6ac7ee]674{
[042f82]675 int Components[NDIM]; // contains indices of non-zero components
676 int Last = 0; // count the number of non-zero entries in vector
677 int j; // loop variables
678 double norm;
679
680 for (j=NDIM;j--;)
681 Components[j] = -1;
682 // find two components != 0
683 for (j=0;j<NDIM;j++)
[273382]684 if (fabs(GivenVector[j]) > MYEPSILON)
[042f82]685 Components[Last++] = j;
686
687 switch(Last) {
688 case 3: // threecomponent system
689 case 2: // two component system
[273382]690 norm = sqrt(1./(GivenVector[Components[1]]*GivenVector[Components[1]]) + 1./(GivenVector[Components[0]]*GivenVector[Components[0]]));
[042f82]691 x[Components[2]] = 0.;
692 // in skp both remaining parts shall become zero but with opposite sign and third is zero
[273382]693 x[Components[1]] = -1./GivenVector[Components[1]] / norm;
694 x[Components[0]] = 1./GivenVector[Components[0]] / norm;
[042f82]695 return true;
696 break;
697 case 1: // one component system
698 // set sole non-zero component to 0, and one of the other zero component pendants to 1
699 x[(Components[0]+2)%NDIM] = 0.;
700 x[(Components[0]+1)%NDIM] = 1.;
701 x[Components[0]] = 0.;
702 return true;
703 break;
704 default:
705 return false;
706 }
[6ac7ee]707};
708
709/** Adds vector \a *y componentwise.
710 * \param *y vector
711 */
[273382]712void Vector::AddVector(const Vector &y)
[6ac7ee]713{
[042f82]714 for (int i=NDIM;i--;)
[273382]715 this->x[i] += y[i];
[6ac7ee]716}
717
718/** Adds vector \a *y componentwise.
719 * \param *y vector
720 */
[273382]721void Vector::SubtractVector(const Vector &y)
[6ac7ee]722{
[042f82]723 for (int i=NDIM;i--;)
[273382]724 this->x[i] -= y[i];
[6ac7ee]725}
726
[ef9df36]727/** Copy vector \a y componentwise.
728 * \param y vector
729 */
[776b64]730void Vector::CopyVector(const Vector &y)
[ef9df36]731{
[2ededc2]732 // check for self assignment
733 if(&y!=this) {
734 for (int i=NDIM;i--;)
735 this->x[i] = y.x[i];
736 }
[ef9df36]737}
738
[0a4f7f]739// this function is completely unused so it is deactivated until new uses arrive and a new
740// place can be found
741#if 0
[6ac7ee]742/** Solves a vectorial system consisting of two orthogonal statements and a norm statement.
743 * This is linear system of equations to be solved, however of the three given (skp of this vector\
744 * with either of the three hast to be zero) only two are linear independent. The third equation
745 * is that the vector should be of magnitude 1 (orthonormal). This all leads to a case-based solution
746 * where very often it has to be checked whether a certain value is zero or not and thus forked into
747 * another case.
748 * \param *x1 first vector
749 * \param *x2 second vector
750 * \param *y third vector
751 * \param alpha first angle
752 * \param beta second angle
753 * \param c norm of final vector
754 * \return a vector with \f$\langle x1,x2 \rangle=A\f$, \f$\langle x1,y \rangle = B\f$ and with norm \a c.
755 * \bug this is not yet working properly
756 */
[776b64]757bool Vector::SolveSystem(Vector * x1, Vector * x2, Vector * y, const double alpha, const double beta, const double c)
[6ac7ee]758{
[042f82]759 double D1,D2,D3,E1,E2,F1,F2,F3,p,q=0., A, B1, B2, C;
760 double ang; // angle on testing
761 double sign[3];
762 int i,j,k;
763 A = cos(alpha) * x1->Norm() * c;
764 B1 = cos(beta + M_PI/2.) * y->Norm() * c;
765 B2 = cos(beta) * x2->Norm() * c;
766 C = c * c;
[e138de]767 Log() << Verbose(2) << "A " << A << "\tB " << B1 << "\tC " << C << endl;
[042f82]768 int flag = 0;
769 if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping
770 if (fabs(x1->x[1]) > MYEPSILON) {
771 flag = 1;
772 } else if (fabs(x1->x[2]) > MYEPSILON) {
773 flag = 2;
774 } else {
775 return false;
776 }
777 }
778 switch (flag) {
779 default:
780 case 0:
781 break;
782 case 2:
[ad8b0d]783 flip(x1->x[0],x1->x[1]);
784 flip(x2->x[0],x2->x[1]);
785 flip(y->x[0],y->x[1]);
786 //flip(x[0],x[1]);
787 flip(x1->x[1],x1->x[2]);
788 flip(x2->x[1],x2->x[2]);
789 flip(y->x[1],y->x[2]);
790 //flip(x[1],x[2]);
[042f82]791 case 1:
[ad8b0d]792 flip(x1->x[0],x1->x[1]);
793 flip(x2->x[0],x2->x[1]);
794 flip(y->x[0],y->x[1]);
795 //flip(x[0],x[1]);
796 flip(x1->x[1],x1->x[2]);
797 flip(x2->x[1],x2->x[2]);
798 flip(y->x[1],y->x[2]);
799 //flip(x[1],x[2]);
[042f82]800 break;
801 }
802 // now comes the case system
803 D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1];
804 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2];
805 D3 = y->x[0]/x1->x[0]*A-B1;
[e138de]806 Log() << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n";
[042f82]807 if (fabs(D1) < MYEPSILON) {
[e138de]808 Log() << Verbose(2) << "D1 == 0!\n";
[042f82]809 if (fabs(D2) > MYEPSILON) {
[e138de]810 Log() << Verbose(3) << "D2 != 0!\n";
[042f82]811 x[2] = -D3/D2;
812 E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2;
813 E2 = -x1->x[1]/x1->x[0];
[e138de]814 Log() << Verbose(3) << "E1 " << E1 << "\tE2 " << E2 << "\n";
[042f82]815 F1 = E1*E1 + 1.;
816 F2 = -E1*E2;
817 F3 = E1*E1 + D3*D3/(D2*D2) - C;
[e138de]818 Log() << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n";
[042f82]819 if (fabs(F1) < MYEPSILON) {
[e138de]820 Log() << Verbose(4) << "F1 == 0!\n";
821 Log() << Verbose(4) << "Gleichungssystem linear\n";
[042f82]822 x[1] = F3/(2.*F2);
823 } else {
824 p = F2/F1;
825 q = p*p - F3/F1;
[e138de]826 Log() << Verbose(4) << "p " << p << "\tq " << q << endl;
[042f82]827 if (q < 0) {
[e138de]828 Log() << Verbose(4) << "q < 0" << endl;
[042f82]829 return false;
830 }
831 x[1] = p + sqrt(q);
832 }
833 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];
834 } else {
[e138de]835 Log() << Verbose(2) << "Gleichungssystem unterbestimmt\n";
[042f82]836 return false;
837 }
838 } else {
839 E1 = A/x1->x[0]+x1->x[1]/x1->x[0]*D3/D1;
840 E2 = x1->x[1]/x1->x[0]*D2/D1 - x1->x[2];
[e138de]841 Log() << Verbose(2) << "E1 " << E1 << "\tE2 " << E2 << "\n";
[042f82]842 F1 = E2*E2 + D2*D2/(D1*D1) + 1.;
843 F2 = -(E1*E2 + D2*D3/(D1*D1));
844 F3 = E1*E1 + D3*D3/(D1*D1) - C;
[e138de]845 Log() << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n";
[042f82]846 if (fabs(F1) < MYEPSILON) {
[e138de]847 Log() << Verbose(3) << "F1 == 0!\n";
848 Log() << Verbose(3) << "Gleichungssystem linear\n";
[042f82]849 x[2] = F3/(2.*F2);
850 } else {
851 p = F2/F1;
852 q = p*p - F3/F1;
[e138de]853 Log() << Verbose(3) << "p " << p << "\tq " << q << endl;
[042f82]854 if (q < 0) {
[e138de]855 Log() << Verbose(3) << "q < 0" << endl;
[042f82]856 return false;
857 }
858 x[2] = p + sqrt(q);
859 }
860 x[1] = (-D2 * x[2] - D3)/D1;
861 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];
862 }
863 switch (flag) { // back-flipping
864 default:
865 case 0:
866 break;
867 case 2:
[ad8b0d]868 flip(x1->x[0],x1->x[1]);
869 flip(x2->x[0],x2->x[1]);
870 flip(y->x[0],y->x[1]);
871 flip(x[0],x[1]);
872 flip(x1->x[1],x1->x[2]);
873 flip(x2->x[1],x2->x[2]);
874 flip(y->x[1],y->x[2]);
875 flip(x[1],x[2]);
[042f82]876 case 1:
[ad8b0d]877 flip(x1->x[0],x1->x[1]);
878 flip(x2->x[0],x2->x[1]);
879 flip(y->x[0],y->x[1]);
880 //flip(x[0],x[1]);
881 flip(x1->x[1],x1->x[2]);
882 flip(x2->x[1],x2->x[2]);
883 flip(y->x[1],y->x[2]);
884 flip(x[1],x[2]);
[042f82]885 break;
886 }
887 // one z component is only determined by its radius (without sign)
888 // thus check eight possible sign flips and determine by checking angle with second vector
889 for (i=0;i<8;i++) {
890 // set sign vector accordingly
891 for (j=2;j>=0;j--) {
892 k = (i & pot(2,j)) << j;
[e138de]893 Log() << Verbose(2) << "k " << k << "\tpot(2,j) " << pot(2,j) << endl;
[042f82]894 sign[j] = (k == 0) ? 1. : -1.;
895 }
[e138de]896 Log() << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n";
[042f82]897 // apply sign matrix
898 for (j=NDIM;j--;)
899 x[j] *= sign[j];
900 // calculate angle and check
901 ang = x2->Angle (this);
[e138de]902 Log() << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t";
[042f82]903 if (fabs(ang - cos(beta)) < MYEPSILON) {
904 break;
905 }
906 // unapply sign matrix (is its own inverse)
907 for (j=NDIM;j--;)
908 x[j] *= sign[j];
909 }
910 return true;
[6ac7ee]911};
[89c8b2]912
[0a4f7f]913#endif
914
[89c8b2]915/**
916 * Checks whether this vector is within the parallelepiped defined by the given three vectors and
917 * their offset.
918 *
919 * @param offest for the origin of the parallelepiped
920 * @param three vectors forming the matrix that defines the shape of the parallelpiped
921 */
[776b64]922bool Vector::IsInParallelepiped(const Vector &offset, const double * const parallelepiped) const
[89c8b2]923{
[273382]924 Vector a = (*this) - offset;
[89c8b2]925 a.InverseMatrixMultiplication(parallelepiped);
926 bool isInside = true;
927
928 for (int i=NDIM;i--;)
929 isInside = isInside && ((a.x[i] <= 1) && (a.x[i] >= 0));
930
931 return isInside;
932}
Note: See TracBrowser for help on using the repository browser.