source: src/vector.cpp@ e6f8b7

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 e6f8b7 was db942e, checked in by Frederik Heber <heber@…>, 17 years ago

HUGE REWRITE to allow for adaptive increase of the bond order, first working commit

Lots of code was thrown out:
-BottomUp, TopDown and GetAtomicFragments
-TEFactors are now used as "CreationCounters", i.e. the count how often a fragment as been created (ideal would be only once)
-ReduceToUniqueOnes and stuff all thrown out, since they are out-dated since use of hash table
Other changes:
-CreateListofUniqueFragments renamed to PowerSetGenerator
-PowerSetGenerator goes not over all reachable roots, but one given by calling function FragmentBOSSANOVA
-FragmentBOSSANOVA loops over all possible root sites and hands this over to PowerSetGenerator
-by the virtue of the hash table it is not important anymore whether created keysets are unique or not, as this is recognized in log(n). Hence, the label < label is not important anymore (and not applicable in an adaptive scheme with old, parsed keysets and unknown labels) (THIS IS HOWEVER NOT DONE YET!)
The setup is then as follows:

  1. FragmentMolecule
    1. parses adjacency, keysets and orderatsite files
    2. performs DFS to find connected subgraphs (to leave this in was a design decision: might be useful later)
    3. a RootStack is created for every subgraph (here, later we implement the "update 10 sites with highest energy contribution", and that's why this consciously not done in the following loop)
    4. in a loop over all subgraphs

d1. calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure
d2. creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)

  1. combines the generated molecule lists from all subgraphs
  2. saves to disk: fragment configs, adjacency, orderatsite, keyset files
  1. FragmentBOSSANOVA
    1. constructs a complete keyset of the molecule
    2. In a loop over all possible roots from the given rootstack

b1. increases order of root site
b2. calls PowerSetGenerator with this order, the complete keyset and the rootkeynr
b3. for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset as the restricted one and each site in the set as the root)
b4. these are merged into a fragment list of keysets

  1. All fragment lists (for all orders, i.e. from all destination fields) are merged into one list for return
  1. PowerSetGenerator
    1. initialises UniqueFragments structure
    2. fills edge list via BFS
    3. creates the fragment by calling recursive function SPFragmentGenerator with UniqueFragments structure, 0 as root distance, the edge set, its dimension and the current suborder
    4. Free'ing structure
  2. SPFragmentGenerator (nothing much has changed here)
    1. loops over every possible combination (2dimension of edge set)

a1. inserts current set, if there's still space left

a11. yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root distance+1
a12. no: stores fragment into keyset list by calling InsertFragmentIntoGraph

a2. removes all items added into the snake stack (in UniqueFragments structure) added during level (root distance) and current set

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