source: src/builder.cpp@ a251a3

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

molecule::CreateAdjacencyList() now needs IsAngstroem as parameter

This is necessary, as the database values (covalent radii et al) are in Angstroem, hence don't match if we use Bohrradii as length unit instead. CreateAdjacencyList() converts units and now finds correct bond structure and fragments properly.

  • Property mode set to 100644
File size: 48.2 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 */
61static void 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=NDIM;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=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 */
258static void CenterAtoms(molecule *mol)
259{
260 vector x, y;
261 char choice; // menu choice char
262
263 cout << Verbose(0) << "===========CENTER ATOMS=========================" << endl;
264 cout << Verbose(0) << " a - on origin" << endl;
265 cout << Verbose(0) << " b - on center of gravity" << endl;
266 cout << Verbose(0) << " c - within box with additional boundary" << endl;
267 cout << Verbose(0) << " d - within given simulation box" << endl;
268 cout << Verbose(0) << "all else - go back" << endl;
269 cout << Verbose(0) << "===============================================" << endl;
270 cout << Verbose(0) << "INPUT: ";
271 cin >> choice;
272
273 switch (choice) {
274 default:
275 cout << Verbose(0) << "Not a valid choice." << endl;
276 break;
277 case 'a':
278 cout << Verbose(0) << "Centering atoms in config file on origin." << endl;
279 mol->CenterOrigin((ofstream *)&cout, &x);
280 break;
281 case 'b':
282 cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl;
283 mol->CenterGravity((ofstream *)&cout, &x);
284 break;
285 case 'c':
286 cout << Verbose(0) << "Centering atoms in config file within given additional boundary." << endl;
287 for (int i=0;i<NDIM;i++) {
288 cout << Verbose(0) << "Enter axis " << i << " boundary: ";
289 cin >> y.x[i];
290 }
291 mol->CenterEdge((ofstream *)&cout, &x); // make every coordinate positive
292 mol->Translate(&y); // translate by boundary
293 mol->SetBoxDimension(&(x+y*2)); // update Box of atoms by boundary
294 break;
295 case 'd':
296 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
297 for (int i=0;i<NDIM;i++) {
298 cout << Verbose(0) << "Enter axis " << i << " boundary: ";
299 cin >> x.x[i];
300 }
301 // center
302 mol->CenterInBox((ofstream *)&cout, &x);
303 // update Box of atoms by boundary
304 mol->SetBoxDimension(&x);
305 break;
306 }
307};
308
309/** Submenu for aligning the atoms in the molecule.
310 * \param *periode periodentafel
311 * \param *mol the molecule with all the atoms
312 */
313static void AlignAtoms(periodentafel *periode, molecule *mol)
314{
315 atom *first, *second, *third;
316 vector x,n;
317 char choice; // menu choice char
318
319 cout << Verbose(0) << "===========ALIGN ATOMS=========================" << endl;
320 cout << Verbose(0) << " a - state three atoms defining align plane" << endl;
321 cout << Verbose(0) << " b - state alignment vector" << endl;
322 cout << Verbose(0) << " c - state two atoms in alignment direction" << endl;
323 cout << Verbose(0) << " d - align automatically by least square fit" << endl;
324 cout << Verbose(0) << "all else - go back" << endl;
325 cout << Verbose(0) << "===============================================" << endl;
326 cout << Verbose(0) << "INPUT: ";
327 cin >> choice;
328
329 switch (choice) {
330 default:
331 case 'a': // three atoms defining mirror plane
332 first = mol->AskAtom("Enter first atom: ");
333 second = mol->AskAtom("Enter second atom: ");
334 third = mol->AskAtom("Enter third atom: ");
335
336 n.MakeNormalVector((const vector *)&first->x,(const vector *)&second->x,(const vector *)&third->x);
337 break;
338 case 'b': // normal vector of mirror plane
339 cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
340 n.AskPosition(mol->cell_size,0);
341 n.Normalize();
342 break;
343 case 'c': // three atoms defining mirror plane
344 first = mol->AskAtom("Enter first atom: ");
345 second = mol->AskAtom("Enter second atom: ");
346
347 n.CopyVector((const vector *)&first->x);
348 n.SubtractVector((const vector *)&second->x);
349 n.Normalize();
350 break;
351 case 'd':
352 char shorthand[4];
353 vector a;
354 struct lsq_params param;
355 do {
356 fprintf(stdout, "Enter the element of atoms to be chosen: ");
357 fscanf(stdin, "%3s", shorthand);
358 } while ((param.type = periode->FindElement(shorthand)) == NULL);
359 cout << Verbose(0) << "Element is " << param.type->name << endl;
360 mol->GetAlignVector(&param);
361 for (int i=NDIM;i--;) {
362 x.x[i] = gsl_vector_get(param.x,i);
363 n.x[i] = gsl_vector_get(param.x,i+NDIM);
364 }
365 gsl_vector_free(param.x);
366 cout << Verbose(0) << "Offset vector: ";
367 x.Output((ofstream *)&cout);
368 cout << Verbose(0) << endl;
369 n.Normalize();
370 break;
371 };
372 cout << Verbose(0) << "Alignment vector: ";
373 n.Output((ofstream *)&cout);
374 cout << Verbose(0) << endl;
375 mol->Align(&n);
376};
377
378/** Submenu for mirroring the atoms in the molecule.
379 * \param *mol the molecule with all the atoms
380 */
381static void MirrorAtoms(molecule *mol)
382{
383 atom *first, *second, *third;
384 vector n;
385 char choice; // menu choice char
386
387 cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl;
388 cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl;
389 cout << Verbose(0) << " b - state normal vector of mirror plane" << endl;
390 cout << Verbose(0) << " c - state two atoms in normal direction" << endl;
391 cout << Verbose(0) << "all else - go back" << endl;
392 cout << Verbose(0) << "===============================================" << endl;
393 cout << Verbose(0) << "INPUT: ";
394 cin >> choice;
395
396 switch (choice) {
397 default:
398 case 'a': // three atoms defining mirror plane
399 first = mol->AskAtom("Enter first atom: ");
400 second = mol->AskAtom("Enter second atom: ");
401 third = mol->AskAtom("Enter third atom: ");
402
403 n.MakeNormalVector((const vector *)&first->x,(const vector *)&second->x,(const vector *)&third->x);
404 break;
405 case 'b': // normal vector of mirror plane
406 cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
407 n.AskPosition(mol->cell_size,0);
408 n.Normalize();
409 break;
410 case 'c': // three atoms defining mirror plane
411 first = mol->AskAtom("Enter first atom: ");
412 second = mol->AskAtom("Enter second atom: ");
413
414 n.CopyVector((const vector *)&first->x);
415 n.SubtractVector((const vector *)&second->x);
416 n.Normalize();
417 break;
418 };
419 cout << Verbose(0) << "Normal vector: ";
420 n.Output((ofstream *)&cout);
421 cout << Verbose(0) << endl;
422 mol->Mirror((const vector *)&n);
423};
424
425/** Submenu for removing the atoms from the molecule.
426 * \param *mol the molecule with all the atoms
427 */
428static void RemoveAtoms(molecule *mol)
429{
430 atom *first, *second;
431 int axis;
432 double tmp1, tmp2;
433 char choice; // menu choice char
434
435 cout << Verbose(0) << "===========REMOVE ATOMS=========================" << endl;
436 cout << Verbose(0) << " a - state atom for removal by number" << endl;
437 cout << Verbose(0) << " b - keep only in radius around atom" << endl;
438 cout << Verbose(0) << " c - remove this with one axis greater value" << endl;
439 cout << Verbose(0) << "all else - go back" << endl;
440 cout << Verbose(0) << "===============================================" << endl;
441 cout << Verbose(0) << "INPUT: ";
442 cin >> choice;
443
444 switch (choice) {
445 default:
446 case 'a':
447 if (mol->RemoveAtom(mol->AskAtom("Enter number of atom within molecule: ")))
448 cout << Verbose(1) << "Atom removed." << endl;
449 else
450 cout << Verbose(1) << "Atom not found." << endl;
451 break;
452 case 'b':
453 second = mol->AskAtom("Enter number of atom as reference point: ");
454 cout << Verbose(0) << "Enter radius: ";
455 cin >> tmp1;
456 first = mol->start;
457 while(first->next != mol->end) {
458 first = first->next;
459 if (first->x.Distance((const vector *)&second->x) > tmp1*tmp1) // distance to first above radius ...
460 mol->RemoveAtom(first);
461 }
462 break;
463 case 'c':
464 cout << Verbose(0) << "Which axis is it: ";
465 cin >> axis;
466 cout << Verbose(0) << "Left inward boundary: ";
467 cin >> tmp1;
468 cout << Verbose(0) << "Right inward boundary: ";
469 cin >> tmp2;
470 first = mol->start;
471 while(first->next != mol->end) {
472 first = first->next;
473 if ((first->x.x[axis] > tmp2) || (first->x.x[axis] < tmp1)) // out of boundary ...
474 mol->RemoveAtom(first);
475 }
476 break;
477 };
478 //mol->Output((ofstream *)&cout);
479 choice = 'r';
480};
481
482/** Submenu for measuring out the atoms in the molecule.
483 * \param *periode periodentafel
484 * \param *mol the molecule with all the atoms
485 */
486static void MeasureAtoms(periodentafel *periode, molecule *mol)
487{
488 atom *first, *second, *third;
489 vector x,y;
490 double min[256], tmp1, tmp2, tmp3;
491 int Z;
492 char choice; // menu choice char
493
494 cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl;
495 cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl;
496 cout << Verbose(0) << " b - calculate bond length between two atoms" << endl;
497 cout << Verbose(0) << " c - calculate bond angle" << endl;
498 cout << Verbose(0) << "all else - go back" << endl;
499 cout << Verbose(0) << "===============================================" << endl;
500 cout << Verbose(0) << "INPUT: ";
501 cin >> choice;
502
503 switch(choice) {
504 default:
505 cout << Verbose(1) << "Not a valid choice." << endl;
506 break;
507 case 'a':
508 first = mol->AskAtom("Enter first atom: ");
509 for (int i=MAX_ELEMENTS;i--;)
510 min[i] = 0.;
511
512 second = mol->start;
513 while ((second->next != mol->end)) {
514 second = second->next; // advance
515 Z = second->type->Z;
516 tmp1 = 0.;
517 if (first != second) {
518 x.CopyVector((const vector *)&first->x);
519 x.SubtractVector((const vector *)&second->x);
520 tmp1 = x.Norm();
521 }
522 if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1;
523 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl;
524 }
525 for (int i=MAX_ELEMENTS;i--;)
526 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;
527 break;
528
529 case 'b':
530 first = mol->AskAtom("Enter first atom: ");
531 second = mol->AskAtom("Enter second atom: ");
532 for (int i=NDIM;i--;)
533 min[i] = 0.;
534 x.CopyVector((const vector *)&first->x);
535 x.SubtractVector((const vector *)&second->x);
536 tmp1 = x.Norm();
537 cout << Verbose(1) << "Distance vector is ";
538 x.Output((ofstream *)&cout);
539 cout << "." << endl << "Norm of distance is " << tmp1 << "." << endl;
540 break;
541
542 case 'c':
543 cout << Verbose(0) << "Evaluating bond angle between three - first, central, last - atoms." << endl;
544 first = mol->AskAtom("Enter first atom: ");
545 second = mol->AskAtom("Enter central atom: ");
546 third = mol->AskAtom("Enter last atom: ");
547 tmp1 = tmp2 = tmp3 = 0.;
548 x.CopyVector((const vector *)&first->x);
549 x.SubtractVector((const vector *)&second->x);
550 y.CopyVector((const vector *)&third->x);
551 y.SubtractVector((const vector *)&second->x);
552 cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": ";
553 cout << Verbose(0) << (acos(x.ScalarProduct((const vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl;
554 break;
555 }
556};
557
558/** Submenu for measuring out the atoms in the molecule.
559 * \param *mol the molecule with all the atoms
560 * \param *configuration configuration structure for the to be written config files of all fragments
561 */
562static void FragmentAtoms(molecule *mol, config *configuration)
563{
564 int Order1;
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 if (mol->first->next != mol->last) { // there are bonds
571 start = clock();
572 mol->FragmentMolecule((ofstream *)&cout, Order1, configuration);
573 end = clock();
574 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
575 } else
576 cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl;
577};
578
579/********************************************** Test routine **************************************/
580
581/** Is called always as option 'T' in the menu.
582 */
583static void testroutine(molecule *mol)
584{
585 // the current test routine checks the functionality of the KeySet&Graph concept:
586 // We want to have a multiindex (the KeySet) describing a unique subgraph
587 atom *Walker = mol->start;
588 int i, comp, counter=0;
589
590 // generate some KeySets
591 cout << "Generating KeySets." << endl;
592 KeySet TestSets[mol->AtomCount+1];
593 i=1;
594 while (Walker->next != mol->end) {
595 Walker = Walker->next;
596 for (int j=0;j<i;j++) {
597 TestSets[j].insert(Walker->nr);
598 }
599 i++;
600 }
601 cout << "Testing insertion of already present item in KeySets." << endl;
602 KeySetTestPair test;
603 test = TestSets[mol->AtomCount-1].insert(Walker->nr);
604 if (test.second) {
605 cout << Verbose(1) << "Insertion worked?!" << endl;
606 } else {
607 cout << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl;
608 }
609 TestSets[mol->AtomCount].insert(mol->end->previous->nr);
610 TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr);
611
612 // constructing Graph structure
613 cout << "Generating Subgraph class." << endl;
614 Graph Subgraphs;
615
616 // insert KeySets into Subgraphs
617 cout << "Inserting KeySets into Subgraph class." << endl;
618 for (int j=0;j<mol->AtomCount;j++) {
619 Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.)));
620 }
621 cout << "Testing insertion of already present item in Subgraph." << endl;
622 GraphTestPair test2;
623 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.)));
624 if (test2.second) {
625 cout << Verbose(1) << "Insertion worked?!" << endl;
626 } else {
627 cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl;
628 }
629
630 // show graphs
631 cout << "Showing Subgraph's contents, checking that it's sorted." << endl;
632 Graph::iterator A = Subgraphs.begin();
633 while (A != Subgraphs.end()) {
634 cout << (*A).second.first << ": ";
635 KeySet::iterator key = (*A).first.begin();
636 comp = -1;
637 while (key != (*A).first.end()) {
638 if ((*key) > comp)
639 cout << (*key) << " ";
640 else
641 cout << (*key) << "! ";
642 comp = (*key);
643 key++;
644 }
645 cout << endl;
646 A++;
647 }
648};
649
650/** Tries given filename or standard on saving the config file.
651 * \param *ConfigFileName name of file
652 * \param *configuration pointer to configuration structure with all the values
653 * \param *periode pointer to periodentafel structure with all the elements
654 * \param *mol pointer to molecule structure with all the atoms and coordinates
655 */
656static void SaveConfig(char *ConfigFileName, config *configuration, periodentafel *periode, molecule *mol)
657{
658 char filename[MAXSTRINGSIZE];
659 ofstream output;
660
661 cout << Verbose(0) << "Storing configuration ... " << endl;
662 // get correct valence orbitals
663 mol->CalculateOrbitals(*configuration);
664 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble;
665 if (ConfigFileName != NULL) {
666 output.open(ConfigFileName, ios::trunc);
667 } else if (strlen(configuration->configname) != 0) {
668 output.open(configuration->configname, ios::trunc);
669 } else {
670 output.open(DEFAULTCONFIG, ios::trunc);
671 }
672 if (configuration->Save(&output, periode, mol))
673 cout << Verbose(0) << "Saving of config file successful." << endl;
674 else
675 cout << Verbose(0) << "Saving of config file failed." << endl;
676 output.close();
677 output.clear();
678 // and save to xyz file
679 if (ConfigFileName != NULL) {
680 strcpy(filename, ConfigFileName);
681 strcat(filename, ".xyz");
682 output.open(filename, ios::trunc);
683 }
684 if (output == NULL) {
685 strcpy(filename,"main_pcp_linux");
686 strcat(filename, ".xyz");
687 output.open(filename, ios::trunc);
688 }
689 if (mol->OutputXYZ(&output))
690 cout << Verbose(0) << "Saving of XYZ file successful." << endl;
691 else
692 cout << Verbose(0) << "Saving of XYZ file failed." << endl;
693 output.close();
694 output.clear();
695
696 if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) {
697 cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl;
698 }
699};
700
701/** Parses the command line options.
702 * \param argc argument count
703 * \param **argv arguments array
704 * \param *mol molecule structure
705 * \param *periode elements structure
706 * \param configuration config file structure
707 * \param *ConfigFileName pointer to config file name in **argv
708 * \param *ElementsFileName pointer to elements db file name in **argv
709 * \return exit code (0 - successful, all else - something's wrong)
710 */
711static int ParseCommandLineOptions(int argc, char **argv, molecule *&mol, periodentafel *&periode, config& configuration, char *&ConfigFileName, char *&ElementsFileName)
712{
713 element *finder;
714 vector x,y,z,n; // coordinates for absolute point in cell volume
715 double *factor; // unit factor if desired
716 ifstream test;
717 ofstream output;
718 string line;
719 atom *first;
720 int ExitFlag = 0;
721 int j;
722 enum ConfigStatus config_present = absent;
723 clock_t start,end;
724 int argptr;
725
726 if (argc > 1) { // config file specified as option
727 // 1. : Parse options that just set variables or print help
728 argptr = 1;
729 do {
730 if (argv[argptr][0] == '-') {
731 cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n";
732 argptr++;
733 switch(argv[argptr-1][1]) {
734 case 'h':
735 case 'H':
736 case '?':
737 cout << "MoleCuilder suite" << endl << "==================" << endl << endl;
738 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl;
739 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl;
740 cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl;
741 cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl;
742 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl;
743 cout << "\t-e <file>\tSets the element database to be parsed from this file (default: elements.db in same dir as " << argv[0] << ")." << endl;
744 cout << "\t-f <dist> <order>\tFragments the molecule in BOSSANOVA manner and stores config files in same dir as config." << endl;
745 cout << "\t-h/-H/-?\tGive this help screen." << endl;
746 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;
747 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl;
748 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl;
749 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl;
750 cout << "\t-v/-V\t\tGives version information." << endl;
751 cout << "Note: config files must not begin with '-' !" << endl;
752 delete(mol);
753 delete(periode);
754 return (1);
755 break;
756 case 'v':
757 case 'V':
758 cout << argv[0] << " " << VERSIONSTRING << endl;
759 cout << "Build your own molecule position set." << endl;
760 delete(mol);
761 delete(periode);
762 return (1);
763 break;
764 case 'e':
765 cout << "Using " << argv[argptr] << " as elements database." << endl;
766 ElementsFileName = argv[argptr];
767 argptr+=1;
768 break;
769 default: // no match? Step on
770 argptr++;
771 break;
772 }
773 } else
774 argptr++;
775 } while (argptr < argc);
776
777 // 2. Parse the element database
778 if (periode->LoadPeriodentafel(ElementsFileName))
779 cout << Verbose(0) << "Element list loaded successfully." << endl;
780 else
781 cout << Verbose(0) << "Element list loading failed." << endl;
782
783 // 3. Find config file name and parse if possible
784 if (argv[1][0] != '-') {
785 cout << Verbose(0) << "Config file given." << endl;
786 test.open(argv[1], ios::in);
787 if (test == NULL) {
788 //return (1);
789 output.open(argv[1], ios::out);
790 if (output == NULL) {
791 cout << Verbose(1) << "Specified config file " << argv[1] << " not found." << endl;
792 config_present = absent;
793 } else {
794 cout << "Empty configuration file." << endl;
795 ConfigFileName = argv[1];
796 config_present = empty;
797 output.close();
798 }
799 } else {
800 test.close();
801 ConfigFileName = argv[1];
802 cout << Verbose(1) << "Specified config file found, parsing ...";
803 switch (configuration.TestSyntax(ConfigFileName, periode, mol)) {
804 case 1:
805 cout << "new syntax." << endl;
806 configuration.Load(ConfigFileName, periode, mol);
807 config_present = present;
808 break;
809 case 0:
810 cout << "old syntax." << endl;
811 configuration.LoadOld(ConfigFileName, periode, mol);
812 config_present = present;
813 break;
814 default:
815 cout << "Unknown syntax or empty, yet present file." << endl;
816 config_present = empty;
817 }
818 }
819 } else
820 config_present = absent;
821
822 // 4. parse again through options, now for those depending on elements db and config presence
823 argptr = 1;
824 do {
825 cout << "Current Command line argument: " << argv[argptr] << "." << endl;
826 if (argv[argptr][0] == '-') {
827 argptr++;
828 if ((config_present == present) || (config_present == empty)) {
829 switch(argv[argptr-1][1]) {
830 case 'p':
831 ExitFlag = 1;
832 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl;
833 if (!mol->AddXYZFile(argv[argptr]))
834 cout << Verbose(2) << "File not found." << endl;
835 else
836 cout << Verbose(2) << "File found and parsed." << endl;
837 config_present = present;
838 break;
839 default: // no match? Don't step on (this is done in next switch's default)
840 break;
841 }
842 }
843 if (config_present == present) {
844 switch(argv[argptr-1][1]) {
845 case 't':
846 ExitFlag = 1;
847 cout << Verbose(1) << "Translating all ions to new origin." << endl;
848 for (int i=NDIM;i--;)
849 x.x[i] = atof(argv[argptr+i]);
850 mol->Translate((const vector *)&x);
851 argptr+=3;
852 break;
853 case 'a':
854 ExitFlag = 1;
855 cout << Verbose(1) << "Adding new atom." << endl;
856 first = new atom;
857 for (int i=NDIM;i--;)
858 first->x.x[i] = atof(argv[argptr+1+i]);
859 finder = periode->start;
860 while (finder != periode->end) {
861 finder = finder->next;
862 if (strncmp(finder->symbol,argv[argptr+1],3) == 0) {
863 first->type = finder;
864 break;
865 }
866 }
867 mol->AddAtom(first); // add to molecule
868 argptr+=4;
869 break;
870 case 's':
871 ExitFlag = 1;
872 j = -1;
873 cout << Verbose(1) << "Scaling all ion positions by factor." << endl;
874 factor = new double[NDIM];
875 factor[0] = atof(argv[argptr]);
876 if (argc > argptr+1)
877 argptr++;
878 factor[1] = atof(argv[argptr]);
879 if (argc > argptr+1)
880 argptr++;
881 factor[2] = atof(argv[argptr]);
882 mol->Scale(&factor);
883 for (int i=0;i<NDIM;i++) {
884 j += i+1;
885 x.x[i] = atof(argv[NDIM+i]);
886 mol->cell_size[j]*=factor[i];
887 }
888 delete[](factor);
889 argptr+=1;
890 break;
891 case 'b':
892 ExitFlag = 1;
893 j = -1;
894 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
895 j=-1;
896 for (int i=0;i<NDIM;i++) {
897 j += i+1;
898 x.x[i] = atof(argv[argptr++]);
899 mol->cell_size[j] += x.x[i]*2.;
900 }
901 // center
902 mol->CenterInBox((ofstream *)&cout, &x);
903 // update Box of atoms by boundary
904 mol->SetBoxDimension(&x);
905 break;
906 case 'c':
907 ExitFlag = 1;
908 j = -1;
909 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl;
910 // make every coordinate positive
911 mol->CenterEdge((ofstream *)&cout, &x);
912 // update Box of atoms by boundary
913 mol->SetBoxDimension(&x);
914 // translate each coordinate by boundary
915 j=-1;
916 for (int i=0;i<NDIM;i++) {
917 j += i+1;
918 x.x[i] = atof(argv[argptr++]);
919 mol->cell_size[j] += x.x[i]*2.;
920 }
921 mol->Translate((const vector *)&x);
922 break;
923 case 'r':
924 ExitFlag = 1;
925 cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl;
926 break;
927 case 'f':
928 if (ExitFlag ==0) ExitFlag = 2; // only set if not already by other command line switch
929 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl;
930 if (argc >= argptr+2) {
931 cout << Verbose(0) << "Creating connection matrix..." << endl;
932 start = clock();
933 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]), configuration.GetIsAngstroem());
934 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
935 if (mol->first->next != mol->last) {
936 mol->FragmentMolecule((ofstream *)&cout, atoi(argv[argptr]), &configuration);
937 }
938 end = clock();
939 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
940 argptr+=1;
941 } else {
942 cerr << "Not enough arguments for fragmentation: -f <max. bond distance> <bond order>" << endl;
943 }
944 break;
945 default: // no match? Step on
946 argptr++;
947 break;
948 }
949 }
950 } else argptr++;
951 } while (argptr < argc);
952 if (ExitFlag == 1) // 1 means save and exit
953 SaveConfig(ConfigFileName, &configuration, periode, mol);
954 if (ExitFlag >= 1) { // 2 means just exit
955 delete(mol);
956 delete(periode);
957 return (0);
958 }
959 } else { // no arguments, hence scan the elements db
960 if (periode->LoadPeriodentafel(ElementsFileName))
961 cout << Verbose(0) << "Element list loaded successfully." << endl;
962 else
963 cout << Verbose(0) << "Element list loading failed." << endl;
964 configuration.RetrieveConfigPathAndName("main_pcp_linux");
965 }
966 return(0);
967};
968
969/********************************************** Main routine **************************************/
970
971int main(int argc, char **argv)
972{
973 periodentafel *periode = new periodentafel; // and a period table of all elements
974 molecule *mol = new molecule(periode); // first we need an empty molecule
975 config configuration;
976 double tmp1;
977 double bond, min_bond;
978 atom *first, *second;
979 char choice; // menu choice char
980 vector x,y,z,n; // coordinates for absolute point in cell volume
981 double *factor; // unit factor if desired
982 bool valid; // flag if input was valid or not
983 ifstream test;
984 ofstream output;
985 string line;
986 char filename[MAXSTRINGSIZE];
987 char *ConfigFileName = NULL;
988 char *ElementsFileName = NULL;
989 int Z;
990 int j, axis, count, faktor;
991 int *MinimumRingSize = NULL;
992 MoleculeLeafClass *Subgraphs = NULL;
993 clock_t start,end;
994 element **Elements;
995 vector **Vectors;
996
997 // =========================== PARSE COMMAND LINE OPTIONS ====================================
998 j = ParseCommandLineOptions(argc, argv, mol, periode, configuration, ConfigFileName, ElementsFileName);
999 if (j) return j; // something went wrong
1000
1001 // General stuff
1002 if (mol->cell_size[0] == 0.) {
1003 cout << Verbose(0) << "enter lower triadiagonal form of basis matrix" << endl << endl;
1004 for (int i=0;i<6;i++) {
1005 cout << Verbose(1) << "Cell size" << i << ": ";
1006 cin >> mol->cell_size[i];
1007 }
1008 }
1009
1010 // =========================== START INTERACTIVE SESSION ====================================
1011
1012 // now the main construction loop
1013 cout << Verbose(0) << endl << "Now comes the real construction..." << endl;
1014 do {
1015 cout << Verbose(0) << endl << endl;
1016 cout << Verbose(0) << "============Element list=======================" << endl;
1017 mol->Checkout((ofstream *)&cout);
1018 cout << Verbose(0) << "============Atom list==========================" << endl;
1019 mol->Output((ofstream *)&cout);
1020 cout << Verbose(0) << "============Menu===============================" << endl;
1021 cout << Verbose(0) << "a - add an atom" << endl;
1022 cout << Verbose(0) << "r - remove an atom" << endl;
1023 cout << Verbose(0) << "b - scale a bond between atoms" << endl;
1024 cout << Verbose(0) << "u - change an atoms element" << endl;
1025 cout << Verbose(0) << "l - measure lengths, angles, ... for an atom" << endl;
1026 cout << Verbose(0) << "-----------------------------------------------" << endl;
1027 cout << Verbose(0) << "p - Parse xyz file" << endl;
1028 cout << Verbose(0) << "e - edit the current configuration" << endl;
1029 cout << Verbose(0) << "o - create connection matrix" << endl;
1030 cout << Verbose(0) << "f - fragment molecule many-body bond order style" << endl;
1031 cout << Verbose(0) << "-----------------------------------------------" << endl;
1032 cout << Verbose(0) << "d - duplicate molecule/periodic cell" << endl;
1033 cout << Verbose(0) << "i - realign molecule" << endl;
1034 cout << Verbose(0) << "m - mirror all molecules" << endl;
1035 cout << Verbose(0) << "t - translate molecule by vector" << endl;
1036 cout << Verbose(0) << "c - scale by unit transformation" << endl;
1037 cout << Verbose(0) << "g - center atoms in box" << endl;
1038 cout << Verbose(0) << "-----------------------------------------------" << endl;
1039 cout << Verbose(0) << "s - save current setup to config file" << endl;
1040 cout << Verbose(0) << "T - call the current test routine" << endl;
1041 cout << Verbose(0) << "q - quit" << endl;
1042 cout << Verbose(0) << "===============================================" << endl;
1043 cout << Verbose(0) << "Input: ";
1044 cin >> choice;
1045
1046 switch (choice) {
1047 default:
1048 case 'a': // add atom
1049 AddAtoms(periode, mol);
1050 choice = 'a';
1051 break;
1052
1053 case 'b': // scale a bond
1054 cout << Verbose(0) << "Scaling bond length between two atoms." << endl;
1055 first = mol->AskAtom("Enter first (fixed) atom: ");
1056 second = mol->AskAtom("Enter second (shifting) atom: ");
1057 min_bond = 0.;
1058 for (int i=NDIM;i--;)
1059 min_bond += (first->x.x[i]-second->x.x[i])*(first->x.x[i] - second->x.x[i]);
1060 min_bond = sqrt(min_bond);
1061 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;
1062 cout << Verbose(0) << "Enter new bond length [a.u.]: ";
1063 cin >> bond;
1064 for (int i=NDIM;i--;) {
1065 second->x.x[i] -= (second->x.x[i]-first->x.x[i])/min_bond*(min_bond-bond);
1066 }
1067 //cout << Verbose(0) << "New coordinates of Atom " << second->nr << " are: ";
1068 //second->Output(second->type->No, 1, (ofstream *)&cout);
1069 break;
1070
1071 case 'c': // unit scaling of the metric
1072 cout << Verbose(0) << "Angstroem -> Bohrradius: 1.8897261\t\tBohrradius -> Angstroem: 0.52917721" << endl;
1073 cout << Verbose(0) << "Enter three factors: ";
1074 factor = new double[NDIM];
1075 cin >> factor[0];
1076 cin >> factor[1];
1077 cin >> factor[2];
1078 valid = true;
1079 mol->Scale(&factor);
1080 delete[](factor);
1081 break;
1082
1083 case 'd': // duplicate the periodic cell along a given axis, given times
1084 cout << Verbose(0) << "State the axis [(+-)123]: ";
1085 cin >> axis;
1086 cout << Verbose(0) << "State the factor: ";
1087 cin >> faktor;
1088
1089 mol->CountAtoms((ofstream *)&cout); // recount atoms
1090 if (mol->AtomCount != 0) { // if there is more than none
1091 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand
1092 Elements = new element *[count];
1093 Vectors = new vector *[count];
1094 j = 0;
1095 first = mol->start;
1096 while (first->next != mol->end) { // make a list of all atoms with coordinates and element
1097 first = first->next;
1098 Elements[j] = first->type;
1099 Vectors[j] = &first->x;
1100 j++;
1101 }
1102 if (count != j)
1103 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;
1104 x.Zero();
1105 y.Zero();
1106 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
1107 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times
1108 x.AddVector(&y); // per factor one cell width further
1109 for (int k=count;k--;) { // go through every atom of the original cell
1110 first = new atom(); // create a new body
1111 first->x.CopyVector(Vectors[k]); // use coordinate of original atom
1112 first->x.AddVector(&x); // translate the coordinates
1113 first->type = Elements[k]; // insert original element
1114 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)
1115 }
1116 }
1117 if (mol->first->next != mol->last) // if connect matrix is present already, redo it
1118 mol->CreateAdjacencyList((ofstream *)&cout, mol->BondDistance, configuration.GetIsAngstroem());
1119 // free memory
1120 delete[](Elements);
1121 delete[](Vectors);
1122 // correct cell size
1123 if (axis < 0) { // if sign was negative, we have to translate everything
1124 x.Zero();
1125 x.AddVector(&y);
1126 x.Scale(-(faktor-1));
1127 mol->Translate(&x);
1128 }
1129 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;
1130 }
1131 break;
1132
1133 case 'e': // edit each field of the configuration
1134 configuration.Edit(mol);
1135 break;
1136
1137 case 'f':
1138 FragmentAtoms(mol, &configuration);
1139 break;
1140
1141 case 'g': // center the atoms
1142 CenterAtoms(mol);
1143 break;
1144
1145 case 'i': // align all atoms
1146 AlignAtoms(periode, mol);
1147 break;
1148
1149 case 'l': // measure distances or angles
1150 MeasureAtoms(periode, mol);
1151 break;
1152
1153 case 'm': // mirror atoms along a given axis
1154 MirrorAtoms(mol);
1155 break;
1156
1157 case 'o': // create the connection matrix
1158 cout << Verbose(0) << "What's the maximum bond distance: ";
1159 cin >> tmp1;
1160 start = clock();
1161 mol->CreateAdjacencyList((ofstream *)&cout, tmp1, configuration.GetIsAngstroem());
1162 //mol->CreateListOfBondsPerAtom((ofstream *)&cout);
1163 Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, false, MinimumRingSize);
1164 while (Subgraphs->next != NULL) {
1165 Subgraphs = Subgraphs->next;
1166 delete(Subgraphs->previous);
1167 }
1168 delete(Subgraphs); // we don't need the list here, so free everything
1169 delete[](MinimumRingSize);
1170 Subgraphs = NULL;
1171 end = clock();
1172 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
1173 break;
1174
1175 case 'p': // parse and XYZ file
1176 cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
1177 do {
1178 cout << Verbose(0) << "Enter file name: ";
1179 cin >> filename;
1180 } while (!mol->AddXYZFile(filename));
1181 break;
1182
1183 case 'q': // quit
1184 break;
1185
1186 case 'r': // remove atom
1187 RemoveAtoms(mol);
1188 break;
1189
1190 case 's': // save to config file
1191 SaveConfig(ConfigFileName, &configuration, periode, mol);
1192 break;
1193
1194 case 't': // translate all atoms
1195 cout << Verbose(0) << "Enter translation vector." << endl;
1196 x.AskPosition(mol->cell_size,0);
1197 mol->Translate((const vector *)&x);
1198 break;
1199
1200 case 'T':
1201 testroutine(mol);
1202 break;
1203
1204 case 'u': // change an atom's element
1205 first = NULL;
1206 do {
1207 cout << Verbose(0) << "Change the element of which atom: ";
1208 cin >> Z;
1209 } while ((first = mol->FindAtom(Z)) == NULL);
1210 cout << Verbose(0) << "New element by atomic number Z: ";
1211 cin >> Z;
1212 first->type = periode->FindElement(Z);
1213 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl;
1214 break;
1215 };
1216 } while (choice != 'q');
1217
1218 // save element data base
1219 if (periode->StorePeriodentafel()) //ElementsFileName
1220 cout << Verbose(0) << "Saving of elements.db successful." << endl;
1221 else
1222 cout << Verbose(0) << "Saving of elements.db failed." << endl;
1223
1224 // Free all
1225 if (Subgraphs != NULL) { // free disconnected subgraph list of DFS analysis was performed
1226 while (Subgraphs->next != NULL) {
1227 Subgraphs = Subgraphs->next;
1228 delete(Subgraphs->previous);
1229 }
1230 delete(Subgraphs);
1231 }
1232 delete(mol);
1233 delete(periode);
1234 return (0);
1235}
1236
1237/********************************************** E N D **************************************************/
Note: See TracBrowser for help on using the repository browser.