source: src/builder.cpp@ 4b4d65

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

renamed ElementsFileName to PathToDatabases, -e now gives path to databases instead of elements db file

We rather now give the path and not elements db file as all the databases generally reside in the same dir.

  • Property mode set to 100644
File size: 48.3 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 *PathToDatabases pointer to db's path 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 *&PathToDatabases)
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 PathToDatabases = LocalPath;
726
727 if (argc > 1) { // config file specified as option
728 // 1. : Parse options that just set variables or print help
729 argptr = 1;
730 do {
731 if (argv[argptr][0] == '-') {
732 cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n";
733 argptr++;
734 switch(argv[argptr-1][1]) {
735 case 'h':
736 case 'H':
737 case '?':
738 cout << "MoleCuilder suite" << endl << "==================" << endl << endl;
739 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl;
740 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl;
741 cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl;
742 cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl;
743 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl;
744 cout << "\t-e <file>\tSets the databases path to be parsed (default: ./)." << endl;
745 cout << "\t-f <dist> <order>\tFragments the molecule in BOSSANOVA manner and stores config files in same dir as config." << endl;
746 cout << "\t-h/-H/-?\tGive this help screen." << endl;
747 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;
748 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl;
749 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl;
750 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl;
751 cout << "\t-v/-V\t\tGives version information." << endl;
752 cout << "Note: config files must not begin with '-' !" << endl;
753 delete(mol);
754 delete(periode);
755 return (1);
756 break;
757 case 'v':
758 case 'V':
759 cout << argv[0] << " " << VERSIONSTRING << endl;
760 cout << "Build your own molecule position set." << endl;
761 delete(mol);
762 delete(periode);
763 return (1);
764 break;
765 case 'e':
766 cout << "Using " << argv[argptr] << " as elements database." << endl;
767 PathToDatabases = argv[argptr];
768 argptr+=1;
769 break;
770 default: // no match? Step on
771 argptr++;
772 break;
773 }
774 } else
775 argptr++;
776 } while (argptr < argc);
777
778 // 2. Parse the element database
779 if (periode->LoadPeriodentafel(PathToDatabases)) {
780 cout << Verbose(0) << "Element list loaded successfully." << endl;
781 periode->Output((ofstream *)&cout);
782 } else
783 cout << Verbose(0) << "Element list loading failed." << endl;
784
785 // 3. Find config file name and parse if possible
786 if (argv[1][0] != '-') {
787 cout << Verbose(0) << "Config file given." << endl;
788 test.open(argv[1], ios::in);
789 if (test == NULL) {
790 //return (1);
791 output.open(argv[1], ios::out);
792 if (output == NULL) {
793 cout << Verbose(1) << "Specified config file " << argv[1] << " not found." << endl;
794 config_present = absent;
795 } else {
796 cout << "Empty configuration file." << endl;
797 ConfigFileName = argv[1];
798 config_present = empty;
799 output.close();
800 }
801 } else {
802 test.close();
803 ConfigFileName = argv[1];
804 cout << Verbose(1) << "Specified config file found, parsing ...";
805 switch (configuration.TestSyntax(ConfigFileName, periode, mol)) {
806 case 1:
807 cout << "new syntax." << endl;
808 configuration.Load(ConfigFileName, periode, mol);
809 config_present = present;
810 break;
811 case 0:
812 cout << "old syntax." << endl;
813 configuration.LoadOld(ConfigFileName, periode, mol);
814 config_present = present;
815 break;
816 default:
817 cout << "Unknown syntax or empty, yet present file." << endl;
818 config_present = empty;
819 }
820 }
821 } else
822 config_present = absent;
823
824 // 4. parse again through options, now for those depending on elements db and config presence
825 argptr = 1;
826 do {
827 cout << "Current Command line argument: " << argv[argptr] << "." << endl;
828 if (argv[argptr][0] == '-') {
829 argptr++;
830 if ((config_present == present) || (config_present == empty)) {
831 switch(argv[argptr-1][1]) {
832 case 'p':
833 ExitFlag = 1;
834 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl;
835 if (!mol->AddXYZFile(argv[argptr]))
836 cout << Verbose(2) << "File not found." << endl;
837 else
838 cout << Verbose(2) << "File found and parsed." << endl;
839 config_present = present;
840 break;
841 default: // no match? Don't step on (this is done in next switch's default)
842 break;
843 }
844 }
845 if (config_present == present) {
846 switch(argv[argptr-1][1]) {
847 case 't':
848 ExitFlag = 1;
849 cout << Verbose(1) << "Translating all ions to new origin." << endl;
850 for (int i=NDIM;i--;)
851 x.x[i] = atof(argv[argptr+i]);
852 mol->Translate((const vector *)&x);
853 argptr+=3;
854 break;
855 case 'a':
856 ExitFlag = 1;
857 cout << Verbose(1) << "Adding new atom." << endl;
858 first = new atom;
859 for (int i=NDIM;i--;)
860 first->x.x[i] = atof(argv[argptr+1+i]);
861 finder = periode->start;
862 while (finder != periode->end) {
863 finder = finder->next;
864 if (strncmp(finder->symbol,argv[argptr+1],3) == 0) {
865 first->type = finder;
866 break;
867 }
868 }
869 mol->AddAtom(first); // add to molecule
870 argptr+=4;
871 break;
872 case 's':
873 ExitFlag = 1;
874 j = -1;
875 cout << Verbose(1) << "Scaling all ion positions by factor." << endl;
876 factor = new double[NDIM];
877 factor[0] = atof(argv[argptr]);
878 if (argc > argptr+1)
879 argptr++;
880 factor[1] = atof(argv[argptr]);
881 if (argc > argptr+1)
882 argptr++;
883 factor[2] = atof(argv[argptr]);
884 mol->Scale(&factor);
885 for (int i=0;i<NDIM;i++) {
886 j += i+1;
887 x.x[i] = atof(argv[NDIM+i]);
888 mol->cell_size[j]*=factor[i];
889 }
890 delete[](factor);
891 argptr+=1;
892 break;
893 case 'b':
894 ExitFlag = 1;
895 j = -1;
896 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
897 j=-1;
898 for (int i=0;i<NDIM;i++) {
899 j += i+1;
900 x.x[i] = atof(argv[argptr++]);
901 mol->cell_size[j] += x.x[i]*2.;
902 }
903 // center
904 mol->CenterInBox((ofstream *)&cout, &x);
905 // update Box of atoms by boundary
906 mol->SetBoxDimension(&x);
907 break;
908 case 'c':
909 ExitFlag = 1;
910 j = -1;
911 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl;
912 // make every coordinate positive
913 mol->CenterEdge((ofstream *)&cout, &x);
914 // update Box of atoms by boundary
915 mol->SetBoxDimension(&x);
916 // translate each coordinate by boundary
917 j=-1;
918 for (int i=0;i<NDIM;i++) {
919 j += i+1;
920 x.x[i] = atof(argv[argptr++]);
921 mol->cell_size[j] += x.x[i]*2.;
922 }
923 mol->Translate((const vector *)&x);
924 break;
925 case 'r':
926 ExitFlag = 1;
927 cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl;
928 break;
929 case 'f':
930 if (ExitFlag ==0) ExitFlag = 2; // only set if not already by other command line switch
931 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl;
932 if (argc >= argptr+2) {
933 cout << Verbose(0) << "Creating connection matrix..." << endl;
934 start = clock();
935 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]), configuration.GetIsAngstroem());
936 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
937 if (mol->first->next != mol->last) {
938 mol->FragmentMolecule((ofstream *)&cout, atoi(argv[argptr]), &configuration);
939 }
940 end = clock();
941 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
942 argptr+=1;
943 } else {
944 cerr << "Not enough arguments for fragmentation: -f <max. bond distance> <bond order>" << endl;
945 }
946 break;
947 default: // no match? Step on
948 argptr++;
949 break;
950 }
951 }
952 } else argptr++;
953 } while (argptr < argc);
954 if (ExitFlag == 1) // 1 means save and exit
955 SaveConfig(ConfigFileName, &configuration, periode, mol);
956 if (ExitFlag >= 1) { // 2 means just exit
957 delete(mol);
958 delete(periode);
959 return (1);
960 }
961 } else { // no arguments, hence scan the elements db
962 if (periode->LoadPeriodentafel(PathToDatabases))
963 cout << Verbose(0) << "Element list loaded successfully." << endl;
964 else
965 cout << Verbose(0) << "Element list loading failed." << endl;
966 configuration.RetrieveConfigPathAndName("main_pcp_linux");
967 }
968 return(0);
969};
970
971/********************************************** Main routine **************************************/
972
973int main(int argc, char **argv)
974{
975 periodentafel *periode = new periodentafel; // and a period table of all elements
976 molecule *mol = new molecule(periode); // first we need an empty molecule
977 config configuration;
978 double tmp1;
979 double bond, min_bond;
980 atom *first, *second;
981 char choice; // menu choice char
982 vector x,y,z,n; // coordinates for absolute point in cell volume
983 double *factor; // unit factor if desired
984 bool valid; // flag if input was valid or not
985 ifstream test;
986 ofstream output;
987 string line;
988 char filename[MAXSTRINGSIZE];
989 char *ConfigFileName = NULL;
990 char *ElementsFileName = NULL;
991 int Z;
992 int j, axis, count, faktor;
993 int *MinimumRingSize = NULL;
994 MoleculeLeafClass *Subgraphs = NULL;
995 clock_t start,end;
996 element **Elements;
997 vector **Vectors;
998
999 // =========================== PARSE COMMAND LINE OPTIONS ====================================
1000 j = ParseCommandLineOptions(argc, argv, mol, periode, configuration, ConfigFileName, ElementsFileName);
1001 if (j == 1) return 0; // just for -v and -h options
1002 if (j) return j; // something went wrong
1003 periode->Output((ofstream *)&cout);
1004
1005 // General stuff
1006 if (mol->cell_size[0] == 0.) {
1007 cout << Verbose(0) << "enter lower triadiagonal form of basis matrix" << endl << endl;
1008 for (int i=0;i<6;i++) {
1009 cout << Verbose(1) << "Cell size" << i << ": ";
1010 cin >> mol->cell_size[i];
1011 }
1012 }
1013
1014 // =========================== START INTERACTIVE SESSION ====================================
1015
1016 // now the main construction loop
1017 cout << Verbose(0) << endl << "Now comes the real construction..." << endl;
1018 do {
1019 cout << Verbose(0) << endl << endl;
1020 cout << Verbose(0) << "============Element list=======================" << endl;
1021 mol->Checkout((ofstream *)&cout);
1022 cout << Verbose(0) << "============Atom list==========================" << endl;
1023 mol->Output((ofstream *)&cout);
1024 cout << Verbose(0) << "============Menu===============================" << endl;
1025 cout << Verbose(0) << "a - add an atom" << endl;
1026 cout << Verbose(0) << "r - remove an atom" << endl;
1027 cout << Verbose(0) << "b - scale a bond between atoms" << endl;
1028 cout << Verbose(0) << "u - change an atoms element" << endl;
1029 cout << Verbose(0) << "l - measure lengths, angles, ... for an atom" << endl;
1030 cout << Verbose(0) << "-----------------------------------------------" << endl;
1031 cout << Verbose(0) << "p - Parse xyz file" << endl;
1032 cout << Verbose(0) << "e - edit the current configuration" << endl;
1033 cout << Verbose(0) << "o - create connection matrix" << endl;
1034 cout << Verbose(0) << "f - fragment molecule many-body bond order style" << endl;
1035 cout << Verbose(0) << "-----------------------------------------------" << endl;
1036 cout << Verbose(0) << "d - duplicate molecule/periodic cell" << endl;
1037 cout << Verbose(0) << "i - realign molecule" << endl;
1038 cout << Verbose(0) << "m - mirror all molecules" << endl;
1039 cout << Verbose(0) << "t - translate molecule by vector" << endl;
1040 cout << Verbose(0) << "c - scale by unit transformation" << endl;
1041 cout << Verbose(0) << "g - center atoms in box" << endl;
1042 cout << Verbose(0) << "-----------------------------------------------" << endl;
1043 cout << Verbose(0) << "s - save current setup to config file" << endl;
1044 cout << Verbose(0) << "T - call the current test routine" << endl;
1045 cout << Verbose(0) << "q - quit" << endl;
1046 cout << Verbose(0) << "===============================================" << endl;
1047 cout << Verbose(0) << "Input: ";
1048 cin >> choice;
1049
1050 switch (choice) {
1051 default:
1052 case 'a': // add atom
1053 AddAtoms(periode, mol);
1054 choice = 'a';
1055 break;
1056
1057 case 'b': // scale a bond
1058 cout << Verbose(0) << "Scaling bond length between two atoms." << endl;
1059 first = mol->AskAtom("Enter first (fixed) atom: ");
1060 second = mol->AskAtom("Enter second (shifting) atom: ");
1061 min_bond = 0.;
1062 for (int i=NDIM;i--;)
1063 min_bond += (first->x.x[i]-second->x.x[i])*(first->x.x[i] - second->x.x[i]);
1064 min_bond = sqrt(min_bond);
1065 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;
1066 cout << Verbose(0) << "Enter new bond length [a.u.]: ";
1067 cin >> bond;
1068 for (int i=NDIM;i--;) {
1069 second->x.x[i] -= (second->x.x[i]-first->x.x[i])/min_bond*(min_bond-bond);
1070 }
1071 //cout << Verbose(0) << "New coordinates of Atom " << second->nr << " are: ";
1072 //second->Output(second->type->No, 1, (ofstream *)&cout);
1073 break;
1074
1075 case 'c': // unit scaling of the metric
1076 cout << Verbose(0) << "Angstroem -> Bohrradius: 1.8897261\t\tBohrradius -> Angstroem: 0.52917721" << endl;
1077 cout << Verbose(0) << "Enter three factors: ";
1078 factor = new double[NDIM];
1079 cin >> factor[0];
1080 cin >> factor[1];
1081 cin >> factor[2];
1082 valid = true;
1083 mol->Scale(&factor);
1084 delete[](factor);
1085 break;
1086
1087 case 'd': // duplicate the periodic cell along a given axis, given times
1088 cout << Verbose(0) << "State the axis [(+-)123]: ";
1089 cin >> axis;
1090 cout << Verbose(0) << "State the factor: ";
1091 cin >> faktor;
1092
1093 mol->CountAtoms((ofstream *)&cout); // recount atoms
1094 if (mol->AtomCount != 0) { // if there is more than none
1095 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand
1096 Elements = new element *[count];
1097 Vectors = new vector *[count];
1098 j = 0;
1099 first = mol->start;
1100 while (first->next != mol->end) { // make a list of all atoms with coordinates and element
1101 first = first->next;
1102 Elements[j] = first->type;
1103 Vectors[j] = &first->x;
1104 j++;
1105 }
1106 if (count != j)
1107 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;
1108 x.Zero();
1109 y.Zero();
1110 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
1111 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times
1112 x.AddVector(&y); // per factor one cell width further
1113 for (int k=count;k--;) { // go through every atom of the original cell
1114 first = new atom(); // create a new body
1115 first->x.CopyVector(Vectors[k]); // use coordinate of original atom
1116 first->x.AddVector(&x); // translate the coordinates
1117 first->type = Elements[k]; // insert original element
1118 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)
1119 }
1120 }
1121 if (mol->first->next != mol->last) // if connect matrix is present already, redo it
1122 mol->CreateAdjacencyList((ofstream *)&cout, mol->BondDistance, configuration.GetIsAngstroem());
1123 // free memory
1124 delete[](Elements);
1125 delete[](Vectors);
1126 // correct cell size
1127 if (axis < 0) { // if sign was negative, we have to translate everything
1128 x.Zero();
1129 x.AddVector(&y);
1130 x.Scale(-(faktor-1));
1131 mol->Translate(&x);
1132 }
1133 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;
1134 }
1135 break;
1136
1137 case 'e': // edit each field of the configuration
1138 configuration.Edit(mol);
1139 break;
1140
1141 case 'f':
1142 FragmentAtoms(mol, &configuration);
1143 break;
1144
1145 case 'g': // center the atoms
1146 CenterAtoms(mol);
1147 break;
1148
1149 case 'i': // align all atoms
1150 AlignAtoms(periode, mol);
1151 break;
1152
1153 case 'l': // measure distances or angles
1154 MeasureAtoms(periode, mol);
1155 break;
1156
1157 case 'm': // mirror atoms along a given axis
1158 MirrorAtoms(mol);
1159 break;
1160
1161 case 'o': // create the connection matrix
1162 cout << Verbose(0) << "What's the maximum bond distance: ";
1163 cin >> tmp1;
1164 start = clock();
1165 mol->CreateAdjacencyList((ofstream *)&cout, tmp1, configuration.GetIsAngstroem());
1166 //mol->CreateListOfBondsPerAtom((ofstream *)&cout);
1167 Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, false, MinimumRingSize);
1168 while (Subgraphs->next != NULL) {
1169 Subgraphs = Subgraphs->next;
1170 delete(Subgraphs->previous);
1171 }
1172 delete(Subgraphs); // we don't need the list here, so free everything
1173 delete[](MinimumRingSize);
1174 Subgraphs = NULL;
1175 end = clock();
1176 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
1177 break;
1178
1179 case 'p': // parse and XYZ file
1180 cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
1181 do {
1182 cout << Verbose(0) << "Enter file name: ";
1183 cin >> filename;
1184 } while (!mol->AddXYZFile(filename));
1185 break;
1186
1187 case 'q': // quit
1188 break;
1189
1190 case 'r': // remove atom
1191 RemoveAtoms(mol);
1192 break;
1193
1194 case 's': // save to config file
1195 SaveConfig(ConfigFileName, &configuration, periode, mol);
1196 break;
1197
1198 case 't': // translate all atoms
1199 cout << Verbose(0) << "Enter translation vector." << endl;
1200 x.AskPosition(mol->cell_size,0);
1201 mol->Translate((const vector *)&x);
1202 break;
1203
1204 case 'T':
1205 testroutine(mol);
1206 break;
1207
1208 case 'u': // change an atom's element
1209 first = NULL;
1210 do {
1211 cout << Verbose(0) << "Change the element of which atom: ";
1212 cin >> Z;
1213 } while ((first = mol->FindAtom(Z)) == NULL);
1214 cout << Verbose(0) << "New element by atomic number Z: ";
1215 cin >> Z;
1216 first->type = periode->FindElement(Z);
1217 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl;
1218 break;
1219 };
1220 } while (choice != 'q');
1221
1222 // save element data base
1223 if (periode->StorePeriodentafel()) //ElementsFileName
1224 cout << Verbose(0) << "Saving of elements.db successful." << endl;
1225 else
1226 cout << Verbose(0) << "Saving of elements.db failed." << endl;
1227
1228 // Free all
1229 if (Subgraphs != NULL) { // free disconnected subgraph list of DFS analysis was performed
1230 while (Subgraphs->next != NULL) {
1231 Subgraphs = Subgraphs->next;
1232 delete(Subgraphs->previous);
1233 }
1234 delete(Subgraphs);
1235 }
1236 delete(mol);
1237 delete(periode);
1238 return (0);
1239}
1240
1241/********************************************** E N D **************************************************/
Note: See TracBrowser for help on using the repository browser.