source: src/molecule_geometry.cpp@ d6c485

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 d6c485 was a67d19, checked in by Frederik Heber <heber@…>, 15 years ago

Huge change: Log() << Verbose(.) --> DoLog(.) && (Log() << Verbose(.) << ...);

Most of the files are affected, but this is necessary as if DoLog() says verbosity is not enough, all the stream operators won"t get executed which saves substantial amount of computation time.

Signed-off-by: Frederik Heber <heber@…>

  • Property mode set to 100644
File size: 18.2 KB
Line 
1/*
2 * molecule_geometry.cpp
3 *
4 * Created on: Oct 5, 2009
5 * Author: heber
6 */
7
8#include "atom.hpp"
9#include "bond.hpp"
10#include "config.hpp"
11#include "element.hpp"
12#include "helpers.hpp"
13#include "leastsquaremin.hpp"
14#include "log.hpp"
15#include "memoryallocator.hpp"
16#include "molecule.hpp"
17#include "World.hpp"
18
19/************************************* Functions for class molecule *********************************/
20
21
22/** Centers the molecule in the box whose lengths are defined by vector \a *BoxLengths.
23 * \param *out output stream for debugging
24 */
25bool molecule::CenterInBox()
26{
27 bool status = true;
28 const Vector *Center = DetermineCenterOfAll();
29 double * const cell_size = World::get()->cell_size;
30 double *M = ReturnFullMatrixforSymmetric(cell_size);
31 double *Minv = InverseMatrix(M);
32
33 // go through all atoms
34 ActOnAllVectors( &Vector::SubtractVector, Center);
35 ActOnAllVectors( &Vector::WrapPeriodically, (const double *)M, (const double *)Minv);
36
37 Free(&M);
38 Free(&Minv);
39 delete(Center);
40 return status;
41};
42
43
44/** Bounds the molecule in the box whose lengths are defined by vector \a *BoxLengths.
45 * \param *out output stream for debugging
46 */
47bool molecule::BoundInBox()
48{
49 bool status = true;
50 double * const cell_size = World::get()->cell_size;
51 double *M = ReturnFullMatrixforSymmetric(cell_size);
52 double *Minv = InverseMatrix(M);
53
54 // go through all atoms
55 ActOnAllVectors( &Vector::WrapPeriodically, (const double *)M, (const double *)Minv);
56
57 Free(&M);
58 Free(&Minv);
59 return status;
60};
61
62/** Centers the edge of the atoms at (0,0,0).
63 * \param *out output stream for debugging
64 * \param *max coordinates of other edge, specifying box dimensions.
65 */
66void molecule::CenterEdge(Vector *max)
67{
68 Vector *min = new Vector;
69
70// Log() << Verbose(3) << "Begin of CenterEdge." << endl;
71 atom *ptr = start->next; // start at first in list
72 if (ptr != end) { //list not empty?
73 for (int i=NDIM;i--;) {
74 max->x[i] = ptr->x.x[i];
75 min->x[i] = ptr->x.x[i];
76 }
77 while (ptr->next != end) { // continue with second if present
78 ptr = ptr->next;
79 //ptr->Output(1,1,out);
80 for (int i=NDIM;i--;) {
81 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];
82 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];
83 }
84 }
85// Log() << Verbose(4) << "Maximum is ";
86// max->Output(out);
87// Log() << Verbose(0) << ", Minimum is ";
88// min->Output(out);
89// Log() << Verbose(0) << endl;
90 min->Scale(-1.);
91 max->AddVector(min);
92 Translate(min);
93 Center.Zero();
94 }
95 delete(min);
96// Log() << Verbose(3) << "End of CenterEdge." << endl;
97};
98
99/** Centers the center of the atoms at (0,0,0).
100 * \param *out output stream for debugging
101 * \param *center return vector for translation vector
102 */
103void molecule::CenterOrigin()
104{
105 int Num = 0;
106 atom *ptr = start; // start at first in list
107
108 Center.Zero();
109
110 if (ptr->next != end) { //list not empty?
111 while (ptr->next != end) { // continue with second if present
112 ptr = ptr->next;
113 Num++;
114 Center.AddVector(&ptr->x);
115 }
116 Center.Scale(-1./Num); // divide through total number (and sign for direction)
117 Translate(&Center);
118 Center.Zero();
119 }
120};
121
122/** Returns vector pointing to center of all atoms.
123 * \return pointer to center of all vector
124 */
125Vector * molecule::DetermineCenterOfAll() const
126{
127 atom *ptr = start->next; // start at first in list
128 Vector *a = new Vector();
129 Vector tmp;
130 double Num = 0;
131
132 a->Zero();
133
134 if (ptr != end) { //list not empty?
135 while (ptr->next != end) { // continue with second if present
136 ptr = ptr->next;
137 Num += 1.;
138 tmp.CopyVector(&ptr->x);
139 a->AddVector(&tmp);
140 }
141 a->Scale(1./Num); // divide through total mass (and sign for direction)
142 }
143 return a;
144};
145
146/** Returns vector pointing to center of gravity.
147 * \param *out output stream for debugging
148 * \return pointer to center of gravity vector
149 */
150Vector * molecule::DetermineCenterOfGravity()
151{
152 atom *ptr = start->next; // start at first in list
153 Vector *a = new Vector();
154 Vector tmp;
155 double Num = 0;
156
157 a->Zero();
158
159 if (ptr != end) { //list not empty?
160 while (ptr->next != end) { // continue with second if present
161 ptr = ptr->next;
162 Num += ptr->type->mass;
163 tmp.CopyVector(&ptr->x);
164 tmp.Scale(ptr->type->mass); // scale by mass
165 a->AddVector(&tmp);
166 }
167 a->Scale(-1./Num); // divide through total mass (and sign for direction)
168 }
169// Log() << Verbose(1) << "Resulting center of gravity: ";
170// a->Output(out);
171// Log() << Verbose(0) << endl;
172 return a;
173};
174
175/** Centers the center of gravity of the atoms at (0,0,0).
176 * \param *out output stream for debugging
177 * \param *center return vector for translation vector
178 */
179void molecule::CenterPeriodic()
180{
181 DeterminePeriodicCenter(Center);
182};
183
184
185/** Centers the center of gravity of the atoms at (0,0,0).
186 * \param *out output stream for debugging
187 * \param *center return vector for translation vector
188 */
189void molecule::CenterAtVector(Vector *newcenter)
190{
191 Center.CopyVector(newcenter);
192};
193
194
195/** Scales all atoms by \a *factor.
196 * \param *factor pointer to scaling factor
197 */
198void molecule::Scale(const double ** const factor)
199{
200 atom *ptr = start;
201
202 while (ptr->next != end) {
203 ptr = ptr->next;
204 for (int j=0;j<MDSteps;j++)
205 ptr->Trajectory.R.at(j).Scale(factor);
206 ptr->x.Scale(factor);
207 }
208};
209
210/** Translate all atoms by given vector.
211 * \param trans[] translation vector.
212 */
213void molecule::Translate(const Vector *trans)
214{
215 atom *ptr = start;
216
217 while (ptr->next != end) {
218 ptr = ptr->next;
219 for (int j=0;j<MDSteps;j++)
220 ptr->Trajectory.R.at(j).Translate(trans);
221 ptr->x.Translate(trans);
222 }
223};
224
225/** Translate the molecule periodically in the box.
226 * \param trans[] translation vector.
227 * TODO treatment of trajetories missing
228 */
229void molecule::TranslatePeriodically(const Vector *trans)
230{
231 double * const cell_size = World::get()->cell_size;
232 double *M = ReturnFullMatrixforSymmetric(cell_size);
233 double *Minv = InverseMatrix(M);
234
235 // go through all atoms
236 ActOnAllVectors( &Vector::SubtractVector, trans);
237 ActOnAllVectors( &Vector::WrapPeriodically, (const double *)M, (const double *)Minv);
238
239 Free(&M);
240 Free(&Minv);
241};
242
243
244/** Mirrors all atoms against a given plane.
245 * \param n[] normal vector of mirror plane.
246 */
247void molecule::Mirror(const Vector *n)
248{
249 ActOnAllVectors( &Vector::Mirror, n );
250};
251
252/** Determines center of molecule (yet not considering atom masses).
253 * \param center reference to return vector
254 */
255void molecule::DeterminePeriodicCenter(Vector &center)
256{
257 atom *Walker = start;
258 double * const cell_size = World::get()->cell_size;
259 double *matrix = ReturnFullMatrixforSymmetric(cell_size);
260 double *inversematrix = InverseMatrix(cell_size);
261 double tmp;
262 bool flag;
263 Vector Testvector, Translationvector;
264
265 do {
266 Center.Zero();
267 flag = true;
268 while (Walker->next != end) {
269 Walker = Walker->next;
270#ifdef ADDHYDROGEN
271 if (Walker->type->Z != 1) {
272#endif
273 Testvector.CopyVector(&Walker->x);
274 Testvector.MatrixMultiplication(inversematrix);
275 Translationvector.Zero();
276 for (BondList::const_iterator Runner = Walker->ListOfBonds.begin(); Runner != Walker->ListOfBonds.end(); (++Runner)) {
277 if (Walker->nr < (*Runner)->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing
278 for (int j=0;j<NDIM;j++) {
279 tmp = Walker->x.x[j] - (*Runner)->GetOtherAtom(Walker)->x.x[j];
280 if ((fabs(tmp)) > BondDistance) {
281 flag = false;
282 DoLog(0) && (Log() << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *(*Runner) << " has to be shifted due to " << tmp << "." << endl);
283 if (tmp > 0)
284 Translationvector.x[j] -= 1.;
285 else
286 Translationvector.x[j] += 1.;
287 }
288 }
289 }
290 Testvector.AddVector(&Translationvector);
291 Testvector.MatrixMultiplication(matrix);
292 Center.AddVector(&Testvector);
293 DoLog(1) && (Log() << Verbose(1) << "vector is: ");
294 Testvector.Output();
295 DoLog(0) && (Log() << Verbose(0) << endl);
296#ifdef ADDHYDROGEN
297 // now also change all hydrogens
298 for (BondList::const_iterator Runner = Walker->ListOfBonds.begin(); Runner != Walker->ListOfBonds.end(); (++Runner)) {
299 if ((*Runner)->GetOtherAtom(Walker)->type->Z == 1) {
300 Testvector.CopyVector(&(*Runner)->GetOtherAtom(Walker)->x);
301 Testvector.MatrixMultiplication(inversematrix);
302 Testvector.AddVector(&Translationvector);
303 Testvector.MatrixMultiplication(matrix);
304 Center.AddVector(&Testvector);
305 DoLog(1) && (Log() << Verbose(1) << "Hydrogen vector is: ");
306 Testvector.Output();
307 DoLog(0) && (Log() << Verbose(0) << endl);
308 }
309 }
310 }
311#endif
312 }
313 } while (!flag);
314 Free(&matrix);
315 Free(&inversematrix);
316
317 Center.Scale(1./(double)AtomCount);
318};
319
320/** Transforms/Rotates the given molecule into its principal axis system.
321 * \param *out output stream for debugging
322 * \param DoRotate whether to rotate (true) or only to determine the PAS.
323 * TODO treatment of trajetories missing
324 */
325void molecule::PrincipalAxisSystem(bool DoRotate)
326{
327 atom *ptr = start; // start at first in list
328 double InertiaTensor[NDIM*NDIM];
329 Vector *CenterOfGravity = DetermineCenterOfGravity();
330
331 CenterPeriodic();
332
333 // reset inertia tensor
334 for(int i=0;i<NDIM*NDIM;i++)
335 InertiaTensor[i] = 0.;
336
337 // sum up inertia tensor
338 while (ptr->next != end) {
339 ptr = ptr->next;
340 Vector x;
341 x.CopyVector(&ptr->x);
342 //x.SubtractVector(CenterOfGravity);
343 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
344 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
345 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
346 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
347 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
348 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
349 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
350 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
351 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
352 }
353 // print InertiaTensor for debugging
354 DoLog(0) && (Log() << Verbose(0) << "The inertia tensor is:" << endl);
355 for(int i=0;i<NDIM;i++) {
356 for(int j=0;j<NDIM;j++)
357 DoLog(0) && (Log() << Verbose(0) << InertiaTensor[i*NDIM+j] << " ");
358 DoLog(0) && (Log() << Verbose(0) << endl);
359 }
360 DoLog(0) && (Log() << Verbose(0) << endl);
361
362 // diagonalize to determine principal axis system
363 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM);
364 gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM);
365 gsl_vector *eval = gsl_vector_alloc(NDIM);
366 gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM);
367 gsl_eigen_symmv(&m.matrix, eval, evec, T);
368 gsl_eigen_symmv_free(T);
369 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC);
370
371 for(int i=0;i<NDIM;i++) {
372 DoLog(1) && (Log() << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i));
373 DoLog(0) && (Log() << Verbose(0) << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl);
374 }
375
376 // check whether we rotate or not
377 if (DoRotate) {
378 DoLog(1) && (Log() << Verbose(1) << "Transforming molecule into PAS ... ");
379 // the eigenvectors specify the transformation matrix
380 ActOnAllVectors( &Vector::MatrixMultiplication, (const double *) evec->data );
381 DoLog(0) && (Log() << Verbose(0) << "done." << endl);
382
383 // summing anew for debugging (resulting matrix has to be diagonal!)
384 // reset inertia tensor
385 for(int i=0;i<NDIM*NDIM;i++)
386 InertiaTensor[i] = 0.;
387
388 // sum up inertia tensor
389 ptr = start;
390 while (ptr->next != end) {
391 ptr = ptr->next;
392 Vector x;
393 x.CopyVector(&ptr->x);
394 //x.SubtractVector(CenterOfGravity);
395 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
396 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
397 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
398 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
399 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
400 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
401 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
402 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
403 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
404 }
405 // print InertiaTensor for debugging
406 DoLog(0) && (Log() << Verbose(0) << "The inertia tensor is:" << endl);
407 for(int i=0;i<NDIM;i++) {
408 for(int j=0;j<NDIM;j++)
409 DoLog(0) && (Log() << Verbose(0) << InertiaTensor[i*NDIM+j] << " ");
410 DoLog(0) && (Log() << Verbose(0) << endl);
411 }
412 DoLog(0) && (Log() << Verbose(0) << endl);
413 }
414
415 // free everything
416 delete(CenterOfGravity);
417 gsl_vector_free(eval);
418 gsl_matrix_free(evec);
419};
420
421
422/** Align all atoms in such a manner that given vector \a *n is along z axis.
423 * \param n[] alignment vector.
424 */
425void molecule::Align(Vector *n)
426{
427 atom *ptr = start;
428 double alpha, tmp;
429 Vector z_axis;
430 z_axis.x[0] = 0.;
431 z_axis.x[1] = 0.;
432 z_axis.x[2] = 1.;
433
434 // rotate on z-x plane
435 DoLog(0) && (Log() << Verbose(0) << "Begin of Aligning all atoms." << endl);
436 alpha = atan(-n->x[0]/n->x[2]);
437 DoLog(1) && (Log() << Verbose(1) << "Z-X-angle: " << alpha << " ... ");
438 while (ptr->next != end) {
439 ptr = ptr->next;
440 tmp = ptr->x.x[0];
441 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
442 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
443 for (int j=0;j<MDSteps;j++) {
444 tmp = ptr->Trajectory.R.at(j).x[0];
445 ptr->Trajectory.R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * ptr->Trajectory.R.at(j).x[2];
446 ptr->Trajectory.R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->Trajectory.R.at(j).x[2];
447 }
448 }
449 // rotate n vector
450 tmp = n->x[0];
451 n->x[0] = cos(alpha) * tmp + sin(alpha) * n->x[2];
452 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2];
453 DoLog(1) && (Log() << Verbose(1) << "alignment vector after first rotation: ");
454 n->Output();
455 DoLog(0) && (Log() << Verbose(0) << endl);
456
457 // rotate on z-y plane
458 ptr = start;
459 alpha = atan(-n->x[1]/n->x[2]);
460 DoLog(1) && (Log() << Verbose(1) << "Z-Y-angle: " << alpha << " ... ");
461 while (ptr->next != end) {
462 ptr = ptr->next;
463 tmp = ptr->x.x[1];
464 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
465 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
466 for (int j=0;j<MDSteps;j++) {
467 tmp = ptr->Trajectory.R.at(j).x[1];
468 ptr->Trajectory.R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * ptr->Trajectory.R.at(j).x[2];
469 ptr->Trajectory.R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->Trajectory.R.at(j).x[2];
470 }
471 }
472 // rotate n vector (for consistency check)
473 tmp = n->x[1];
474 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2];
475 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2];
476
477 DoLog(1) && (Log() << Verbose(1) << "alignment vector after second rotation: ");
478 n->Output();
479 DoLog(1) && (Log() << Verbose(1) << endl);
480 DoLog(0) && (Log() << Verbose(0) << "End of Aligning all atoms." << endl);
481};
482
483
484/** Calculates sum over least square distance to line hidden in \a *x.
485 * \param *x offset and direction vector
486 * \param *params pointer to lsq_params structure
487 * \return \f$ sum_i^N | y_i - (a + t_i b)|^2\f$
488 */
489double LeastSquareDistance (const gsl_vector * x, void * params)
490{
491 double res = 0, t;
492 Vector a,b,c,d;
493 struct lsq_params *par = (struct lsq_params *)params;
494 atom *ptr = par->mol->start;
495
496 // initialize vectors
497 a.x[0] = gsl_vector_get(x,0);
498 a.x[1] = gsl_vector_get(x,1);
499 a.x[2] = gsl_vector_get(x,2);
500 b.x[0] = gsl_vector_get(x,3);
501 b.x[1] = gsl_vector_get(x,4);
502 b.x[2] = gsl_vector_get(x,5);
503 // go through all atoms
504 while (ptr != par->mol->end) {
505 ptr = ptr->next;
506 if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type
507 c.CopyVector(&ptr->x); // copy vector to temporary one
508 c.SubtractVector(&a); // subtract offset vector
509 t = c.ScalarProduct(&b); // get direction parameter
510 d.CopyVector(&b); // and create vector
511 d.Scale(&t);
512 c.SubtractVector(&d); // ... yielding distance vector
513 res += d.ScalarProduct((const Vector *)&d); // add squared distance
514 }
515 }
516 return res;
517};
518
519/** By minimizing the least square distance gains alignment vector.
520 * \bug this is not yet working properly it seems
521 */
522void molecule::GetAlignvector(struct lsq_params * par) const
523{
524 int np = 6;
525
526 const gsl_multimin_fminimizer_type *T =
527 gsl_multimin_fminimizer_nmsimplex;
528 gsl_multimin_fminimizer *s = NULL;
529 gsl_vector *ss;
530 gsl_multimin_function minex_func;
531
532 size_t iter = 0, i;
533 int status;
534 double size;
535
536 /* Initial vertex size vector */
537 ss = gsl_vector_alloc (np);
538
539 /* Set all step sizes to 1 */
540 gsl_vector_set_all (ss, 1.0);
541
542 /* Starting point */
543 par->x = gsl_vector_alloc (np);
544 par->mol = this;
545
546 gsl_vector_set (par->x, 0, 0.0); // offset
547 gsl_vector_set (par->x, 1, 0.0);
548 gsl_vector_set (par->x, 2, 0.0);
549 gsl_vector_set (par->x, 3, 0.0); // direction
550 gsl_vector_set (par->x, 4, 0.0);
551 gsl_vector_set (par->x, 5, 1.0);
552
553 /* Initialize method and iterate */
554 minex_func.f = &LeastSquareDistance;
555 minex_func.n = np;
556 minex_func.params = (void *)par;
557
558 s = gsl_multimin_fminimizer_alloc (T, np);
559 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss);
560
561 do
562 {
563 iter++;
564 status = gsl_multimin_fminimizer_iterate(s);
565
566 if (status)
567 break;
568
569 size = gsl_multimin_fminimizer_size (s);
570 status = gsl_multimin_test_size (size, 1e-2);
571
572 if (status == GSL_SUCCESS)
573 {
574 printf ("converged to minimum at\n");
575 }
576
577 printf ("%5d ", (int)iter);
578 for (i = 0; i < (size_t)np; i++)
579 {
580 printf ("%10.3e ", gsl_vector_get (s->x, i));
581 }
582 printf ("f() = %7.3f size = %.3f\n", s->fval, size);
583 }
584 while (status == GSL_CONTINUE && iter < 100);
585
586 for (i=0;i<(size_t)np;i++)
587 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i));
588 //gsl_vector_free(par->x);
589 gsl_vector_free(ss);
590 gsl_multimin_fminimizer_free (s);
591};
Note: See TracBrowser for help on using the repository browser.