source: src/builder.cpp@ 08f1a0

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 08f1a0 was 73f80e, checked in by Frederik Heber <heber@…>, 17 years ago

new elementsdb-switch and command line options parsing parts moved around to accomodate.

New switch (just sets a variable) made some moving around necessary. Elements db cannot be parsed right at the start anymore, neither the config file before the command line switches. Hence, the following is now in operation:

  1. first parse through all options for stuff just setting variables, giving help et al
  2. parse elements db
  3. parse config file if present
  4. parse again through options for those that actually operate on a given configuration or add atoms (parsing xyz) ...

This was necessary, as 'make check' could not be made workable otherwise and its "bad behaviour" if the code assumes the elements.db to be in the same dir as the exe.

  • Property mode set to 100644
File size: 47.7 KB
Line 
1/** \file builder.cpp
2 *
3 * By stating absolute positions or binding angles and distances atomic positions of a molecule can be constructed.
4 * The output is the complete configuration file for PCP for direct use.
5 * Features:
6 * -# Atomic data is retrieved from a file, if not found requested and stored there for later re-use
7 * -# step-by-step construction of the molecule beginning either at a centre of with a certain atom
8 *
9 */
10
11/*! \mainpage Molecuilder - a molecular set builder
12 *
13 * This introductory shall briefly make aquainted with the program, helping in installing and a first run.
14 *
15 * \section about About the Program
16 *
17 * Molecuilder is a short program, written in C++, that enables the construction of a coordinate set for the
18 * atoms making up an molecule by the successive statement of binding angles and distances and referencing to
19 * already constructed atoms.
20 *
21 * A configuration file may be written that is compatible to the format used by PCP - a parallel Car-Parrinello
22 * molecular dynamics implementation.
23 *
24 * \section install Installation
25 *
26 * Installation should without problems succeed as follows:
27 * -# ./configure (or: mkdir build;mkdir run;cd build; ../configure --bindir=../run)
28 * -# make
29 * -# make install
30 *
31 * Further useful commands are
32 * -# make clean uninstall: deletes .o-files and removes executable from the given binary directory\n
33 * -# make doxygen-doc: Creates these html pages out of the documented source
34 *
35 * \section run Running
36 *
37 * The program can be executed by running: ./molecuilder
38 *
39 * Note, that it uses a database, called "elements.db", in the executable's directory. If the file is not found,
40 * it is created and any given data on elements of the periodic table will be stored therein and re-used on
41 * later re-execution.
42 *
43 * \section ref References
44 *
45 * For the special configuration file format, see the documentation of pcp.
46 *
47 */
48
49
50using namespace std;
51
52#include "helpers.hpp"
53#include "molecules.hpp"
54
55/********************************************** Submenu routine **************************************/
56
57/** Submenu for adding atoms to the molecule.
58 * \param *periode periodentafel
59 * \param *mol the molecule to add to
60 */
61void AddAtoms(periodentafel *periode, molecule *mol)
62{
63 atom *first, *second, *third, *fourth;
64 vector **atoms;
65 vector x,y,z,n; // coordinates for absolute point in cell volume
66 double a,b,c;
67 char choice; // menu choice char
68 bool valid;
69
70 cout << Verbose(0) << "===========ADD ATOM============================" << endl;
71 cout << Verbose(0) << " a - state absolute coordinates of atom" << endl;
72 cout << Verbose(0) << " b - state relative coordinates of atom wrt to reference point" << endl;
73 cout << Verbose(0) << " c - state relative coordinates of atom wrt to already placed atom" << endl;
74 cout << Verbose(0) << " d - state two atoms, two angles and a distance" << endl;
75 cout << Verbose(0) << " e - least square distance position to a set of atoms" << endl;
76 cout << Verbose(0) << "all else - go back" << endl;
77 cout << Verbose(0) << "===============================================" << endl;
78 cout << Verbose(0) << "Note: Specifiy angles in degrees not multiples of Pi!" << endl;
79 cout << Verbose(0) << "INPUT: ";
80 cin >> choice;
81
82 switch (choice) {
83 case 'a': // absolute coordinates of atom
84 cout << Verbose(0) << "Enter absolute coordinates." << endl;
85 first = new atom;
86 first->x.AskPosition(mol->cell_size, false);
87 first->type = periode->AskElement(); // give type
88 mol->AddAtom(first); // add to molecule
89 break;
90
91 case 'b': // relative coordinates of atom wrt to reference point
92 first = new atom;
93 valid = true;
94 do {
95 if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl;
96 cout << Verbose(0) << "Enter reference coordinates." << endl;
97 x.AskPosition(mol->cell_size, true);
98 cout << Verbose(0) << "Enter relative coordinates." << endl;
99 first->x.AskPosition(mol->cell_size, false);
100 first->x.AddVector((const vector *)&x);
101 cout << Verbose(0) << "\n";
102 } while (!(valid = mol->CheckBounds((const vector *)&first->x)));
103 first->type = periode->AskElement(); // give type
104 mol->AddAtom(first); // add to molecule
105 break;
106
107 case 'c': // relative coordinates of atom wrt to already placed atom
108 first = new atom;
109 valid = true;
110 do {
111 if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl;
112 second = mol->AskAtom("Enter atom number: ");
113 cout << Verbose(0) << "Enter relative coordinates." << endl;
114 first->x.AskPosition(mol->cell_size, false);
115 for (int i=0;i<3;i++) {
116 first->x.x[i] += second->x.x[i];
117 }
118 } while (!(valid = mol->CheckBounds((const vector *)&first->x)));
119 first->type = periode->AskElement(); // give type
120 mol->AddAtom(first); // add to molecule
121 break;
122
123 case 'd': // two atoms, two angles and a distance
124 first = new atom;
125 valid = true;
126 do {
127 if (!valid) {
128 cout << Verbose(0) << "Resulting coordinates out of cell - ";
129 first->x.Output((ofstream *)&cout);
130 cout << Verbose(0) << endl;
131 }
132 cout << Verbose(0) << "First, we need two atoms, the first atom is the central, while the second is the outer one." << endl;
133 second = mol->AskAtom("Enter central atom: ");
134 third = mol->AskAtom("Enter second atom (specifying the axis for first angle): ");
135 fourth = mol->AskAtom("Enter third atom (specifying a plane for second angle): ");
136 a = ask_value("Enter distance between central (first) and new atom: ");
137 b = ask_value("Enter angle between new, first and second atom (degrees): ");
138 b *= M_PI/180.;
139 bound(&b, 0., 2.*M_PI);
140 c = ask_value("Enter second angle between new and normal vector of plane defined by first, second and third atom (degrees): ");
141 c *= M_PI/180.;
142 bound(&c, -M_PI, M_PI);
143 cout << Verbose(0) << "radius: " << a << "\t phi: " << b*180./M_PI << "\t theta: " << c*180./M_PI << endl;
144/*
145 second->Output(1,1,(ofstream *)&cout);
146 third->Output(1,2,(ofstream *)&cout);
147 fourth->Output(1,3,(ofstream *)&cout);
148 n.MakeNormalVector((const vector *)&second->x, (const vector *)&third->x, (const vector *)&fourth->x);
149 x.CopyVector(&second->x);
150 x.SubtractVector(&third->x);
151 x.CopyVector(&fourth->x);
152 x.SubtractVector(&third->x);
153
154 if (!z.SolveSystem(&x,&y,&n, b, c, a)) {
155 cout << Verbose(0) << "Failure solving self-dependent linear system!" << endl;
156 continue;
157 }
158 cout << Verbose(0) << "resulting relative coordinates: ";
159 z.Output((ofstream *)&cout);
160 cout << Verbose(0) << endl;
161 */
162 // calc axis vector
163 x.CopyVector(&second->x);
164 x.SubtractVector(&third->x);
165 x.Normalize();
166 cout << "x: ",
167 x.Output((ofstream *)&cout);
168 cout << endl;
169 z.MakeNormalVector(&second->x,&third->x,&fourth->x);
170 cout << "z: ",
171 z.Output((ofstream *)&cout);
172 cout << endl;
173 y.MakeNormalVector(&x,&z);
174 cout << "y: ",
175 y.Output((ofstream *)&cout);
176 cout << endl;
177
178 // rotate vector around first angle
179 first->x.CopyVector(&x);
180 first->x.RotateVector(&z,b - M_PI);
181 cout << "Rotated vector: ",
182 first->x.Output((ofstream *)&cout);
183 cout << endl;
184 // remove the projection onto the rotation plane of the second angle
185 n.CopyVector(&y);
186 n.Scale(first->x.Projection(&y));
187 cout << "N1: ",
188 n.Output((ofstream *)&cout);
189 cout << endl;
190 first->x.SubtractVector(&n);
191 cout << "Subtracted vector: ",
192 first->x.Output((ofstream *)&cout);
193 cout << endl;
194 n.CopyVector(&z);
195 n.Scale(first->x.Projection(&z));
196 cout << "N2: ",
197 n.Output((ofstream *)&cout);
198 cout << endl;
199 first->x.SubtractVector(&n);
200 cout << "2nd subtracted vector: ",
201 first->x.Output((ofstream *)&cout);
202 cout << endl;
203
204 // rotate another vector around second angle
205 n.CopyVector(&y);
206 n.RotateVector(&x,c - M_PI);
207 cout << "2nd Rotated vector: ",
208 n.Output((ofstream *)&cout);
209 cout << endl;
210
211 // add the two linear independent vectors
212 first->x.AddVector(&n);
213 first->x.Normalize();
214 first->x.Scale(a);
215 first->x.AddVector(&second->x);
216
217 cout << Verbose(0) << "resulting coordinates: ";
218 first->x.Output((ofstream *)&cout);
219 cout << Verbose(0) << endl;
220 } while (!(valid = mol->CheckBounds((const vector *)&first->x)));
221 first->type = periode->AskElement(); // give type
222 mol->AddAtom(first); // add to molecule
223 break;
224
225 case 'e': // least square distance position to a set of atoms
226 first = new atom;
227 atoms = new (vector*[128]);
228 valid = true;
229 for(int i=0;i<128;i++)
230 atoms[i] = NULL;
231 int i=0, j=0;
232 cout << Verbose(0) << "Now we need at least three molecules.\n";
233 do {
234 cout << Verbose(0) << "Enter " << i+1 << "th atom: ";
235 cin >> j;
236 if (j != -1) {
237 second = mol->FindAtom(j);
238 atoms[i++] = &(second->x);
239 }
240 } while ((j != -1) && (i<128));
241 if (i >= 2) {
242 first->x.LSQdistance(atoms, i);
243
244 first->x.Output((ofstream *)&cout);
245 first->type = periode->AskElement(); // give type
246 mol->AddAtom(first); // add to molecule
247 } else {
248 delete first;
249 cout << Verbose(0) << "Please enter at least two vectors!\n";
250 }
251 break;
252 };
253};
254
255/** Submenu for centering the atoms in the molecule.
256 * \param *mol the molecule with all the atoms
257 */
258void CenterAtoms(molecule *mol)
259{
260 vector x;
261 char choice; // menu choice char
262 double min[3];
263 int j;
264
265 cout << Verbose(0) << "===========CENTER ATOMS=========================" << endl;
266 cout << Verbose(0) << " a - on origin" << endl;
267 cout << Verbose(0) << " b - on center of gravity" << endl;
268 cout << Verbose(0) << " c - within box with additional boundary" << endl;
269 cout << Verbose(0) << "all else - go back" << endl;
270 cout << Verbose(0) << "===============================================" << endl;
271 cout << Verbose(0) << "INPUT: ";
272 cin >> choice;
273
274 switch (choice) {
275 default:
276 cout << Verbose(0) << "Not a valid choice." << endl;
277 break;
278 case 'a':
279 cout << Verbose(0) << "Centering atoms in config file on origin." << endl;
280 mol->CenterOrigin((ofstream *)&cout, &x);
281 break;
282 case 'b':
283 cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl;
284 mol->CenterGravity((ofstream *)&cout, &x);
285 break;
286 case 'c':
287 cout << Verbose(0) << "Centering atoms in config file within given additional boundary." << endl;
288 for (int i=0;i<3;i++) {
289 cout << Verbose(0) << "Enter axis " << i << " boundary: ";
290 cin >> min[i];
291 }
292 mol->CenterEdge((ofstream *)&cout, &x); // make every coordinate positive
293 mol->SetBoxDimension(&x); // update Box of atoms by boundary
294 // translate each coordinate by boundary
295 j=-1;
296 for (int i=0;i<NDIM;i++) {
297 j += i+1;
298 x.x[i] = min[i];
299 mol->cell_size[j] += x.x[i]*2.;
300 }
301 mol->Translate(&x);
302 break;
303 }
304};
305
306/** Submenu for aligning the atoms in the molecule.
307 * \param *periode periodentafel
308 * \param *mol the molecule with all the atoms
309 */
310void AlignAtoms(periodentafel *periode, molecule *mol)
311{
312 atom *first, *second, *third;
313 vector x,n;
314 char choice; // menu choice char
315
316 cout << Verbose(0) << "===========ALIGN ATOMS=========================" << endl;
317 cout << Verbose(0) << " a - state three atoms defining align plane" << endl;
318 cout << Verbose(0) << " b - state alignment vector" << endl;
319 cout << Verbose(0) << " c - state two atoms in alignment direction" << endl;
320 cout << Verbose(0) << " d - align automatically by least square fit" << endl;
321 cout << Verbose(0) << "all else - go back" << endl;
322 cout << Verbose(0) << "===============================================" << endl;
323 cout << Verbose(0) << "INPUT: ";
324 cin >> choice;
325
326 switch (choice) {
327 default:
328 case 'a': // three atoms defining mirror plane
329 first = mol->AskAtom("Enter first atom: ");
330 second = mol->AskAtom("Enter second atom: ");
331 third = mol->AskAtom("Enter third atom: ");
332
333 n.MakeNormalVector((const vector *)&first->x,(const vector *)&second->x,(const vector *)&third->x);
334 break;
335 case 'b': // normal vector of mirror plane
336 cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
337 n.AskPosition(mol->cell_size,0);
338 n.Normalize();
339 break;
340 case 'c': // three atoms defining mirror plane
341 first = mol->AskAtom("Enter first atom: ");
342 second = mol->AskAtom("Enter second atom: ");
343
344 n.CopyVector((const vector *)&first->x);
345 n.SubtractVector((const vector *)&second->x);
346 n.Normalize();
347 break;
348 case 'd':
349 char shorthand[4];
350 vector a;
351 struct lsq_params param;
352 do {
353 fprintf(stdout, "Enter the element of atoms to be chosen: ");
354 fscanf(stdin, "%3s", shorthand);
355 } while ((param.type = periode->FindElement(shorthand)) == NULL);
356 cout << Verbose(0) << "Element is " << param.type->name << endl;
357 mol->GetAlignVector(&param);
358 for (int i=0;i<3;i++) {
359 x.x[i] = gsl_vector_get(param.x,i);
360 n.x[i] = gsl_vector_get(param.x,i+3);
361 }
362 gsl_vector_free(param.x);
363 cout << Verbose(0) << "Offset vector: ";
364 x.Output((ofstream *)&cout);
365 cout << Verbose(0) << endl;
366 n.Normalize();
367 break;
368 };
369 cout << Verbose(0) << "Alignment vector: ";
370 n.Output((ofstream *)&cout);
371 cout << Verbose(0) << endl;
372 mol->Align(&n);
373};
374
375/** Submenu for mirroring the atoms in the molecule.
376 * \param *mol the molecule with all the atoms
377 */
378void MirrorAtoms(molecule *mol)
379{
380 atom *first, *second, *third;
381 vector n;
382 char choice; // menu choice char
383
384 cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl;
385 cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl;
386 cout << Verbose(0) << " b - state normal vector of mirror plane" << endl;
387 cout << Verbose(0) << " c - state two atoms in normal direction" << endl;
388 cout << Verbose(0) << "all else - go back" << endl;
389 cout << Verbose(0) << "===============================================" << endl;
390 cout << Verbose(0) << "INPUT: ";
391 cin >> choice;
392
393 switch (choice) {
394 default:
395 case 'a': // three atoms defining mirror plane
396 first = mol->AskAtom("Enter first atom: ");
397 second = mol->AskAtom("Enter second atom: ");
398 third = mol->AskAtom("Enter third atom: ");
399
400 n.MakeNormalVector((const vector *)&first->x,(const vector *)&second->x,(const vector *)&third->x);
401 break;
402 case 'b': // normal vector of mirror plane
403 cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
404 n.AskPosition(mol->cell_size,0);
405 n.Normalize();
406 break;
407 case 'c': // three atoms defining mirror plane
408 first = mol->AskAtom("Enter first atom: ");
409 second = mol->AskAtom("Enter second atom: ");
410
411 n.CopyVector((const vector *)&first->x);
412 n.SubtractVector((const vector *)&second->x);
413 n.Normalize();
414 break;
415 };
416 cout << Verbose(0) << "Normal vector: ";
417 n.Output((ofstream *)&cout);
418 cout << Verbose(0) << endl;
419 mol->Mirror((const vector *)&n);
420};
421
422/** Submenu for removing the atoms from the molecule.
423 * \param *mol the molecule with all the atoms
424 */
425void RemoveAtoms(molecule *mol)
426{
427 atom *first, *second;
428 int axis;
429 double tmp1, tmp2;
430 char choice; // menu choice char
431
432 cout << Verbose(0) << "===========REMOVE ATOMS=========================" << endl;
433 cout << Verbose(0) << " a - state atom for removal by number" << endl;
434 cout << Verbose(0) << " b - keep only in radius around atom" << endl;
435 cout << Verbose(0) << " c - remove this with one axis greater value" << endl;
436 cout << Verbose(0) << "all else - go back" << endl;
437 cout << Verbose(0) << "===============================================" << endl;
438 cout << Verbose(0) << "INPUT: ";
439 cin >> choice;
440
441 switch (choice) {
442 default:
443 case 'a':
444 if (mol->RemoveAtom(mol->AskAtom("Enter number of atom within molecule: ")))
445 cout << Verbose(1) << "Atom removed." << endl;
446 else
447 cout << Verbose(1) << "Atom not found." << endl;
448 break;
449 case 'b':
450 second = mol->AskAtom("Enter number of atom as reference point: ");
451 cout << Verbose(0) << "Enter radius: ";
452 cin >> tmp1;
453 first = mol->start;
454 while(first->next != mol->end) {
455 first = first->next;
456 if (first->x.Distance((const vector *)&second->x) > tmp1*tmp1) // distance to first above radius ...
457 mol->RemoveAtom(first);
458 }
459 break;
460 case 'c':
461 cout << Verbose(0) << "Which axis is it: ";
462 cin >> axis;
463 cout << Verbose(0) << "Left inward boundary: ";
464 cin >> tmp1;
465 cout << Verbose(0) << "Right inward boundary: ";
466 cin >> tmp2;
467 first = mol->start;
468 while(first->next != mol->end) {
469 first = first->next;
470 if ((first->x.x[axis] > tmp2) || (first->x.x[axis] < tmp1)) // out of boundary ...
471 mol->RemoveAtom(first);
472 }
473 break;
474 };
475 //mol->Output((ofstream *)&cout);
476 choice = 'r';
477};
478
479/** Submenu for measuring out the atoms in the molecule.
480 * \param *periode periodentafel
481 * \param *mol the molecule with all the atoms
482 */
483void MeasureAtoms(periodentafel *periode, molecule *mol)
484{
485 atom *first, *second, *third;
486 vector x,y;
487 double min[256], tmp1, tmp2, tmp3;
488 int Z;
489 char choice; // menu choice char
490
491 cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl;
492 cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl;
493 cout << Verbose(0) << " b - calculate bond length between two atoms" << endl;
494 cout << Verbose(0) << " c - calculate bond angle" << endl;
495 cout << Verbose(0) << "all else - go back" << endl;
496 cout << Verbose(0) << "===============================================" << endl;
497 cout << Verbose(0) << "INPUT: ";
498 cin >> choice;
499
500 switch(choice) {
501 default:
502 cout << Verbose(1) << "Not a valid choice." << endl;
503 break;
504 case 'a':
505 first = mol->AskAtom("Enter first atom: ");
506 for (int i=0;i<256;i++)
507 min[i] = 0.;
508
509 second = mol->start;
510 while ((second->next != mol->end)) {
511 second = second->next; // advance
512 Z = second->type->Z;
513 tmp1 = 0.;
514 if (first != second) {
515 x.CopyVector((const vector *)&first->x);
516 x.SubtractVector((const vector *)&second->x);
517 tmp1 = x.Norm();
518 }
519 if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1;
520 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl;
521 }
522 for (int i=0;i<256;i++)
523 if (min[i] != 0.) cout << Verbose(0) << "Minimum Bond length between " << first->type->name << " Atom " << first->nr << " and next Ion of type " << (periode->FindElement(i))->name << ": " << min[i] << " a.u." << endl;
524 break;
525
526 case 'b':
527 first = mol->AskAtom("Enter first atom: ");
528 second = mol->AskAtom("Enter second atom: ");
529 for (int i=0;i<NDIM;i++)
530 min[i] = 0.;
531 x.CopyVector((const vector *)&first->x);
532 x.SubtractVector((const vector *)&second->x);
533 tmp1 = x.Norm();
534 cout << Verbose(1) << "Distance vector is ";
535 x.Output((ofstream *)&cout);
536 cout << "." << endl << "Norm of distance is " << tmp1 << "." << endl;
537 break;
538
539 case 'c':
540 cout << Verbose(0) << "Evaluating bond angle between three - first, central, last - atoms." << endl;
541 first = mol->AskAtom("Enter first atom: ");
542 second = mol->AskAtom("Enter central atom: ");
543 third = mol->AskAtom("Enter last atom: ");
544 tmp1 = tmp2 = tmp3 = 0.;
545 x.CopyVector((const vector *)&first->x);
546 x.SubtractVector((const vector *)&second->x);
547 y.CopyVector((const vector *)&third->x);
548 y.SubtractVector((const vector *)&second->x);
549 cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": ";
550 cout << Verbose(0) << (acos(x.ScalarProduct((const vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl;
551 break;
552 }
553};
554
555/** Submenu for measuring out the atoms in the molecule.
556 * \param *mol the molecule with all the atoms
557 * \param *configuration configuration structure for the to be written config files of all fragments
558 */
559void FragmentAtoms(molecule *mol, config *configuration)
560{
561 enum BondOrderScheme Scheme = NoScheme;
562 enum CutCyclicBond CutCyclic;
563 char schema;
564 int Order1, Order2;
565 clock_t start, end;
566
567 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
568 cout << Verbose(0) << "What's the desired bond order: ";
569 cin >> Order1;
570 cout << Verbose(0) << "What's the desired bond scheme [(B)ottomUp/(T)opDown/(A)NOVA/(C)ombined]: ";
571 cin >> schema;
572 CutCyclic = SaturateBond;
573 switch (schema) {
574 default:
575 Scheme = NoScheme;
576 break;
577 case 'B':
578 CutCyclic = KeepBond;
579 case 'b':
580 Scheme = BottomUp;
581 Order2 = 0;
582 break;
583 case 'T':
584 CutCyclic = KeepBond;
585 case 't':
586 Scheme = TopDown;
587 Order2 = Order1;
588 Order1 = 0;
589 break;
590 case 'A':
591 CutCyclic = KeepBond;
592 case 'a':
593 Scheme = ANOVA;
594 Order2 = 0;
595 break;
596 case 'C':
597 CutCyclic = KeepBond;
598 case 'c':
599 cout << Verbose(0) << "Combined first selects subgraphs by BottomUp of bond order " << Order1 << " then TopDown to fragment these." << endl;
600 cout << Verbose(0) << "What's the desired bond order for TopDown: ";
601 cin >> Order2;
602 Scheme = Combined;
603 break;
604 };
605 if (mol->first->next != mol->last) { // there are bonds
606 start = clock();
607 mol->FragmentMolecule((ofstream *)&cout, Order1, Order2, Scheme, configuration, CutCyclic);
608 end = clock();
609 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
610 } else
611 cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl;
612};
613
614/********************************************** Test routine **************************************/
615
616/** Is called always as option 'T' in the menu.
617 */
618void testroutine(molecule *mol)
619{
620 // the current test routine checks the functionality of the KeySet&Graph concept:
621 // We want to have a multiindex (the KeySet) describing a unique subgraph
622 atom *Walker = mol->start;
623 int i, comp, counter=0;
624
625 // generate some KeySets
626 cout << "Generating KeySets." << endl;
627 KeySet TestSets[mol->AtomCount+1];
628 i=1;
629 while (Walker->next != mol->end) {
630 Walker = Walker->next;
631 for (int j=0;j<i;j++) {
632 TestSets[j].insert(Walker->nr);
633 }
634 i++;
635 }
636 cout << "Testing insertion of already present item in KeySets." << endl;
637 KeySetTestPair test;
638 test = TestSets[mol->AtomCount-1].insert(Walker->nr);
639 if (test.second) {
640 cout << Verbose(1) << "Insertion worked?!" << endl;
641 } else {
642 cout << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl;
643 }
644 TestSets[mol->AtomCount].insert(mol->end->previous->nr);
645 TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr);
646
647 // constructing Graph structure
648 cout << "Generating Subgraph class." << endl;
649 Graph Subgraphs;
650
651 // insert KeySets into Subgraphs
652 cout << "Inserting KeySets into Subgraph class." << endl;
653 for (int j=0;j<mol->AtomCount;j++) {
654 Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.)));
655 }
656 cout << "Testing insertion of already present item in Subgraph." << endl;
657 GraphTestPair test2;
658 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.)));
659 if (test2.second) {
660 cout << Verbose(1) << "Insertion worked?!" << endl;
661 } else {
662 cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl;
663 }
664
665 // show graphs
666 cout << "Showing Subgraph's contents, checking that it's sorted." << endl;
667 Graph::iterator A = Subgraphs.begin();
668 while (A != Subgraphs.end()) {
669 cout << (*A).second.first << ": ";
670 KeySet::iterator key = (*A).first.begin();
671 comp = -1;
672 while (key != (*A).first.end()) {
673 if ((*key) > comp)
674 cout << (*key) << " ";
675 else
676 cout << (*key) << "! ";
677 comp = (*key);
678 key++;
679 }
680 cout << endl;
681 A++;
682 }
683};
684
685/** Tries given filename or standard on saving the config file.
686 * \param *ConfigFileName name of file
687 * \param *configuration pointer to configuration structure with all the values
688 * \param *periode pointer to periodentafel structure with all the elements
689 * \param *mol pointer to molecule structure with all the atoms and coordinates
690 */
691void SaveConfig(char *ConfigFileName, config *configuration, periodentafel *periode, molecule *mol)
692{
693 char filename[255];
694 ofstream output;
695
696 cout << Verbose(0) << "Storing configuration ... " << endl;
697 // get correct valence orbitals
698 mol->CalculateOrbitals(*configuration);
699 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble;
700 if (ConfigFileName != NULL)
701 output.open(ConfigFileName, ios::trunc);
702 if (output == NULL)
703 output.open("main_pcp_linux", ios::trunc);
704 if (configuration->Save(&output, periode, mol))
705 cout << Verbose(0) << "Saving of config file successful." << endl;
706 else
707 cout << Verbose(0) << "Saving of config file failed." << endl;
708 output.close();
709 output.clear();
710 // and save to xyz file
711 if (ConfigFileName != NULL) {
712 strcpy(filename, ConfigFileName);
713 strcat(filename, ".xyz");
714 output.open(filename, ios::trunc);
715 }
716 if (output == NULL) {
717 strcpy(filename,"main_pcp_linux");
718 strcat(filename, ".xyz");
719 output.open(filename, ios::trunc);
720 }
721 if (mol->OutputXYZ(&output))
722 cout << Verbose(0) << "Saving of XYZ file successful." << endl;
723 else
724 cout << Verbose(0) << "Saving of XYZ file failed." << endl;
725 output.close();
726 output.clear();
727};
728
729/********************************************** Main routine **************************************/
730
731int main(int argc, char **argv)
732{
733 periodentafel *periode = new periodentafel; // and a period table of all elements
734 molecule *mol = new molecule(periode); // first we need an empty molecule
735 config configuration;
736 double tmp1;
737 double bond, min_bond;
738 atom *first, *second;
739 element *finder;
740 char choice; // menu choice char
741 vector x,y,z,n; // coordinates for absolute point in cell volume
742 double *factor; // unit factor if desired
743 bool valid; // flag if input was valid or not
744 ifstream test;
745 ofstream output;
746 string line;
747 char filename[255];
748 char *ConfigFileName = NULL;
749 char *ElementsFileName = NULL;
750 int flag = 1;
751 int Z;
752 int j, axis, count, faktor;
753 int MinimumRingSize = -1;
754 enum BondOrderScheme Scheme = NoScheme;
755 enum CutCyclicBond CutCyclic;
756 enum ConfigStatus config_present = absent;
757 MoleculeLeafClass *Subgraphs = NULL;
758 clock_t start,end;
759 element **Elements;
760 vector **Vectors;
761 int argptr;
762
763 // =========================== PARSE COMMAND LINE OPTIONS ====================================
764 if (argc >= 1) { // config file specified as option
765 // 1. : Parse options that just set variables or print help
766 argptr = 1;
767 do {
768 if (argv[argptr][0] == '-') {
769 cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n";
770 argptr++;
771 switch(argv[argptr-1][1]) {
772 case 'h':
773 case 'H':
774 case '?':
775 cout << "MoleCuilder suite" << endl << "==================" << endl << endl;
776 cout << "Usage: " << argv[0] << "[-{acepsthH?vfrp}] [further arguments] [config file]" << endl;
777 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl;
778 cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl;
779 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl;
780 cout << "\t-e <file>\tSets the element database to be parsed from this file (default: elements.db in same dir as " << argv[0] << ")." << endl;
781 cout << "\t-h/-H/-?\tGive this help screen." << endl;
782 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;
783 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl;
784 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl;
785 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl;
786 cout << "\t-v/-V\t\tGives version information." << endl;
787 return 0;
788 break;
789 case 'v':
790 case 'V':
791 cout << argv[0] << " " << VERSIONSTRING << endl;
792 cout << "Build your own molecule position set." << endl;
793 return 0;
794 break;
795 case 'e':
796 cout << "Using " << argv[argptr] << " as elements database." << endl;
797 ElementsFileName = argv[argptr];
798 argptr+=1;
799 break;
800 default: // no match? Step on
801 argptr++;
802 break;
803 }
804 } else
805 argptr++;
806 } while (argptr < (argc-1));
807 // 2. Parse the element database
808 if (periode->LoadPeriodentafel(ElementsFileName))
809 cout << Verbose(0) << "Element list loaded successfully." << endl;
810 else
811 cout << Verbose(0) << "Element list loading failed." << endl;
812 // 3. Find config file name and parse if possible
813 if (argv[argc-1][0] != '-') {
814 cout << Verbose(0) << "Config file given." << endl;
815 test.open(argv[argc-1], ios::in);
816 if (test == NULL) {
817 //return (1);
818 output.open(argv[argc-1], ios::out);
819 if (output == NULL) {
820 cout << Verbose(1) << "Specified config file " << argv[argc-1] << " not found." << endl;
821 config_present = absent;
822 } else {
823 cout << "Empty configuration file." << endl;
824 ConfigFileName = argv[argc-1];
825 config_present = empty;
826 output.close();
827 }
828 } else {
829 ConfigFileName = argv[argc-1];
830 cout << Verbose(1) << "Specified config file found, parsing ...";
831 switch (configuration.TestSyntax(&test, periode, mol)) {
832 case 1:
833 cout << "new syntax." << endl;
834 configuration.Load(&test, periode, mol);
835 config_present = present;
836 break;
837 case 0:
838 cout << "old syntax." << endl;
839 configuration.LoadOld(&test, periode, mol);
840 config_present = present;
841 break;
842 default:
843 cout << "Unknown syntax or empty, yet present file." << endl;
844 config_present = empty;
845 }
846 test.close();
847 }
848 } else
849 config_present = absent;
850 // 4. parse again through options, now for those depending on elements db and config presence
851 argptr = 1;
852 do {
853 if (argv[argptr][0] == '-') {
854 argptr++;
855 if ((config_present == present) || (config_present == empty)) {
856 switch(argv[argptr-1][1]) {
857 case 'p':
858 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl;
859 if (!mol->AddXYZFile(argv[argptr++]))
860 cout << Verbose(2) << "File not found." << endl;
861 else
862 cout << Verbose(2) << "File found and parsed." << endl;
863 config_present = present;
864 break;
865 default: // no match? Don't step on (this is done in next switch's default)
866 break;
867 }
868 }
869 if (config_present != empty) {
870 if (config_present == present) {
871 switch(argv[argptr-1][1]) {
872 case 't':
873 cout << Verbose(1) << "Translating all ions to new origin." << endl;
874 for (int i=0;i<3;i++)
875 x.x[i] = atof(argv[argptr+i]);
876 mol->Translate((const vector *)&x);
877 argptr+=3;
878 break;
879 case 'a':
880 cout << Verbose(1) << "Adding new atom." << endl;
881 first = new atom;
882 for (int i=0;i<3;i++)
883 first->x.x[i] = atof(argv[argptr+1+i]);
884 finder = periode->start;
885 while (finder != periode->end) {
886 finder = finder->next;
887 if (strncmp(finder->symbol,argv[argptr+1],3) == 0) {
888 first->type = finder;
889 break;
890 }
891 }
892 mol->AddAtom(first); // add to molecule
893 argptr+=4;
894 break;
895 case 's':
896 j = -1;
897 cout << Verbose(1) << "Scaling all ion positions by factor." << endl;
898 factor = (double *) Malloc(sizeof(double)*NDIM, "main: *factor");
899 factor[0] = atof(argv[argptr]);
900 if (argc > argptr+1)
901 argptr++;
902 factor[1] = atof(argv[argptr]);
903 if (argc > argptr+1)
904 argptr++;
905 factor[2] = atof(argv[argptr]);
906 mol->Scale(&factor);
907 for (int i=0;i<3;i++) {
908 j += i+1;
909 x.x[i] = atof(argv[3+i]);
910 mol->cell_size[j]*=factor[i];
911 }
912 Free((void **)&factor, "main: *factor");
913 argptr+=1;
914 break;
915 case 'c':
916 j = -1;
917 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl;
918 // make every coordinate positive
919 mol->CenterEdge((ofstream *)&cout, &x);
920 // update Box of atoms by boundary
921 mol->SetBoxDimension(&x);
922 // translate each coordinate by boundary
923 j=-1;
924 for (int i=0;i<3;i++) {
925 j += i+1;
926 x.x[i] = atof(argv[argptr++]);
927 mol->cell_size[j] += x.x[i]*2.;
928 }
929 mol->Translate((const vector *)&x);
930 break;
931 case 'r':
932 cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl;
933 break;
934 case 'f':
935 int i,j;
936 flag = 0;
937 if (argc > argptr+3) {
938 cout << Verbose(0) << "Creating connection matrix..." << endl;
939 start = clock();
940 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]));
941 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
942 cout << Verbose(0) << "What's the desired bond scheme [(B)ottomUp/(T)opDown/(A)NOVA/(C)ombined]: ";
943 CutCyclic = SaturateBond;
944 switch (argv[argptr+1][0]) {
945 default:
946 Scheme = NoScheme;
947 break;
948 case 'B':
949 CutCyclic = KeepBond;
950 case 'b':
951 Scheme = BottomUp;
952 i = atoi(argv[argptr]);
953 j = 0;
954 break;
955 case 'T':
956 CutCyclic = KeepBond;
957 case 't':
958 Scheme = TopDown;
959 i = 0;
960 j = atoi(argv[argptr]);
961 break;
962 case 'A':
963 CutCyclic = KeepBond;
964 case 'a':
965 Scheme = ANOVA;
966 i = atoi(argv[argptr]);
967 j = 0;
968 break;
969 // case 'C':
970 // CutCyclic = KeepBond;
971 // case 'c':
972 // if (argc > 5) {
973 // i = atoi(argv[4]);
974 // j = atoi(argv[6]);
975 // Scheme = Combined;
976 // }
977 // else
978 // cerr << "Missing second bond order for TopDown fragmentation in combined approach." << endl;
979 // break;
980 };
981 if (mol->first->next != mol->last) {
982 mol->FragmentMolecule((ofstream *)&cout, i, j, Scheme, &configuration, CutCyclic);
983 }
984 end = clock();
985 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
986 argptr+=2;
987 }
988 break;
989 default: // no match? Step on
990 argptr++;
991 break;
992 }
993 } else {
994 cout << "Cannot apply command line parameter as no valid config file was found." << endl;
995 return 1;
996 }
997 }
998 } else argptr++;
999 } while (argptr < (argc-1));
1000 if (flag)
1001 SaveConfig(ConfigFileName, &configuration, periode, mol);
1002 delete(mol);
1003 delete(periode);
1004 return (0);
1005 }
1006
1007
1008 // General stuff
1009 if (mol->cell_size[0] == 0.) {
1010 cout << Verbose(0) << "enter lower triadiagonal form of basis matrix" << endl << endl;
1011 for (int i=0;i<6;i++) {
1012 cout << Verbose(1) << "Cell size" << i << ": ";
1013 cin >> mol->cell_size[i];
1014 }
1015 }
1016
1017 // =========================== START INTERACTIVE SESSION ====================================
1018
1019 // now the main construction loop
1020 cout << Verbose(0) << endl << "Now comes the real construction..." << endl;
1021 do {
1022 cout << Verbose(0) << endl << endl;
1023 cout << Verbose(0) << "============Element list=======================" << endl;
1024 mol->Checkout((ofstream *)&cout);
1025 cout << Verbose(0) << "============Atom list==========================" << endl;
1026 mol->Output((ofstream *)&cout);
1027 cout << Verbose(0) << "============Menu===============================" << endl;
1028 cout << Verbose(0) << "a - add an atom" << endl;
1029 cout << Verbose(0) << "r - remove an atom" << endl;
1030 cout << Verbose(0) << "b - scale a bond between atoms" << endl;
1031 cout << Verbose(0) << "u - change an atoms element" << endl;
1032 cout << Verbose(0) << "l - measure lengths, angles, ... for an atom" << endl;
1033 cout << Verbose(0) << "-----------------------------------------------" << endl;
1034 cout << Verbose(0) << "p - Parse xyz file" << endl;
1035 cout << Verbose(0) << "e - edit the current configuration" << endl;
1036 cout << Verbose(0) << "o - create connection matrix" << endl;
1037 cout << Verbose(0) << "f - fragment molecule many-body bond order style" << endl;
1038 cout << Verbose(0) << "-----------------------------------------------" << endl;
1039 cout << Verbose(0) << "d - duplicate molecule/periodic cell" << endl;
1040 cout << Verbose(0) << "i - realign molecule" << endl;
1041 cout << Verbose(0) << "m - mirror all molecules" << endl;
1042 cout << Verbose(0) << "t - translate molecule by vector" << endl;
1043 cout << Verbose(0) << "c - scale by unit transformation" << endl;
1044 cout << Verbose(0) << "g - center atoms in box" << endl;
1045 cout << Verbose(0) << "-----------------------------------------------" << endl;
1046 cout << Verbose(0) << "s - save current setup to config file" << endl;
1047 cout << Verbose(0) << "T - call the current test routine" << endl;
1048 cout << Verbose(0) << "q - quit" << endl;
1049 cout << Verbose(0) << "===============================================" << endl;
1050 cout << Verbose(0) << "Input: ";
1051 cin >> choice;
1052
1053 switch (choice) {
1054 default:
1055 case 'q': // quit
1056 break;
1057
1058 case 'a': // add atom
1059 AddAtoms(periode, mol);
1060 choice = 'a';
1061 break;
1062
1063 case 'd': // duplicate the periodic cell along a given axis, given times
1064 cout << Verbose(0) << "State the axis [(+-)123]: ";
1065 cin >> axis;
1066 cout << Verbose(0) << "State the factor: ";
1067 cin >> faktor;
1068
1069 mol->CountAtoms((ofstream *)&cout); // recount atoms
1070 if (mol->AtomCount != 0) { // if there is more than none
1071 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand
1072 Elements = (element **) Malloc(sizeof(element *)*count, "main: duplicateCell - **Elements");
1073 Vectors = (vector **) Malloc(sizeof(vector *)*count, "main: duplicateCell - **Vectors");
1074 j = 0;
1075 first = mol->start;
1076 while (first->next != mol->end) { // make a list of all atoms with coordinates and element
1077 first = first->next;
1078 Elements[j] = first->type;
1079 Vectors[j] = &first->x;
1080 j++;
1081 }
1082 if (count != j)
1083 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;
1084 x.Zero();
1085 y.Zero();
1086 y.x[abs(axis)-1] = mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] * abs(axis)/axis; // last term is for sign, first is for magnitude
1087 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times
1088 x.AddVector(&y); // per factor one cell width further
1089 for (int k=0;k<count;k++) { // go through every atom of the original cell
1090 first = new atom(); // create a new body
1091 first->x.CopyVector(Vectors[k]); // use coordinate of original atom
1092 first->x.AddVector(&x); // translate the coordinates
1093 first->type = Elements[k]; // insert original element
1094 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)
1095 }
1096 }
1097 if (mol->first->next != mol->last) // if connect matrix is present already, redo it
1098 mol->CreateAdjacencyList((ofstream *)&cout, mol->BondDistance);
1099 // free memory
1100 Free((void **)&Elements, "main: duplicateCell - **Elements");
1101 Free((void **)&Vectors, "main: duplicateCell - **Vectors");
1102 // correct cell size
1103 if (axis < 0) { // if sign was negative, we have to translate everything
1104 x.Zero();
1105 x.AddVector(&y);
1106 x.Scale(-(faktor-1));
1107 mol->Translate(&x);
1108 }
1109 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;
1110 }
1111 break;
1112
1113 case 'g': // center the atoms
1114 CenterAtoms(mol);
1115 break;
1116
1117 case 'b': // scale a bond
1118 cout << Verbose(0) << "Scaling bond length between two atoms." << endl;
1119 first = mol->AskAtom("Enter first (fixed) atom: ");
1120 second = mol->AskAtom("Enter second (shifting) atom: ");
1121 min_bond = 0.;
1122 for (int i=0;i<3;i++)
1123 min_bond += (first->x.x[i]-second->x.x[i])*(first->x.x[i] - second->x.x[i]);
1124 min_bond = sqrt(min_bond);
1125 cout << Verbose(0) << "Current Bond length between " << first->type->name << " Atom " << first->nr << " and " << second->type->name << " Atom " << second->nr << ": " << min_bond << " a.u." << endl;
1126 cout << Verbose(0) << "Enter new bond length [a.u.]: ";
1127 cin >> bond;
1128 for (int i=0;i<3;i++) {
1129 second->x.x[i] -= (second->x.x[i]-first->x.x[i])/min_bond*(min_bond-bond);
1130 }
1131 //cout << Verbose(0) << "New coordinates of Atom " << second->nr << " are: ";
1132 //second->Output(second->type->No, 1, (ofstream *)&cout);
1133 break;
1134
1135 case 'i': // align all atoms
1136 AlignAtoms(periode, mol);
1137 break;
1138
1139 case 'm': // mirror atoms along a given axis
1140 MirrorAtoms(mol);
1141 break;
1142
1143 case 't': // translate all atoms
1144 cout << Verbose(0) << "Enter translation vector." << endl;
1145 x.AskPosition(mol->cell_size,0);
1146 mol->Translate((const vector *)&x);
1147 break;
1148
1149 case 'e': // edit each field of the configuration
1150 configuration.Edit(mol);
1151 break;
1152
1153 case 'c': // unit scaling of the metric
1154 cout << Verbose(0) << "Enter three factors: ";
1155 factor = (double *) Malloc(sizeof(double)*NDIM, "main: *factor");
1156 cin >> factor[0];
1157 cin >> factor[1];
1158 cin >> factor[2];
1159 valid = true;
1160 mol->Scale(&factor);
1161 Free((void **)&factor, "main: *factor");
1162 break;
1163
1164 case 'r': // remove atom
1165 RemoveAtoms(mol);
1166 break;
1167
1168 case 'l': // measure distances or angles
1169 MeasureAtoms(periode, mol);
1170 break;
1171
1172 case 'p': // parse and XYZ file
1173 cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
1174 do {
1175 cout << Verbose(0) << "Enter file name: ";
1176 cin >> filename;
1177 } while (!mol->AddXYZFile(filename));
1178 break;
1179
1180 case 'o': // create the connection matrix
1181 cout << Verbose(0) << "What's the maximum bond distance: ";
1182 cin >> tmp1;
1183 start = clock();
1184 mol->CreateAdjacencyList((ofstream *)&cout, tmp1);
1185 //mol->CreateListOfBondsPerAtom((ofstream *)&cout);
1186 Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, false, MinimumRingSize);
1187 while (Subgraphs->next != NULL) {
1188 Subgraphs = Subgraphs->next;
1189 delete(Subgraphs->previous);
1190 }
1191 delete(Subgraphs); // we don't need the list here, so free everything
1192 Subgraphs = NULL;
1193 end = clock();
1194 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
1195 break;
1196
1197 case 'f':
1198 FragmentAtoms(mol, &configuration);
1199 break;
1200
1201 case 'u': // change an atom's element
1202 first = NULL;
1203 do {
1204 cout << Verbose(0) << "Change the element of which atom: ";
1205 cin >> Z;
1206 } while ((first = mol->FindAtom(Z)) == NULL);
1207 cout << Verbose(0) << "New element by atomic number Z: ";
1208 cin >> Z;
1209 first->type = periode->FindElement(Z);
1210 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl;
1211 break;
1212
1213 case 'T':
1214 testroutine(mol);
1215 break;
1216
1217 case 's': // save to config file
1218 SaveConfig(ConfigFileName, &configuration, periode, mol);
1219 break;
1220 };
1221 } while (choice != 'q');
1222
1223 // save element data base
1224 if (periode->StorePeriodentafel()) //ElementsFileName
1225 cout << Verbose(0) << "Saving of elements.db successful." << endl;
1226 else
1227 cout << Verbose(0) << "Saving of elements.db failed." << endl;
1228
1229 // Free all
1230 if (Subgraphs != NULL) { // free disconnected subgraph list of DFS analysis was performed
1231 while (Subgraphs->next != NULL) {
1232 Subgraphs = Subgraphs->next;
1233 delete(Subgraphs->previous);
1234 }
1235 delete(Subgraphs);
1236 }
1237 delete(mol);
1238 delete(periode);
1239 return (0);
1240}
1241
1242/********************************************** E N D **************************************************/
Note: See TracBrowser for help on using the repository browser.