source: src/molecule_geometry.cpp@ 23b830

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 23b830 was fcd7b6, checked in by Frederik Heber <heber@…>, 16 years ago

In molecule::OutputTrajectories() ActOnAllAtoms() with new function atom::OutputTrajectory() is used.

For this to work, I had to change the Trajectory struct that was so far included in molecule.hpp to be incorporated directly into the class atom.
NOTE: This incorporation is incomplete and a ticket (#34) has been filed to remind of this issue.
However, the trajectory is better suited to reside in atom anyway and was probably just put in molecule due to memory prejudices against STL vector<>.
Functions in molecule.cpp, config.cpp, molecule_geometry.cpp and molecule_dynamics.cpp were adapted (changed from Trajectories[atom *] to atom *->Trajectory).
And the atom pointer in the Trajectory structure was removed.

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