source: src/vector.cpp@ 68cb0f

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 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 68cb0f was 110ceb, checked in by Frederik Heber <heber@…>, 17 years ago

VolumeOfConvexEnvelope: Works!

VolumeOfConvexEnvelope has been analysed into various smaller functions and approach is working.
two new files: boundary.?pp
various new functions:
class Tesselation with AddPoint(), TesselateOnBoundary() and GuessStartingTriangle() does the actual tesselation
CreateClustersinWater() will create the repetition of the cluster with correct spacing (unfinished).
GetDiametersOfCluster() calculate the greatest diameter in projection per axis
GetBoundaryPoints() gets the boundary on the convex envelope by projection for a molecular cluster
GetCommonEndpoint() finds the endpoint two lines are sharing

  • Property mode set to 100644
File size: 24.5 KB
RevLine 
[14de469]1/** \file vector.cpp
2 *
3 * Function implementations for the class vector.
4 *
5 */
6
7#include "molecules.hpp"
8
9
10/************************************ Functions for class vector ************************************/
11
12/** Constructor of class vector.
13 */
14vector::vector() { x[0] = x[1] = x[2] = 0.; };
15
[498a9f]16/** Constructor of class vector.
17 */
18vector::vector(double x1, double x2, double x3) { x[0] = x1; x[1] = x2; x[2] = x3; };
19
[14de469]20/** Desctructor of class vector.
21 */
22vector::~vector() {};
23
24/** Calculates distance between this and another vector.
25 * \param *y array to second vector
26 * \return \f$| x - y |^2\f$
27 */
28double vector::Distance(const vector *y) const
29{
30 double res = 0.;
[7f3b9d]31 for (int i=NDIM;i--;)
[14de469]32 res += (x[i]-y->x[i])*(x[i]-y->x[i]);
33 return (res);
34};
35
36/** Calculates distance between this and another vector in a periodic cell.
37 * \param *y array to second vector
38 * \param *cell_size 6-dimensional array with (xx, xy, yy, xz, yz, zz) entries specifying the periodic cell
39 * \return \f$| x - y |^2\f$
40 */
41double vector::PeriodicDistance(const vector *y, const double *cell_size) const
42{
43 double res = Distance(y), tmp, matrix[NDIM*NDIM];
44 vector Shiftedy, TranslationVector;
45 int N[NDIM];
46 matrix[0] = cell_size[0];
47 matrix[1] = cell_size[1];
48 matrix[2] = cell_size[3];
49 matrix[3] = cell_size[1];
50 matrix[4] = cell_size[2];
51 matrix[5] = cell_size[4];
52 matrix[6] = cell_size[3];
53 matrix[7] = cell_size[4];
54 matrix[8] = cell_size[5];
55 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells
56 for (N[0]=-1;N[0]<=1;N[0]++)
57 for (N[1]=-1;N[1]<=1;N[1]++)
58 for (N[2]=-1;N[2]<=1;N[2]++) {
59 // create the translation vector
60 TranslationVector.Zero();
[7f3b9d]61 for (int i=NDIM;i--;)
[14de469]62 TranslationVector.x[i] = (double)N[i];
63 TranslationVector.MatrixMultiplication(matrix);
64 // add onto the original vector to compare with
65 Shiftedy.CopyVector(y);
66 Shiftedy.AddVector(&TranslationVector);
67 // get distance and compare with minimum so far
68 tmp = Distance(&Shiftedy);
69 if (tmp < res) res = tmp;
70 }
71 return (res);
72};
73
74/** Keeps the vector in a periodic cell, defined by the symmetric \a *matrix.
75 * \param *out ofstream for debugging messages
76 * Tries to translate a vector into each adjacent neighbouring cell.
77 */
78void vector::KeepPeriodic(ofstream *out, double *matrix)
79{
80// int N[NDIM];
81// bool flag = false;
82 //vector Shifted, TranslationVector;
83 vector TestVector;
[db942e]84// *out << Verbose(1) << "Begin of KeepPeriodic." << endl;
85// *out << Verbose(2) << "Vector is: ";
86// Output(out);
87// *out << endl;
[14de469]88 TestVector.CopyVector(this);
89 TestVector.InverseMatrixMultiplication(matrix);
[7f3b9d]90 for(int i=NDIM;i--;) { // correct periodically
[14de469]91 if (TestVector.x[i] < 0) { // get every coefficient into the interval [0,1)
92 TestVector.x[i] += ceil(TestVector.x[i]);
93 } else {
94 TestVector.x[i] -= floor(TestVector.x[i]);
95 }
96 }
97 TestVector.MatrixMultiplication(matrix);
98 CopyVector(&TestVector);
[db942e]99// *out << Verbose(2) << "New corrected vector is: ";
100// Output(out);
101// *out << endl;
102// *out << Verbose(1) << "End of KeepPeriodic." << endl;
[14de469]103};
104
105/** Calculates scalar product between this and another vector.
106 * \param *y array to second vector
107 * \return \f$\langle x, y \rangle\f$
108 */
109double vector::ScalarProduct(const vector *y) const
110{
111 double res = 0.;
[7f3b9d]112 for (int i=NDIM;i--;)
[14de469]113 res += x[i]*y->x[i];
114 return (res);
115};
116
[498a9f]117/** projects this vector onto plane defined by \a *y.
118 * \param *y array to normal vector of plane
119 * \return \f$\langle x, y \rangle\f$
120 */
121void vector::ProjectOntoPlane(const vector *y)
122{
123 vector tmp;
124 tmp.CopyVector(y);
125 tmp.Scale(Projection(y));
126 this->SubtractVector(&tmp);
127};
128
[14de469]129/** Calculates the projection of a vector onto another \a *y.
130 * \param *y array to second vector
131 * \return \f$\langle x, y \rangle\f$
132 */
133double vector::Projection(const vector *y) const
134{
[498a9f]135 return (ScalarProduct(y));
[14de469]136};
137
138/** Calculates norm of this vector.
139 * \return \f$|x|\f$
140 */
141double vector::Norm() const
142{
143 double res = 0.;
[7f3b9d]144 for (int i=NDIM;i--;)
[14de469]145 res += this->x[i]*this->x[i];
146 return (sqrt(res));
147};
148
149/** Normalizes this vector.
150 */
151void vector::Normalize()
152{
153 double res = 0.;
[7f3b9d]154 for (int i=NDIM;i--;)
[14de469]155 res += this->x[i]*this->x[i];
156 res = 1./sqrt(res);
157 Scale(&res);
158};
159
160/** Zeros all components of this vector.
161 */
162void vector::Zero()
163{
[7f3b9d]164 for (int i=NDIM;i--;)
[14de469]165 this->x[i] = 0.;
166};
167
[498a9f]168/** Zeros all components of this vector.
169 */
170void vector::One(double one)
171{
172 for (int i=NDIM;i--;)
173 this->x[i] = one;
174};
175
176/** Initialises all components of this vector.
177 */
178void vector::Init(double x1, double x2, double x3)
179{
180 x[0] = x1;
181 x[1] = x2;
182 x[2] = x3;
183};
184
[14de469]185/** Calculates the angle between this and another vector.
186 * \param *y array to second vector
[498a9f]187 * \return \f$\acos\bigl(frac{\langle x, y \rangle}{|x||y|}\bigr)\f$
[14de469]188 */
189double vector::Angle(vector *y) const
190{
[498a9f]191 return acos(this->ScalarProduct(y)/Norm()/y->Norm());
[14de469]192};
193
194/** Rotates the vector around the axis given by \a *axis by an angle of \a alpha.
195 * \param *axis rotation axis
196 * \param alpha rotation angle in radian
197 */
198void vector::RotateVector(const vector *axis, const double alpha)
199{
200 vector a,y;
201 // normalise this vector with respect to axis
202 a.CopyVector(this);
203 a.Scale(Projection(axis));
204 SubtractVector(&a);
205 // construct normal vector
206 y.MakeNormalVector(axis,this);
207 y.Scale(Norm());
208 // scale normal vector by sine and this vector by cosine
209 y.Scale(sin(alpha));
210 Scale(cos(alpha));
211 // add scaled normal vector onto this vector
212 AddVector(&y);
213 // add part in axis direction
214 AddVector(&a);
215};
216
[342f33f]217/** Sums vector \a to this lhs component-wise.
218 * \param a base vector
219 * \param b vector components to add
220 * \return lhs + a
221 */
222vector& operator+=(vector& a, const vector& b)
223{
224 a.AddVector(&b);
225 return a;
226};
227/** factor each component of \a a times a double \a m.
228 * \param a base vector
229 * \param m factor
230 * \return lhs.x[i] * m
231 */
232vector& operator*=(vector& a, const double m)
233{
234 a.Scale(m);
235 return a;
236};
237
238/** Sums two vectors \a and \b component-wise.
239 * \param a first vector
240 * \param b second vector
241 * \return a + b
242 */
243vector& operator+(const vector& a, const vector& b)
244{
245 vector *x = new vector;
246 x->CopyVector(&a);
247 x->AddVector(&b);
248 return *x;
249};
250
251/** Factors given vector \a a times \a m.
252 * \param a vector
253 * \param m factor
254 * \return a + b
255 */
256vector& operator*(const vector& a, const double m)
257{
258 vector *x = new vector;
259 x->CopyVector(&a);
260 x->Scale(m);
261 return *x;
262};
263
[14de469]264/** Prints a 3dim vector.
265 * prints no end of line.
266 * \param *out output stream
267 */
268bool vector::Output(ofstream *out) const
269{
270 if (out != NULL) {
271 *out << "(";
272 for (int i=0;i<NDIM;i++) {
273 *out << x[i];
274 if (i != 2)
275 *out << ",";
276 }
277 *out << ")";
278 return true;
279 } else
280 return false;
281};
282
283ofstream& operator<<(ofstream& ost,vector& m)
284{
285 m.Output(&ost);
286 return ost;
287};
288
289/** Scales each atom coordinate by an individual \a factor.
290 * \param *factor pointer to scaling factor
291 */
292void vector::Scale(double **factor)
293{
[7f3b9d]294 for (int i=NDIM;i--;)
[342f33f]295 x[i] *= (*factor)[i];
[14de469]296};
297
298void vector::Scale(double *factor)
299{
[7f3b9d]300 for (int i=NDIM;i--;)
[342f33f]301 x[i] *= *factor;
[14de469]302};
303
304void vector::Scale(double factor)
305{
[7f3b9d]306 for (int i=NDIM;i--;)
[342f33f]307 x[i] *= factor;
[14de469]308};
309
310/** Translate atom by given vector.
311 * \param trans[] translation vector.
312 */
313void vector::Translate(const vector *trans)
314{
[7f3b9d]315 for (int i=NDIM;i--;)
[14de469]316 x[i] += trans->x[i];
317};
318
319/** Do a matrix multiplication.
320 * \param *matrix NDIM_NDIM array
321 */
322void vector::MatrixMultiplication(double *M)
323{
324 vector C;
325 // do the matrix multiplication
326 C.x[0] = M[0]*x[0]+M[3]*x[1]+M[6]*x[2];
327 C.x[1] = M[1]*x[0]+M[4]*x[1]+M[7]*x[2];
328 C.x[2] = M[2]*x[0]+M[5]*x[1]+M[8]*x[2];
329 // transfer the result into this
[7f3b9d]330 for (int i=NDIM;i--;)
[14de469]331 x[i] = C.x[i];
332};
333
334/** Do a matrix multiplication with \a *matrix' inverse.
335 * \param *matrix NDIM_NDIM array
336 */
337void vector::InverseMatrixMultiplication(double *A)
338{
339 vector C;
340 double B[NDIM*NDIM];
341 double detA = RDET3(A);
342 double detAReci;
343
344 // calculate the inverse B
345 if (fabs(detA) > MYEPSILON) {; // RDET3(A) yields precisely zero if A irregular
346 detAReci = 1./detA;
347 B[0] = detAReci*RDET2(A[4],A[5],A[7],A[8]); // A_11
348 B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]); // A_12
349 B[2] = detAReci*RDET2(A[1],A[2],A[4],A[5]); // A_13
350 B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]); // A_21
351 B[4] = detAReci*RDET2(A[0],A[2],A[6],A[8]); // A_22
352 B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]); // A_23
353 B[6] = detAReci*RDET2(A[3],A[4],A[6],A[7]); // A_31
354 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]); // A_32
355 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]); // A_33
356
357 // do the matrix multiplication
358 C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2];
359 C.x[1] = B[1]*x[0]+B[4]*x[1]+B[7]*x[2];
360 C.x[2] = B[2]*x[0]+B[5]*x[1]+B[8]*x[2];
361 // transfer the result into this
[7f3b9d]362 for (int i=NDIM;i--;)
[14de469]363 x[i] = C.x[i];
364 } else {
365 cerr << "ERROR: inverse of matrix does not exists!" << endl;
366 }
367};
368
369
370/** Creates this vector as the b y *factors' components scaled linear combination of the given three.
371 * this vector = x1*factors[0] + x2* factors[1] + x3*factors[2]
372 * \param *x1 first vector
373 * \param *x2 second vector
374 * \param *x3 third vector
375 * \param *factors three-component vector with the factor for each given vector
376 */
377void vector::LinearCombinationOfVectors(const vector *x1, const vector *x2, const vector *x3, double *factors)
378{
[7f3b9d]379 for(int i=NDIM;i--;)
[14de469]380 x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i];
381};
382
383/** Mirrors atom against a given plane.
384 * \param n[] normal vector of mirror plane.
385 */
386void vector::Mirror(const vector *n)
387{
388 double projection;
[65684f]389 projection = ScalarProduct(n)/n->ScalarProduct(n); // remove constancy from n (keep as logical one)
[14de469]390 // withdraw projected vector twice from original one
391 cout << Verbose(1) << "Vector: ";
392 Output((ofstream *)&cout);
393 cout << "\t";
[7f3b9d]394 for (int i=NDIM;i--;)
[14de469]395 x[i] -= 2.*projection*n->x[i];
396 cout << "Projected vector: ";
397 Output((ofstream *)&cout);
398 cout << endl;
399};
400
401/** Calculates normal vector for three given vectors (being three points in space).
402 * Makes this vector orthonormal to the three given points, making up a place in 3d space.
403 * \param *y1 first vector
404 * \param *y2 second vector
405 * \param *y3 third vector
406 * \return true - success, vectors are linear independent, false - failure due to linear dependency
407 */
408bool vector::MakeNormalVector(const vector *y1, const vector *y2, const vector *y3)
409{
410 vector x1, x2;
411
412 x1.CopyVector(y1);
413 x1.SubtractVector(y2);
414 x2.CopyVector(y3);
415 x2.SubtractVector(y2);
416 if ((x1.Norm()==0) || (x2.Norm()==0)) {
417 cout << Verbose(4) << "Given vectors are linear dependent." << endl;
418 return false;
419 }
[110ceb]420// cout << Verbose(4) << "relative, first plane coordinates:";
421// x1.Output((ofstream *)&cout);
422// cout << endl;
423// cout << Verbose(4) << "second plane coordinates:";
424// x2.Output((ofstream *)&cout);
425// cout << endl;
[14de469]426
427 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]);
428 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]);
429 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]);
430 Normalize();
431
432 return true;
433};
434
435
436/** Calculates orthonormal vector to two given vectors.
437 * Makes this vector orthonormal to two given vectors. This is very similar to the other
438 * vector::MakeNormalVector(), only there three points whereas here two difference
439 * vectors are given.
440 * \param *x1 first vector
441 * \param *x2 second vector
442 * \return true - success, vectors are linear independent, false - failure due to linear dependency
443 */
444bool vector::MakeNormalVector(const vector *y1, const vector *y2)
445{
446 vector x1,x2;
447 x1.CopyVector(y1);
448 x2.CopyVector(y2);
449 Zero();
450 if ((x1.Norm()==0) || (x2.Norm()==0)) {
451 cout << Verbose(4) << "Given vectors are linear dependent." << endl;
452 return false;
453 }
[110ceb]454// cout << Verbose(4) << "relative, first plane coordinates:";
455// x1.Output((ofstream *)&cout);
456// cout << endl;
457// cout << Verbose(4) << "second plane coordinates:";
458// x2.Output((ofstream *)&cout);
459// cout << endl;
[14de469]460
461 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]);
462 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]);
463 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]);
464 Normalize();
465
466 return true;
467};
468
469/** Calculates orthonormal vector to one given vectors.
470 * Just subtracts the projection onto the given vector from this vector.
471 * \param *x1 vector
472 * \return true - success, false - vector is zero
473 */
474bool vector::MakeNormalVector(const vector *y1)
475{
476 bool result = false;
477 vector x1;
478 x1.CopyVector(y1);
479 x1.Scale(x1.Projection(this));
480 SubtractVector(&x1);
[7f3b9d]481 for (int i=NDIM;i--;)
[14de469]482 result = result || (fabs(x[i]) > MYEPSILON);
483
484 return result;
485};
486
487/** Creates this vector as one of the possible orthonormal ones to the given one.
488 * Just scan how many components of given *vector are unequal to zero and
489 * try to get the skp of both to be zero accordingly.
490 * \param *vector given vector
491 * \return true - success, false - failure (null vector given)
492 */
[65684f]493bool vector::GetOneNormalVector(const vector *GivenVector)
[14de469]494{
495 int Components[NDIM]; // contains indices of non-zero components
496 int Last = 0; // count the number of non-zero entries in vector
497 int j; // loop variables
498 double norm;
499
500 cout << Verbose(4);
[65684f]501 GivenVector->Output((ofstream *)&cout);
[14de469]502 cout << endl;
[7f3b9d]503 for (j=NDIM;j--;)
[14de469]504 Components[j] = -1;
505 // find two components != 0
506 for (j=0;j<NDIM;j++)
[65684f]507 if (fabs(GivenVector->x[j]) > MYEPSILON)
[14de469]508 Components[Last++] = j;
509 cout << Verbose(4) << Last << " Components != 0: (" << Components[0] << "," << Components[1] << "," << Components[2] << ")" << endl;
510
511 switch(Last) {
512 case 3: // threecomponent system
513 case 2: // two component system
[65684f]514 norm = sqrt(1./(GivenVector->x[Components[1]]*GivenVector->x[Components[1]]) + 1./(GivenVector->x[Components[0]]*GivenVector->x[Components[0]]));
[14de469]515 x[Components[2]] = 0.;
516 // in skp both remaining parts shall become zero but with opposite sign and third is zero
[65684f]517 x[Components[1]] = -1./GivenVector->x[Components[1]] / norm;
518 x[Components[0]] = 1./GivenVector->x[Components[0]] / norm;
[14de469]519 return true;
520 break;
521 case 1: // one component system
522 // set sole non-zero component to 0, and one of the other zero component pendants to 1
523 x[(Components[0]+2)%NDIM] = 0.;
524 x[(Components[0]+1)%NDIM] = 1.;
525 x[Components[0]] = 0.;
526 return true;
527 break;
528 default:
529 return false;
530 }
531};
532
[110ceb]533/** Determines paramter needed to multiply this vector to obtain intersection point with plane defined by \a *A, \a *B and \a *C.
534 * \param *A first plane vector
535 * \param *B second plane vector
536 * \param *C third plane vector
537 * \return scaling parameter for this vector
538 */
539double vector::CutsPlaneAt(vector *A, vector *B, vector *C)
540{
541// cout << Verbose(3) << "For comparison: ";
542// cout << "A " << A->Projection(this) << "\t";
543// cout << "B " << B->Projection(this) << "\t";
544// cout << "C " << C->Projection(this) << "\t";
545// cout << endl;
546 return A->Projection(this);
547};
548
[14de469]549/** Creates a new vector as the one with least square distance to a given set of \a vectors.
550 * \param *vectors set of vectors
551 * \param num number of vectors
552 * \return true if success, false if failed due to linear dependency
553 */
554bool vector::LSQdistance(vector **vectors, int num)
555{
556 int j;
557
558 for (j=0;j<num;j++) {
559 cout << Verbose(1) << j << "th atom's vector: ";
560 (vectors[j])->Output((ofstream *)&cout);
561 cout << endl;
562 }
563
564 int np = 3;
565 struct LSQ_params par;
566
567 const gsl_multimin_fminimizer_type *T =
568 gsl_multimin_fminimizer_nmsimplex;
569 gsl_multimin_fminimizer *s = NULL;
[65684f]570 gsl_vector *ss, *y;
[14de469]571 gsl_multimin_function minex_func;
572
573 size_t iter = 0, i;
574 int status;
575 double size;
576
577 /* Initial vertex size vector */
578 ss = gsl_vector_alloc (np);
[65684f]579 y = gsl_vector_alloc (np);
[14de469]580
581 /* Set all step sizes to 1 */
582 gsl_vector_set_all (ss, 1.0);
583
584 /* Starting point */
585 par.vectors = vectors;
586 par.num = num;
587
[7f3b9d]588 for (i=NDIM;i--;)
[65684f]589 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.);
[14de469]590
591 /* Initialize method and iterate */
592 minex_func.f = &LSQ;
593 minex_func.n = np;
594 minex_func.params = (void *)&par;
595
596 s = gsl_multimin_fminimizer_alloc (T, np);
[65684f]597 gsl_multimin_fminimizer_set (s, &minex_func, y, ss);
[14de469]598
599 do
600 {
601 iter++;
602 status = gsl_multimin_fminimizer_iterate(s);
603
604 if (status)
605 break;
606
607 size = gsl_multimin_fminimizer_size (s);
608 status = gsl_multimin_test_size (size, 1e-2);
609
610 if (status == GSL_SUCCESS)
611 {
612 printf ("converged to minimum at\n");
613 }
614
615 printf ("%5d ", (int)iter);
616 for (i = 0; i < (size_t)np; i++)
617 {
618 printf ("%10.3e ", gsl_vector_get (s->x, i));
619 }
620 printf ("f() = %7.3f size = %.3f\n", s->fval, size);
621 }
622 while (status == GSL_CONTINUE && iter < 100);
623
[7f3b9d]624 for (i=(size_t)np;i--;)
[14de469]625 this->x[i] = gsl_vector_get(s->x, i);
[65684f]626 gsl_vector_free(y);
[14de469]627 gsl_vector_free(ss);
628 gsl_multimin_fminimizer_free (s);
629
630 return true;
631};
632
633/** Adds vector \a *y componentwise.
634 * \param *y vector
635 */
636void vector::AddVector(const vector *y)
637{
[7f3b9d]638 for (int i=NDIM;i--;)
[14de469]639 this->x[i] += y->x[i];
640}
641
642/** Adds vector \a *y componentwise.
643 * \param *y vector
644 */
645void vector::SubtractVector(const vector *y)
646{
[7f3b9d]647 for (int i=NDIM;i--;)
[14de469]648 this->x[i] -= y->x[i];
649}
650
651/** Copy vector \a *y componentwise.
652 * \param *y vector
653 */
654void vector::CopyVector(const vector *y)
655{
[7f3b9d]656 for (int i=NDIM;i--;)
[14de469]657 this->x[i] = y->x[i];
658}
659
660
661/** Asks for position, checks for boundary.
662 * \param cell_size unitary size of cubic cell, coordinates must be within 0...cell_size
663 * \param check whether bounds shall be checked (true) or not (false)
664 */
665void vector::AskPosition(double *cell_size, bool check)
666{
667 char coords[3] = {'x','y','z'};
668 int j = -1;
669 for (int i=0;i<3;i++) {
670 j += i+1;
671 do {
672 cout << Verbose(0) << coords[i] << "[0.." << cell_size[j] << "]: ";
673 cin >> x[i];
674 } while (((x[i] < 0) || (x[i] >= cell_size[j])) && (check));
675 }
676};
677
678/** Solves a vectorial system consisting of two orthogonal statements and a norm statement.
679 * This is linear system of equations to be solved, however of the three given (skp of this vector\
680 * with either of the three hast to be zero) only two are linear independent. The third equation
681 * is that the vector should be of magnitude 1 (orthonormal). This all leads to a case-based solution
682 * where very often it has to be checked whether a certain value is zero or not and thus forked into
683 * another case.
684 * \param *x1 first vector
685 * \param *x2 second vector
686 * \param *y third vector
687 * \param alpha first angle
688 * \param beta second angle
689 * \param c norm of final vector
690 * \return a vector with \f$\langle x1,x2 \rangle=A\f$, \f$\langle x1,y \rangle = B\f$ and with norm \a c.
691 * \bug this is not yet working properly
692 */
693bool vector::SolveSystem(vector *x1, vector *x2, vector *y, double alpha, double beta, double c)
694{
695 double D1,D2,D3,E1,E2,F1,F2,F3,p,q=0., A, B1, B2, C;
696 double ang; // angle on testing
697 double sign[3];
698 int i,j,k;
699 A = cos(alpha) * x1->Norm() * c;
700 B1 = cos(beta + M_PI/2.) * y->Norm() * c;
701 B2 = cos(beta) * x2->Norm() * c;
702 C = c * c;
703 cout << Verbose(2) << "A " << A << "\tB " << B1 << "\tC " << C << endl;
704 int flag = 0;
705 if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping
706 if (fabs(x1->x[1]) > MYEPSILON) {
707 flag = 1;
708 } else if (fabs(x1->x[2]) > MYEPSILON) {
709 flag = 2;
710 } else {
711 return false;
712 }
713 }
714 switch (flag) {
715 default:
716 case 0:
717 break;
718 case 2:
719 flip(&x1->x[0],&x1->x[1]);
720 flip(&x2->x[0],&x2->x[1]);
721 flip(&y->x[0],&y->x[1]);
722 //flip(&x[0],&x[1]);
723 flip(&x1->x[1],&x1->x[2]);
724 flip(&x2->x[1],&x2->x[2]);
725 flip(&y->x[1],&y->x[2]);
726 //flip(&x[1],&x[2]);
727 case 1:
728 flip(&x1->x[0],&x1->x[1]);
729 flip(&x2->x[0],&x2->x[1]);
730 flip(&y->x[0],&y->x[1]);
731 //flip(&x[0],&x[1]);
732 flip(&x1->x[1],&x1->x[2]);
733 flip(&x2->x[1],&x2->x[2]);
734 flip(&y->x[1],&y->x[2]);
735 //flip(&x[1],&x[2]);
736 break;
737 }
738 // now comes the case system
739 D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1];
740 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2];
741 D3 = y->x[0]/x1->x[0]*A-B1;
742 cout << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n";
743 if (fabs(D1) < MYEPSILON) {
744 cout << Verbose(2) << "D1 == 0!\n";
745 if (fabs(D2) > MYEPSILON) {
746 cout << Verbose(3) << "D2 != 0!\n";
747 x[2] = -D3/D2;
748 E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2;
749 E2 = -x1->x[1]/x1->x[0];
750 cout << Verbose(3) << "E1 " << E1 << "\tE2 " << E2 << "\n";
751 F1 = E1*E1 + 1.;
752 F2 = -E1*E2;
753 F3 = E1*E1 + D3*D3/(D2*D2) - C;
754 cout << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n";
755 if (fabs(F1) < MYEPSILON) {
756 cout << Verbose(4) << "F1 == 0!\n";
757 cout << Verbose(4) << "Gleichungssystem linear\n";
758 x[1] = F3/(2.*F2);
759 } else {
760 p = F2/F1;
761 q = p*p - F3/F1;
762 cout << Verbose(4) << "p " << p << "\tq " << q << endl;
763 if (q < 0) {
764 cout << Verbose(4) << "q < 0" << endl;
765 return false;
766 }
767 x[1] = p + sqrt(q);
768 }
769 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];
770 } else {
771 cout << Verbose(2) << "Gleichungssystem unterbestimmt\n";
772 return false;
773 }
774 } else {
775 E1 = A/x1->x[0]+x1->x[1]/x1->x[0]*D3/D1;
776 E2 = x1->x[1]/x1->x[0]*D2/D1 - x1->x[2];
777 cout << Verbose(2) << "E1 " << E1 << "\tE2 " << E2 << "\n";
778 F1 = E2*E2 + D2*D2/(D1*D1) + 1.;
779 F2 = -(E1*E2 + D2*D3/(D1*D1));
780 F3 = E1*E1 + D3*D3/(D1*D1) - C;
781 cout << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n";
782 if (fabs(F1) < MYEPSILON) {
783 cout << Verbose(3) << "F1 == 0!\n";
784 cout << Verbose(3) << "Gleichungssystem linear\n";
785 x[2] = F3/(2.*F2);
786 } else {
787 p = F2/F1;
788 q = p*p - F3/F1;
789 cout << Verbose(3) << "p " << p << "\tq " << q << endl;
790 if (q < 0) {
791 cout << Verbose(3) << "q < 0" << endl;
792 return false;
793 }
794 x[2] = p + sqrt(q);
795 }
796 x[1] = (-D2 * x[2] - D3)/D1;
797 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];
798 }
799 switch (flag) { // back-flipping
800 default:
801 case 0:
802 break;
803 case 2:
804 flip(&x1->x[0],&x1->x[1]);
805 flip(&x2->x[0],&x2->x[1]);
806 flip(&y->x[0],&y->x[1]);
807 flip(&x[0],&x[1]);
808 flip(&x1->x[1],&x1->x[2]);
809 flip(&x2->x[1],&x2->x[2]);
810 flip(&y->x[1],&y->x[2]);
811 flip(&x[1],&x[2]);
812 case 1:
813 flip(&x1->x[0],&x1->x[1]);
814 flip(&x2->x[0],&x2->x[1]);
815 flip(&y->x[0],&y->x[1]);
816 //flip(&x[0],&x[1]);
817 flip(&x1->x[1],&x1->x[2]);
818 flip(&x2->x[1],&x2->x[2]);
819 flip(&y->x[1],&y->x[2]);
820 flip(&x[1],&x[2]);
821 break;
822 }
823 // one z component is only determined by its radius (without sign)
824 // thus check eight possible sign flips and determine by checking angle with second vector
825 for (i=0;i<8;i++) {
826 // set sign vector accordingly
827 for (j=2;j>=0;j--) {
828 k = (i & pot(2,j)) << j;
829 cout << Verbose(2) << "k " << k << "\tpot(2,j) " << pot(2,j) << endl;
830 sign[j] = (k == 0) ? 1. : -1.;
831 }
832 cout << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n";
833 // apply sign matrix
[7f3b9d]834 for (j=NDIM;j--;)
[14de469]835 x[j] *= sign[j];
836 // calculate angle and check
837 ang = x2->Angle (this);
838 cout << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t";
839 if (fabs(ang - cos(beta)) < MYEPSILON) {
840 break;
841 }
842 // unapply sign matrix (is its own inverse)
[7f3b9d]843 for (j=NDIM;j--;)
[14de469]844 x[j] *= sign[j];
845 }
846 return true;
847};
Note: See TracBrowser for help on using the repository browser.