source: src/builder.cpp@ db6bf74

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

Fixed two memory leaks.

  • FIX: if the element database could not be parsed, in LoadPeriodentafel() still one element would be allocated, Loading failure admonished and then not free'd. Fixed
  • FIX: the config was allocated in main not by a new, but fixed. In its constructor Malloc calls were present. Hence, the memory was not free'd. As fixed types are free'd first at the very end of the code. Hence before any MemoryUsageObserver::getUsedMemorySize() calls ... that's why 1614 bytes were always claimed as still allocated. Fixed.
  • valgrind does not admonish any leaks (however, some errors) anymore when molecuilder is started and immediately quitted.

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

  • Property mode set to 100755
File size: 94.0 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 "analysis_correlation.hpp"
53#include "atom.hpp"
54#include "bond.hpp"
55#include "boundary.hpp"
56#include "config.hpp"
57#include "element.hpp"
58#include "ellipsoid.hpp"
59#include "helpers.hpp"
60#include "leastsquaremin.hpp"
61#include "linkedcell.hpp"
62#include "memoryusageobserverunittest.hpp"
63#include "molecule.hpp"
64#include "periodentafel.hpp"
65
66/********************************************* Subsubmenu routine ************************************/
67
68/** Submenu for adding atoms to the molecule.
69 * \param *periode periodentafel
70 * \param *molecule molecules with atoms
71 */
72static void AddAtoms(periodentafel *periode, molecule *mol)
73{
74 atom *first, *second, *third, *fourth;
75 Vector **atoms;
76 Vector x,y,z,n; // coordinates for absolute point in cell volume
77 double a,b,c;
78 char choice; // menu choice char
79 bool valid;
80
81 cout << Verbose(0) << "===========ADD ATOM============================" << endl;
82 cout << Verbose(0) << " a - state absolute coordinates of atom" << endl;
83 cout << Verbose(0) << " b - state relative coordinates of atom wrt to reference point" << endl;
84 cout << Verbose(0) << " c - state relative coordinates of atom wrt to already placed atom" << endl;
85 cout << Verbose(0) << " d - state two atoms, two angles and a distance" << endl;
86 cout << Verbose(0) << " e - least square distance position to a set of atoms" << endl;
87 cout << Verbose(0) << "all else - go back" << endl;
88 cout << Verbose(0) << "===============================================" << endl;
89 cout << Verbose(0) << "Note: Specifiy angles in degrees not multiples of Pi!" << endl;
90 cout << Verbose(0) << "INPUT: ";
91 cin >> choice;
92
93 switch (choice) {
94 default:
95 cout << Verbose(0) << "Not a valid choice." << endl;
96 break;
97 case 'a': // absolute coordinates of atom
98 cout << Verbose(0) << "Enter absolute coordinates." << endl;
99 first = new atom;
100 first->x.AskPosition(mol->cell_size, false);
101 first->type = periode->AskElement(); // give type
102 mol->AddAtom(first); // add to molecule
103 break;
104
105 case 'b': // relative coordinates of atom wrt to reference point
106 first = new atom;
107 valid = true;
108 do {
109 if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl;
110 cout << Verbose(0) << "Enter reference coordinates." << endl;
111 x.AskPosition(mol->cell_size, true);
112 cout << Verbose(0) << "Enter relative coordinates." << endl;
113 first->x.AskPosition(mol->cell_size, false);
114 first->x.AddVector((const Vector *)&x);
115 cout << Verbose(0) << "\n";
116 } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
117 first->type = periode->AskElement(); // give type
118 mol->AddAtom(first); // add to molecule
119 break;
120
121 case 'c': // relative coordinates of atom wrt to already placed atom
122 first = new atom;
123 valid = true;
124 do {
125 if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl;
126 second = mol->AskAtom("Enter atom number: ");
127 cout << Verbose(0) << "Enter relative coordinates." << endl;
128 first->x.AskPosition(mol->cell_size, false);
129 for (int i=NDIM;i--;) {
130 first->x.x[i] += second->x.x[i];
131 }
132 } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
133 first->type = periode->AskElement(); // give type
134 mol->AddAtom(first); // add to molecule
135 break;
136
137 case 'd': // two atoms, two angles and a distance
138 first = new atom;
139 valid = true;
140 do {
141 if (!valid) {
142 cout << Verbose(0) << "Resulting coordinates out of cell - ";
143 first->x.Output((ofstream *)&cout);
144 cout << Verbose(0) << endl;
145 }
146 cout << Verbose(0) << "First, we need two atoms, the first atom is the central, while the second is the outer one." << endl;
147 second = mol->AskAtom("Enter central atom: ");
148 third = mol->AskAtom("Enter second atom (specifying the axis for first angle): ");
149 fourth = mol->AskAtom("Enter third atom (specifying a plane for second angle): ");
150 a = ask_value("Enter distance between central (first) and new atom: ");
151 b = ask_value("Enter angle between new, first and second atom (degrees): ");
152 b *= M_PI/180.;
153 bound(&b, 0., 2.*M_PI);
154 c = ask_value("Enter second angle between new and normal vector of plane defined by first, second and third atom (degrees): ");
155 c *= M_PI/180.;
156 bound(&c, -M_PI, M_PI);
157 cout << Verbose(0) << "radius: " << a << "\t phi: " << b*180./M_PI << "\t theta: " << c*180./M_PI << endl;
158/*
159 second->Output(1,1,(ofstream *)&cout);
160 third->Output(1,2,(ofstream *)&cout);
161 fourth->Output(1,3,(ofstream *)&cout);
162 n.MakeNormalvector((const vector *)&second->x, (const vector *)&third->x, (const vector *)&fourth->x);
163 x.Copyvector(&second->x);
164 x.SubtractVector(&third->x);
165 x.Copyvector(&fourth->x);
166 x.SubtractVector(&third->x);
167
168 if (!z.SolveSystem(&x,&y,&n, b, c, a)) {
169 cout << Verbose(0) << "Failure solving self-dependent linear system!" << endl;
170 continue;
171 }
172 cout << Verbose(0) << "resulting relative coordinates: ";
173 z.Output((ofstream *)&cout);
174 cout << Verbose(0) << endl;
175 */
176 // calc axis vector
177 x.CopyVector(&second->x);
178 x.SubtractVector(&third->x);
179 x.Normalize();
180 cout << "x: ",
181 x.Output((ofstream *)&cout);
182 cout << endl;
183 z.MakeNormalVector(&second->x,&third->x,&fourth->x);
184 cout << "z: ",
185 z.Output((ofstream *)&cout);
186 cout << endl;
187 y.MakeNormalVector(&x,&z);
188 cout << "y: ",
189 y.Output((ofstream *)&cout);
190 cout << endl;
191
192 // rotate vector around first angle
193 first->x.CopyVector(&x);
194 first->x.RotateVector(&z,b - M_PI);
195 cout << "Rotated vector: ",
196 first->x.Output((ofstream *)&cout);
197 cout << endl;
198 // remove the projection onto the rotation plane of the second angle
199 n.CopyVector(&y);
200 n.Scale(first->x.ScalarProduct(&y));
201 cout << "N1: ",
202 n.Output((ofstream *)&cout);
203 cout << endl;
204 first->x.SubtractVector(&n);
205 cout << "Subtracted vector: ",
206 first->x.Output((ofstream *)&cout);
207 cout << endl;
208 n.CopyVector(&z);
209 n.Scale(first->x.ScalarProduct(&z));
210 cout << "N2: ",
211 n.Output((ofstream *)&cout);
212 cout << endl;
213 first->x.SubtractVector(&n);
214 cout << "2nd subtracted vector: ",
215 first->x.Output((ofstream *)&cout);
216 cout << endl;
217
218 // rotate another vector around second angle
219 n.CopyVector(&y);
220 n.RotateVector(&x,c - M_PI);
221 cout << "2nd Rotated vector: ",
222 n.Output((ofstream *)&cout);
223 cout << endl;
224
225 // add the two linear independent vectors
226 first->x.AddVector(&n);
227 first->x.Normalize();
228 first->x.Scale(a);
229 first->x.AddVector(&second->x);
230
231 cout << Verbose(0) << "resulting coordinates: ";
232 first->x.Output((ofstream *)&cout);
233 cout << Verbose(0) << endl;
234 } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
235 first->type = periode->AskElement(); // give type
236 mol->AddAtom(first); // add to molecule
237 break;
238
239 case 'e': // least square distance position to a set of atoms
240 first = new atom;
241 atoms = new (Vector*[128]);
242 valid = true;
243 for(int i=128;i--;)
244 atoms[i] = NULL;
245 int i=0, j=0;
246 cout << Verbose(0) << "Now we need at least three molecules.\n";
247 do {
248 cout << Verbose(0) << "Enter " << i+1 << "th atom: ";
249 cin >> j;
250 if (j != -1) {
251 second = mol->FindAtom(j);
252 atoms[i++] = &(second->x);
253 }
254 } while ((j != -1) && (i<128));
255 if (i >= 2) {
256 first->x.LSQdistance(atoms, i);
257
258 first->x.Output((ofstream *)&cout);
259 first->type = periode->AskElement(); // give type
260 mol->AddAtom(first); // add to molecule
261 } else {
262 delete first;
263 cout << Verbose(0) << "Please enter at least two vectors!\n";
264 }
265 break;
266 };
267};
268
269/** Submenu for centering the atoms in the molecule.
270 * \param *mol molecule with all the atoms
271 */
272static void CenterAtoms(molecule *mol)
273{
274 Vector x, y, helper;
275 char choice; // menu choice char
276
277 cout << Verbose(0) << "===========CENTER ATOMS=========================" << endl;
278 cout << Verbose(0) << " a - on origin" << endl;
279 cout << Verbose(0) << " b - on center of gravity" << endl;
280 cout << Verbose(0) << " c - within box with additional boundary" << endl;
281 cout << Verbose(0) << " d - within given simulation box" << endl;
282 cout << Verbose(0) << "all else - go back" << endl;
283 cout << Verbose(0) << "===============================================" << endl;
284 cout << Verbose(0) << "INPUT: ";
285 cin >> choice;
286
287 switch (choice) {
288 default:
289 cout << Verbose(0) << "Not a valid choice." << endl;
290 break;
291 case 'a':
292 cout << Verbose(0) << "Centering atoms in config file on origin." << endl;
293 mol->CenterOrigin((ofstream *)&cout);
294 break;
295 case 'b':
296 cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl;
297 mol->CenterPeriodic((ofstream *)&cout);
298 break;
299 case 'c':
300 cout << Verbose(0) << "Centering atoms in config file within given additional boundary." << endl;
301 for (int i=0;i<NDIM;i++) {
302 cout << Verbose(0) << "Enter axis " << i << " boundary: ";
303 cin >> y.x[i];
304 }
305 mol->CenterEdge((ofstream *)&cout, &x); // make every coordinate positive
306 mol->Center.AddVector(&y); // translate by boundary
307 helper.CopyVector(&y);
308 helper.Scale(2.);
309 helper.AddVector(&x);
310 mol->SetBoxDimension(&helper); // update Box of atoms by boundary
311 break;
312 case 'd':
313 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
314 for (int i=0;i<NDIM;i++) {
315 cout << Verbose(0) << "Enter axis " << i << " boundary: ";
316 cin >> x.x[i];
317 }
318 // update Box of atoms by boundary
319 mol->SetBoxDimension(&x);
320 // center
321 mol->CenterInBox((ofstream *)&cout);
322 break;
323 }
324};
325
326/** Submenu for aligning the atoms in the molecule.
327 * \param *periode periodentafel
328 * \param *mol molecule with all the atoms
329 */
330static void AlignAtoms(periodentafel *periode, molecule *mol)
331{
332 atom *first, *second, *third;
333 Vector x,n;
334 char choice; // menu choice char
335
336 cout << Verbose(0) << "===========ALIGN ATOMS=========================" << endl;
337 cout << Verbose(0) << " a - state three atoms defining align plane" << endl;
338 cout << Verbose(0) << " b - state alignment vector" << endl;
339 cout << Verbose(0) << " c - state two atoms in alignment direction" << endl;
340 cout << Verbose(0) << " d - align automatically by least square fit" << endl;
341 cout << Verbose(0) << "all else - go back" << endl;
342 cout << Verbose(0) << "===============================================" << endl;
343 cout << Verbose(0) << "INPUT: ";
344 cin >> choice;
345
346 switch (choice) {
347 default:
348 case 'a': // three atoms defining mirror plane
349 first = mol->AskAtom("Enter first atom: ");
350 second = mol->AskAtom("Enter second atom: ");
351 third = mol->AskAtom("Enter third atom: ");
352
353 n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);
354 break;
355 case 'b': // normal vector of mirror plane
356 cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
357 n.AskPosition(mol->cell_size,0);
358 n.Normalize();
359 break;
360 case 'c': // three atoms defining mirror plane
361 first = mol->AskAtom("Enter first atom: ");
362 second = mol->AskAtom("Enter second atom: ");
363
364 n.CopyVector((const Vector *)&first->x);
365 n.SubtractVector((const Vector *)&second->x);
366 n.Normalize();
367 break;
368 case 'd':
369 char shorthand[4];
370 Vector a;
371 struct lsq_params param;
372 do {
373 fprintf(stdout, "Enter the element of atoms to be chosen: ");
374 fscanf(stdin, "%3s", shorthand);
375 } while ((param.type = periode->FindElement(shorthand)) == NULL);
376 cout << Verbose(0) << "Element is " << param.type->name << endl;
377 mol->GetAlignvector(&param);
378 for (int i=NDIM;i--;) {
379 x.x[i] = gsl_vector_get(param.x,i);
380 n.x[i] = gsl_vector_get(param.x,i+NDIM);
381 }
382 gsl_vector_free(param.x);
383 cout << Verbose(0) << "Offset vector: ";
384 x.Output((ofstream *)&cout);
385 cout << Verbose(0) << endl;
386 n.Normalize();
387 break;
388 };
389 cout << Verbose(0) << "Alignment vector: ";
390 n.Output((ofstream *)&cout);
391 cout << Verbose(0) << endl;
392 mol->Align(&n);
393};
394
395/** Submenu for mirroring the atoms in the molecule.
396 * \param *mol molecule with all the atoms
397 */
398static void MirrorAtoms(molecule *mol)
399{
400 atom *first, *second, *third;
401 Vector n;
402 char choice; // menu choice char
403
404 cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl;
405 cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl;
406 cout << Verbose(0) << " b - state normal vector of mirror plane" << endl;
407 cout << Verbose(0) << " c - state two atoms in normal direction" << endl;
408 cout << Verbose(0) << "all else - go back" << endl;
409 cout << Verbose(0) << "===============================================" << endl;
410 cout << Verbose(0) << "INPUT: ";
411 cin >> choice;
412
413 switch (choice) {
414 default:
415 case 'a': // three atoms defining mirror plane
416 first = mol->AskAtom("Enter first atom: ");
417 second = mol->AskAtom("Enter second atom: ");
418 third = mol->AskAtom("Enter third atom: ");
419
420 n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);
421 break;
422 case 'b': // normal vector of mirror plane
423 cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
424 n.AskPosition(mol->cell_size,0);
425 n.Normalize();
426 break;
427 case 'c': // three atoms defining mirror plane
428 first = mol->AskAtom("Enter first atom: ");
429 second = mol->AskAtom("Enter second atom: ");
430
431 n.CopyVector((const Vector *)&first->x);
432 n.SubtractVector((const Vector *)&second->x);
433 n.Normalize();
434 break;
435 };
436 cout << Verbose(0) << "Normal vector: ";
437 n.Output((ofstream *)&cout);
438 cout << Verbose(0) << endl;
439 mol->Mirror((const Vector *)&n);
440};
441
442/** Submenu for removing the atoms from the molecule.
443 * \param *mol molecule with all the atoms
444 */
445static void RemoveAtoms(molecule *mol)
446{
447 atom *first, *second;
448 int axis;
449 double tmp1, tmp2;
450 char choice; // menu choice char
451
452 cout << Verbose(0) << "===========REMOVE ATOMS=========================" << endl;
453 cout << Verbose(0) << " a - state atom for removal by number" << endl;
454 cout << Verbose(0) << " b - keep only in radius around atom" << endl;
455 cout << Verbose(0) << " c - remove this with one axis greater value" << endl;
456 cout << Verbose(0) << "all else - go back" << endl;
457 cout << Verbose(0) << "===============================================" << endl;
458 cout << Verbose(0) << "INPUT: ";
459 cin >> choice;
460
461 switch (choice) {
462 default:
463 case 'a':
464 if (mol->RemoveAtom(mol->AskAtom("Enter number of atom within molecule: ")))
465 cout << Verbose(1) << "Atom removed." << endl;
466 else
467 cout << Verbose(1) << "Atom not found." << endl;
468 break;
469 case 'b':
470 second = mol->AskAtom("Enter number of atom as reference point: ");
471 cout << Verbose(0) << "Enter radius: ";
472 cin >> tmp1;
473 first = mol->start;
474 second = first->next;
475 while(second != mol->end) {
476 first = second;
477 second = first->next;
478 if (first->x.DistanceSquared((const Vector *)&second->x) > tmp1*tmp1) // distance to first above radius ...
479 mol->RemoveAtom(first);
480 }
481 break;
482 case 'c':
483 cout << Verbose(0) << "Which axis is it: ";
484 cin >> axis;
485 cout << Verbose(0) << "Lower boundary: ";
486 cin >> tmp1;
487 cout << Verbose(0) << "Upper boundary: ";
488 cin >> tmp2;
489 first = mol->start;
490 second = first->next;
491 while(second != mol->end) {
492 first = second;
493 second = first->next;
494 if ((first->x.x[axis] < tmp1) || (first->x.x[axis] > tmp2)) {// out of boundary ...
495 //cout << "Atom " << *first << " with " << first->x.x[axis] << " on axis " << axis << " is out of bounds [" << tmp1 << "," << tmp2 << "]." << endl;
496 mol->RemoveAtom(first);
497 }
498 }
499 break;
500 };
501 //mol->Output((ofstream *)&cout);
502 choice = 'r';
503};
504
505/** Submenu for measuring out the atoms in the molecule.
506 * \param *periode periodentafel
507 * \param *mol molecule with all the atoms
508 */
509static void MeasureAtoms(periodentafel *periode, molecule *mol, config *configuration)
510{
511 atom *first, *second, *third;
512 Vector x,y;
513 double min[256], tmp1, tmp2, tmp3;
514 int Z;
515 char choice; // menu choice char
516
517 cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl;
518 cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl;
519 cout << Verbose(0) << " b - calculate bond length between two atoms" << endl;
520 cout << Verbose(0) << " c - calculate bond angle" << endl;
521 cout << Verbose(0) << " d - calculate principal axis of the system" << endl;
522 cout << Verbose(0) << " e - calculate volume of the convex envelope" << endl;
523 cout << Verbose(0) << " f - calculate temperature from current velocity" << endl;
524 cout << Verbose(0) << " g - output all temperatures per step from velocities" << endl;
525 cout << Verbose(0) << "all else - go back" << endl;
526 cout << Verbose(0) << "===============================================" << endl;
527 cout << Verbose(0) << "INPUT: ";
528 cin >> choice;
529
530 switch(choice) {
531 default:
532 cout << Verbose(1) << "Not a valid choice." << endl;
533 break;
534 case 'a':
535 first = mol->AskAtom("Enter first atom: ");
536 for (int i=MAX_ELEMENTS;i--;)
537 min[i] = 0.;
538
539 second = mol->start;
540 while ((second->next != mol->end)) {
541 second = second->next; // advance
542 Z = second->type->Z;
543 tmp1 = 0.;
544 if (first != second) {
545 x.CopyVector((const Vector *)&first->x);
546 x.SubtractVector((const Vector *)&second->x);
547 tmp1 = x.Norm();
548 }
549 if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1;
550 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl;
551 }
552 for (int i=MAX_ELEMENTS;i--;)
553 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;
554 break;
555
556 case 'b':
557 first = mol->AskAtom("Enter first atom: ");
558 second = mol->AskAtom("Enter second atom: ");
559 for (int i=NDIM;i--;)
560 min[i] = 0.;
561 x.CopyVector((const Vector *)&first->x);
562 x.SubtractVector((const Vector *)&second->x);
563 tmp1 = x.Norm();
564 cout << Verbose(1) << "Distance vector is ";
565 x.Output((ofstream *)&cout);
566 cout << "." << endl << "Norm of distance is " << tmp1 << "." << endl;
567 break;
568
569 case 'c':
570 cout << Verbose(0) << "Evaluating bond angle between three - first, central, last - atoms." << endl;
571 first = mol->AskAtom("Enter first atom: ");
572 second = mol->AskAtom("Enter central atom: ");
573 third = mol->AskAtom("Enter last atom: ");
574 tmp1 = tmp2 = tmp3 = 0.;
575 x.CopyVector((const Vector *)&first->x);
576 x.SubtractVector((const Vector *)&second->x);
577 y.CopyVector((const Vector *)&third->x);
578 y.SubtractVector((const Vector *)&second->x);
579 cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": ";
580 cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl;
581 break;
582 case 'd':
583 cout << Verbose(0) << "Evaluating prinicipal axis." << endl;
584 cout << Verbose(0) << "Shall we rotate? [0/1]: ";
585 cin >> Z;
586 if ((Z >=0) && (Z <=1))
587 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)Z);
588 else
589 mol->PrincipalAxisSystem((ofstream *)&cout, false);
590 break;
591 case 'e':
592 {
593 cout << Verbose(0) << "Evaluating volume of the convex envelope.";
594 LinkedCell LCList(mol, 10.);
595 class Tesselation *TesselStruct = NULL;
596 FindConvexBorder((ofstream *)&cout, mol, &LCList, NULL);
597 double clustervolume = VolumeOfConvexEnvelope((ofstream *)&cout, TesselStruct, configuration);
598 cout << Verbose(0) << "The tesselated surface area is " << clustervolume << "." << endl;
599 delete(TesselStruct);
600 }
601 break;
602 case 'f':
603 mol->OutputTemperatureFromTrajectories((ofstream *)&cout, mol->MDSteps-1, mol->MDSteps, (ofstream *)&cout);
604 break;
605 case 'g':
606 {
607 char filename[255];
608 cout << "Please enter filename: " << endl;
609 cin >> filename;
610 cout << Verbose(1) << "Storing temperatures in " << filename << "." << endl;
611 ofstream *output = new ofstream(filename, ios::trunc);
612 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output))
613 cout << Verbose(2) << "File could not be written." << endl;
614 else
615 cout << Verbose(2) << "File stored." << endl;
616 output->close();
617 delete(output);
618 }
619 break;
620 }
621};
622
623/** Submenu for measuring out the atoms in the molecule.
624 * \param *mol molecule with all the atoms
625 * \param *configuration configuration structure for the to be written config files of all fragments
626 */
627static void FragmentAtoms(molecule *mol, config *configuration)
628{
629 int Order1;
630 clock_t start, end;
631
632 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
633 cout << Verbose(0) << "What's the desired bond order: ";
634 cin >> Order1;
635 if (mol->first->next != mol->last) { // there are bonds
636 start = clock();
637 mol->FragmentMolecule((ofstream *)&cout, Order1, configuration);
638 end = clock();
639 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
640 } else
641 cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl;
642};
643
644/********************************************** Submenu routine **************************************/
645
646/** Submenu for manipulating atoms.
647 * \param *periode periodentafel
648 * \param *molecules list of molecules whose atoms are to be manipulated
649 */
650static void ManipulateAtoms(periodentafel *periode, MoleculeListClass *molecules, config *configuration)
651{
652 atom *first, *second;
653 molecule *mol = NULL;
654 Vector x,y,z,n; // coordinates for absolute point in cell volume
655 double *factor; // unit factor if desired
656 double bond, minBond;
657 char choice; // menu choice char
658 bool valid;
659
660 cout << Verbose(0) << "=========MANIPULATE ATOMS======================" << endl;
661 cout << Verbose(0) << "a - add an atom" << endl;
662 cout << Verbose(0) << "r - remove an atom" << endl;
663 cout << Verbose(0) << "b - scale a bond between atoms" << endl;
664 cout << Verbose(0) << "u - change an atoms element" << endl;
665 cout << Verbose(0) << "l - measure lengths, angles, ... for an atom" << endl;
666 cout << Verbose(0) << "all else - go back" << endl;
667 cout << Verbose(0) << "===============================================" << endl;
668 if (molecules->NumberOfActiveMolecules() > 1)
669 cout << Verbose(0) << "WARNING: There is more than one molecule active! Atoms will be added to each." << endl;
670 cout << Verbose(0) << "INPUT: ";
671 cin >> choice;
672
673 switch (choice) {
674 default:
675 cout << Verbose(0) << "Not a valid choice." << endl;
676 break;
677
678 case 'a': // add atom
679 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
680 if ((*ListRunner)->ActiveFlag) {
681 mol = *ListRunner;
682 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
683 AddAtoms(periode, mol);
684 }
685 break;
686
687 case 'b': // scale a bond
688 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
689 if ((*ListRunner)->ActiveFlag) {
690 mol = *ListRunner;
691 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
692 cout << Verbose(0) << "Scaling bond length between two atoms." << endl;
693 first = mol->AskAtom("Enter first (fixed) atom: ");
694 second = mol->AskAtom("Enter second (shifting) atom: ");
695 minBond = 0.;
696 for (int i=NDIM;i--;)
697 minBond += (first->x.x[i]-second->x.x[i])*(first->x.x[i] - second->x.x[i]);
698 minBond = sqrt(minBond);
699 cout << Verbose(0) << "Current Bond length between " << first->type->name << " Atom " << first->nr << " and " << second->type->name << " Atom " << second->nr << ": " << minBond << " a.u." << endl;
700 cout << Verbose(0) << "Enter new bond length [a.u.]: ";
701 cin >> bond;
702 for (int i=NDIM;i--;) {
703 second->x.x[i] -= (second->x.x[i]-first->x.x[i])/minBond*(minBond-bond);
704 }
705 //cout << Verbose(0) << "New coordinates of Atom " << second->nr << " are: ";
706 //second->Output(second->type->No, 1, (ofstream *)&cout);
707 }
708 break;
709
710 case 'c': // unit scaling of the metric
711 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
712 if ((*ListRunner)->ActiveFlag) {
713 mol = *ListRunner;
714 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
715 cout << Verbose(0) << "Angstroem -> Bohrradius: 1.8897261\t\tBohrradius -> Angstroem: 0.52917721" << endl;
716 cout << Verbose(0) << "Enter three factors: ";
717 factor = new double[NDIM];
718 cin >> factor[0];
719 cin >> factor[1];
720 cin >> factor[2];
721 valid = true;
722 mol->Scale(&factor);
723 delete[](factor);
724 }
725 break;
726
727 case 'l': // measure distances or angles
728 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
729 if ((*ListRunner)->ActiveFlag) {
730 mol = *ListRunner;
731 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
732 MeasureAtoms(periode, mol, configuration);
733 }
734 break;
735
736 case 'r': // remove atom
737 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
738 if ((*ListRunner)->ActiveFlag) {
739 mol = *ListRunner;
740 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
741 RemoveAtoms(mol);
742 }
743 break;
744
745 case 'u': // change an atom's element
746 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
747 if ((*ListRunner)->ActiveFlag) {
748 int Z;
749 mol = *ListRunner;
750 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
751 first = NULL;
752 do {
753 cout << Verbose(0) << "Change the element of which atom: ";
754 cin >> Z;
755 } while ((first = mol->FindAtom(Z)) == NULL);
756 cout << Verbose(0) << "New element by atomic number Z: ";
757 cin >> Z;
758 first->type = periode->FindElement(Z);
759 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl;
760 }
761 break;
762 }
763};
764
765/** Submenu for manipulating molecules.
766 * \param *periode periodentafel
767 * \param *molecules list of molecule to manipulate
768 */
769static void ManipulateMolecules(periodentafel *periode, MoleculeListClass *molecules, config *configuration)
770{
771 atom *first = NULL;
772 Vector x,y,z,n; // coordinates for absolute point in cell volume
773 int j, axis, count, faktor;
774 char choice; // menu choice char
775 molecule *mol = NULL;
776 element **Elements;
777 Vector **vectors;
778 MoleculeLeafClass *Subgraphs = NULL;
779
780 cout << Verbose(0) << "=========MANIPULATE GLOBALLY===================" << endl;
781 cout << Verbose(0) << "c - scale by unit transformation" << endl;
782 cout << Verbose(0) << "d - duplicate molecule/periodic cell" << endl;
783 cout << Verbose(0) << "f - fragment molecule many-body bond order style" << endl;
784 cout << Verbose(0) << "g - center atoms in box" << endl;
785 cout << Verbose(0) << "i - realign molecule" << endl;
786 cout << Verbose(0) << "m - mirror all molecules" << endl;
787 cout << Verbose(0) << "o - create connection matrix" << endl;
788 cout << Verbose(0) << "t - translate molecule by vector" << endl;
789 cout << Verbose(0) << "all else - go back" << endl;
790 cout << Verbose(0) << "===============================================" << endl;
791 if (molecules->NumberOfActiveMolecules() > 1)
792 cout << Verbose(0) << "WARNING: There is more than one molecule active! Atoms will be added to each." << endl;
793 cout << Verbose(0) << "INPUT: ";
794 cin >> choice;
795
796 switch (choice) {
797 default:
798 cout << Verbose(0) << "Not a valid choice." << endl;
799 break;
800
801 case 'd': // duplicate the periodic cell along a given axis, given times
802 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
803 if ((*ListRunner)->ActiveFlag) {
804 mol = *ListRunner;
805 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
806 cout << Verbose(0) << "State the axis [(+-)123]: ";
807 cin >> axis;
808 cout << Verbose(0) << "State the factor: ";
809 cin >> faktor;
810
811 mol->CountAtoms((ofstream *)&cout); // recount atoms
812 if (mol->AtomCount != 0) { // if there is more than none
813 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand
814 Elements = new element *[count];
815 vectors = new Vector *[count];
816 j = 0;
817 first = mol->start;
818 while (first->next != mol->end) { // make a list of all atoms with coordinates and element
819 first = first->next;
820 Elements[j] = first->type;
821 vectors[j] = &first->x;
822 j++;
823 }
824 if (count != j)
825 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;
826 x.Zero();
827 y.Zero();
828 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
829 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times
830 x.AddVector(&y); // per factor one cell width further
831 for (int k=count;k--;) { // go through every atom of the original cell
832 first = new atom(); // create a new body
833 first->x.CopyVector(vectors[k]); // use coordinate of original atom
834 first->x.AddVector(&x); // translate the coordinates
835 first->type = Elements[k]; // insert original element
836 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)
837 }
838 }
839 if (mol->first->next != mol->last) // if connect matrix is present already, redo it
840 mol->CreateAdjacencyList((ofstream *)&cout, mol->BondDistance, configuration->GetIsAngstroem());
841 // free memory
842 delete[](Elements);
843 delete[](vectors);
844 // correct cell size
845 if (axis < 0) { // if sign was negative, we have to translate everything
846 x.Zero();
847 x.AddVector(&y);
848 x.Scale(-(faktor-1));
849 mol->Translate(&x);
850 }
851 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;
852 }
853 }
854 break;
855
856 case 'f':
857 FragmentAtoms(mol, configuration);
858 break;
859
860 case 'g': // center the atoms
861 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
862 if ((*ListRunner)->ActiveFlag) {
863 mol = *ListRunner;
864 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
865 CenterAtoms(mol);
866 }
867 break;
868
869 case 'i': // align all atoms
870 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
871 if ((*ListRunner)->ActiveFlag) {
872 mol = *ListRunner;
873 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
874 AlignAtoms(periode, mol);
875 }
876 break;
877
878 case 'm': // mirror atoms along a given axis
879 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
880 if ((*ListRunner)->ActiveFlag) {
881 mol = *ListRunner;
882 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
883 MirrorAtoms(mol);
884 }
885 break;
886
887 case 'o': // create the connection matrix
888 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
889 if ((*ListRunner)->ActiveFlag) {
890 mol = *ListRunner;
891 double bonddistance;
892 clock_t start,end;
893 cout << Verbose(0) << "What's the maximum bond distance: ";
894 cin >> bonddistance;
895 start = clock();
896 mol->CreateAdjacencyList((ofstream *)&cout, bonddistance, configuration->GetIsAngstroem());
897 mol->CreateListOfBondsPerAtom((ofstream *)&cout);
898 end = clock();
899 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
900 }
901 break;
902
903 case 't': // translate all atoms
904 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
905 if ((*ListRunner)->ActiveFlag) {
906 mol = *ListRunner;
907 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
908 cout << Verbose(0) << "Enter translation vector." << endl;
909 x.AskPosition(mol->cell_size,0);
910 mol->Center.AddVector((const Vector *)&x);
911 }
912 break;
913 }
914 // Free all
915 if (Subgraphs != NULL) { // free disconnected subgraph list of DFS analysis was performed
916 while (Subgraphs->next != NULL) {
917 Subgraphs = Subgraphs->next;
918 delete(Subgraphs->previous);
919 }
920 delete(Subgraphs);
921 }
922};
923
924
925/** Submenu for creating new molecules.
926 * \param *periode periodentafel
927 * \param *molecules list of molecules to add to
928 */
929static void EditMolecules(periodentafel *periode, MoleculeListClass *molecules)
930{
931 char choice; // menu choice char
932 Vector center;
933 int nr, count;
934 molecule *mol = NULL;
935
936 cout << Verbose(0) << "==========EDIT MOLECULES=====================" << endl;
937 cout << Verbose(0) << "c - create new molecule" << endl;
938 cout << Verbose(0) << "l - load molecule from xyz file" << endl;
939 cout << Verbose(0) << "n - change molecule's name" << endl;
940 cout << Verbose(0) << "N - give molecules filename" << endl;
941 cout << Verbose(0) << "p - parse atoms in xyz file into molecule" << endl;
942 cout << Verbose(0) << "r - remove a molecule" << endl;
943 cout << Verbose(0) << "all else - go back" << endl;
944 cout << Verbose(0) << "===============================================" << endl;
945 cout << Verbose(0) << "INPUT: ";
946 cin >> choice;
947
948 switch (choice) {
949 default:
950 cout << Verbose(0) << "Not a valid choice." << endl;
951 break;
952 case 'c':
953 mol = new molecule(periode);
954 molecules->insert(mol);
955 break;
956
957 case 'l': // load from XYZ file
958 {
959 char filename[MAXSTRINGSIZE];
960 cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
961 mol = new molecule(periode);
962 do {
963 cout << Verbose(0) << "Enter file name: ";
964 cin >> filename;
965 } while (!mol->AddXYZFile(filename));
966 mol->SetNameFromFilename(filename);
967 // center at set box dimensions
968 mol->CenterEdge((ofstream *)&cout, &center);
969 mol->cell_size[0] = center.x[0];
970 mol->cell_size[1] = 0;
971 mol->cell_size[2] = center.x[1];
972 mol->cell_size[3] = 0;
973 mol->cell_size[4] = 0;
974 mol->cell_size[5] = center.x[2];
975 molecules->insert(mol);
976 }
977 break;
978
979 case 'n':
980 {
981 char filename[MAXSTRINGSIZE];
982 do {
983 cout << Verbose(0) << "Enter index of molecule: ";
984 cin >> nr;
985 mol = molecules->ReturnIndex(nr);
986 } while (mol == NULL);
987 cout << Verbose(0) << "Enter name: ";
988 cin >> filename;
989 strcpy(mol->name, filename);
990 }
991 break;
992
993 case 'N':
994 {
995 char filename[MAXSTRINGSIZE];
996 do {
997 cout << Verbose(0) << "Enter index of molecule: ";
998 cin >> nr;
999 mol = molecules->ReturnIndex(nr);
1000 } while (mol == NULL);
1001 cout << Verbose(0) << "Enter name: ";
1002 cin >> filename;
1003 mol->SetNameFromFilename(filename);
1004 }
1005 break;
1006
1007 case 'p': // parse XYZ file
1008 {
1009 char filename[MAXSTRINGSIZE];
1010 mol = NULL;
1011 do {
1012 cout << Verbose(0) << "Enter index of molecule: ";
1013 cin >> nr;
1014 mol = molecules->ReturnIndex(nr);
1015 } while (mol == NULL);
1016 cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
1017 do {
1018 cout << Verbose(0) << "Enter file name: ";
1019 cin >> filename;
1020 } while (!mol->AddXYZFile(filename));
1021 mol->SetNameFromFilename(filename);
1022 }
1023 break;
1024
1025 case 'r':
1026 cout << Verbose(0) << "Enter index of molecule: ";
1027 cin >> nr;
1028 count = 1;
1029 for(MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
1030 if (nr == (*ListRunner)->IndexNr) {
1031 mol = *ListRunner;
1032 molecules->ListOfMolecules.erase(ListRunner);
1033 delete(mol);
1034 break;
1035 }
1036 break;
1037 }
1038};
1039
1040
1041/** Submenu for merging molecules.
1042 * \param *periode periodentafel
1043 * \param *molecules list of molecules to add to
1044 */
1045static void MergeMolecules(periodentafel *periode, MoleculeListClass *molecules)
1046{
1047 char choice; // menu choice char
1048
1049 cout << Verbose(0) << "===========MERGE MOLECULES=====================" << endl;
1050 cout << Verbose(0) << "a - simple add of one molecule to another" << endl;
1051 cout << Verbose(0) << "e - embedding merge of two molecules" << endl;
1052 cout << Verbose(0) << "m - multi-merge of all molecules" << endl;
1053 cout << Verbose(0) << "s - scatter merge of two molecules" << endl;
1054 cout << Verbose(0) << "t - simple merge of two molecules" << endl;
1055 cout << Verbose(0) << "all else - go back" << endl;
1056 cout << Verbose(0) << "===============================================" << endl;
1057 cout << Verbose(0) << "INPUT: ";
1058 cin >> choice;
1059
1060 switch (choice) {
1061 default:
1062 cout << Verbose(0) << "Not a valid choice." << endl;
1063 break;
1064
1065 case 'a':
1066 {
1067 int src, dest;
1068 molecule *srcmol = NULL, *destmol = NULL;
1069 {
1070 do {
1071 cout << Verbose(0) << "Enter index of destination molecule: ";
1072 cin >> dest;
1073 destmol = molecules->ReturnIndex(dest);
1074 } while ((destmol == NULL) && (dest != -1));
1075 do {
1076 cout << Verbose(0) << "Enter index of source molecule to add from: ";
1077 cin >> src;
1078 srcmol = molecules->ReturnIndex(src);
1079 } while ((srcmol == NULL) && (src != -1));
1080 if ((src != -1) && (dest != -1))
1081 molecules->SimpleAdd(srcmol, destmol);
1082 }
1083 }
1084 break;
1085
1086 case 'e':
1087 {
1088 int src, dest;
1089 molecule *srcmol = NULL, *destmol = NULL;
1090 do {
1091 cout << Verbose(0) << "Enter index of matrix molecule (the variable one): ";
1092 cin >> src;
1093 srcmol = molecules->ReturnIndex(src);
1094 } while ((srcmol == NULL) && (src != -1));
1095 do {
1096 cout << Verbose(0) << "Enter index of molecule to merge into (the fixed one): ";
1097 cin >> dest;
1098 destmol = molecules->ReturnIndex(dest);
1099 } while ((destmol == NULL) && (dest != -1));
1100 if ((src != -1) && (dest != -1))
1101 molecules->EmbedMerge(destmol, srcmol);
1102 }
1103 break;
1104
1105 case 'm':
1106 {
1107 int nr;
1108 molecule *mol = NULL;
1109 do {
1110 cout << Verbose(0) << "Enter index of molecule to merge into: ";
1111 cin >> nr;
1112 mol = molecules->ReturnIndex(nr);
1113 } while ((mol == NULL) && (nr != -1));
1114 if (nr != -1) {
1115 int N = molecules->ListOfMolecules.size()-1;
1116 int *src = new int(N);
1117 for(MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
1118 if ((*ListRunner)->IndexNr != nr)
1119 src[N++] = (*ListRunner)->IndexNr;
1120 molecules->SimpleMultiMerge(mol, src, N);
1121 delete[](src);
1122 }
1123 }
1124 break;
1125
1126 case 's':
1127 cout << Verbose(0) << "Not implemented yet." << endl;
1128 break;
1129
1130 case 't':
1131 {
1132 int src, dest;
1133 molecule *srcmol = NULL, *destmol = NULL;
1134 {
1135 do {
1136 cout << Verbose(0) << "Enter index of destination molecule: ";
1137 cin >> dest;
1138 destmol = molecules->ReturnIndex(dest);
1139 } while ((destmol == NULL) && (dest != -1));
1140 do {
1141 cout << Verbose(0) << "Enter index of source molecule to merge into: ";
1142 cin >> src;
1143 srcmol = molecules->ReturnIndex(src);
1144 } while ((srcmol == NULL) && (src != -1));
1145 if ((src != -1) && (dest != -1))
1146 molecules->SimpleMerge(srcmol, destmol);
1147 }
1148 }
1149 break;
1150 }
1151};
1152
1153
1154/********************************************** Test routine **************************************/
1155
1156/** Is called always as option 'T' in the menu.
1157 * \param *molecules list of molecules
1158 */
1159static void testroutine(MoleculeListClass *molecules)
1160{
1161 // the current test routine checks the functionality of the KeySet&Graph concept:
1162 // We want to have a multiindex (the KeySet) describing a unique subgraph
1163 int i, comp, counter=0;
1164
1165 // create a clone
1166 molecule *mol = NULL;
1167 if (molecules->ListOfMolecules.size() != 0) // clone
1168 mol = (molecules->ListOfMolecules.front())->CopyMolecule();
1169 else {
1170 cerr << "I don't have anything to test on ... ";
1171 return;
1172 }
1173 atom *Walker = mol->start;
1174
1175 // generate some KeySets
1176 cout << "Generating KeySets." << endl;
1177 KeySet TestSets[mol->AtomCount+1];
1178 i=1;
1179 while (Walker->next != mol->end) {
1180 Walker = Walker->next;
1181 for (int j=0;j<i;j++) {
1182 TestSets[j].insert(Walker->nr);
1183 }
1184 i++;
1185 }
1186 cout << "Testing insertion of already present item in KeySets." << endl;
1187 KeySetTestPair test;
1188 test = TestSets[mol->AtomCount-1].insert(Walker->nr);
1189 if (test.second) {
1190 cout << Verbose(1) << "Insertion worked?!" << endl;
1191 } else {
1192 cout << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl;
1193 }
1194 TestSets[mol->AtomCount].insert(mol->end->previous->nr);
1195 TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr);
1196
1197 // constructing Graph structure
1198 cout << "Generating Subgraph class." << endl;
1199 Graph Subgraphs;
1200
1201 // insert KeySets into Subgraphs
1202 cout << "Inserting KeySets into Subgraph class." << endl;
1203 for (int j=0;j<mol->AtomCount;j++) {
1204 Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.)));
1205 }
1206 cout << "Testing insertion of already present item in Subgraph." << endl;
1207 GraphTestPair test2;
1208 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.)));
1209 if (test2.second) {
1210 cout << Verbose(1) << "Insertion worked?!" << endl;
1211 } else {
1212 cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl;
1213 }
1214
1215 // show graphs
1216 cout << "Showing Subgraph's contents, checking that it's sorted." << endl;
1217 Graph::iterator A = Subgraphs.begin();
1218 while (A != Subgraphs.end()) {
1219 cout << (*A).second.first << ": ";
1220 KeySet::iterator key = (*A).first.begin();
1221 comp = -1;
1222 while (key != (*A).first.end()) {
1223 if ((*key) > comp)
1224 cout << (*key) << " ";
1225 else
1226 cout << (*key) << "! ";
1227 comp = (*key);
1228 key++;
1229 }
1230 cout << endl;
1231 A++;
1232 }
1233 delete(mol);
1234};
1235
1236/** Tries given filename or standard on saving the config file.
1237 * \param *ConfigFileName name of file
1238 * \param *configuration pointer to configuration structure with all the values
1239 * \param *periode pointer to periodentafel structure with all the elements
1240 * \param *molecules list of molecules structure with all the atoms and coordinates
1241 */
1242static void SaveConfig(char *ConfigFileName, config *configuration, periodentafel *periode, MoleculeListClass *molecules)
1243{
1244 char filename[MAXSTRINGSIZE];
1245 ofstream output;
1246 molecule *mol = new molecule(periode);
1247
1248 // translate each to its center and merge all molecules in MoleculeListClass into this molecule
1249 int N = molecules->ListOfMolecules.size();
1250 int *src = new int(N);
1251 N=0;
1252 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
1253 src[N++] = (*ListRunner)->IndexNr;
1254 (*ListRunner)->Translate(&(*ListRunner)->Center);
1255 }
1256 molecules->SimpleMultiAdd(mol, src, N);
1257 delete(src);
1258
1259 // ... and translate back
1260 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
1261 (*ListRunner)->Center.Scale(-1.);
1262 (*ListRunner)->Translate(&(*ListRunner)->Center);
1263 (*ListRunner)->Center.Scale(-1.);
1264 }
1265
1266 cout << Verbose(0) << "Storing configuration ... " << endl;
1267 // get correct valence orbitals
1268 mol->CalculateOrbitals(*configuration);
1269 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble;
1270 if (ConfigFileName != NULL) { // test the file name
1271 strcpy(filename, ConfigFileName);
1272 output.open(filename, ios::trunc);
1273 } else if (strlen(configuration->configname) != 0) {
1274 strcpy(filename, configuration->configname);
1275 output.open(configuration->configname, ios::trunc);
1276 } else {
1277 strcpy(filename, DEFAULTCONFIG);
1278 output.open(DEFAULTCONFIG, ios::trunc);
1279 }
1280 output.close();
1281 output.clear();
1282 cout << Verbose(0) << "Saving of config file ";
1283 if (configuration->Save(filename, periode, mol))
1284 cout << "successful." << endl;
1285 else
1286 cout << "failed." << endl;
1287
1288 // and save to xyz file
1289 if (ConfigFileName != NULL) {
1290 strcpy(filename, ConfigFileName);
1291 strcat(filename, ".xyz");
1292 output.open(filename, ios::trunc);
1293 }
1294 if (output == NULL) {
1295 strcpy(filename,"main_pcp_linux");
1296 strcat(filename, ".xyz");
1297 output.open(filename, ios::trunc);
1298 }
1299 cout << Verbose(0) << "Saving of XYZ file ";
1300 if (mol->MDSteps <= 1) {
1301 if (mol->OutputXYZ(&output))
1302 cout << "successful." << endl;
1303 else
1304 cout << "failed." << endl;
1305 } else {
1306 if (mol->OutputTrajectoriesXYZ(&output))
1307 cout << "successful." << endl;
1308 else
1309 cout << "failed." << endl;
1310 }
1311 output.close();
1312 output.clear();
1313
1314 // and save as MPQC configuration
1315 if (ConfigFileName != NULL)
1316 strcpy(filename, ConfigFileName);
1317 if (output == NULL)
1318 strcpy(filename,"main_pcp_linux");
1319 cout << Verbose(0) << "Saving as mpqc input ";
1320 if (configuration->SaveMPQC(filename, mol))
1321 cout << "done." << endl;
1322 else
1323 cout << "failed." << endl;
1324
1325 if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) {
1326 cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl;
1327 }
1328 delete(mol);
1329};
1330
1331/** Parses the command line options.
1332 * \param argc argument count
1333 * \param **argv arguments array
1334 * \param *molecules list of molecules structure
1335 * \param *periode elements structure
1336 * \param configuration config file structure
1337 * \param *ConfigFileName pointer to config file name in **argv
1338 * \param *PathToDatabases pointer to db's path in **argv
1339 * \return exit code (0 - successful, all else - something's wrong)
1340 */
1341static int ParseCommandLineOptions(int argc, char **argv, MoleculeListClass *&molecules, periodentafel *&periode, config& configuration, char *&ConfigFileName)
1342{
1343 Vector x,y,z,n; // coordinates for absolute point in cell volume
1344 double *factor; // unit factor if desired
1345 ifstream test;
1346 ofstream output;
1347 string line;
1348 atom *first;
1349 bool SaveFlag = false;
1350 int ExitFlag = 0;
1351 int j;
1352 double volume = 0.;
1353 enum ConfigStatus configPresent = absent;
1354 clock_t start,end;
1355 int argptr;
1356 molecule *mol = NULL;
1357 strncpy(configuration.databasepath, LocalPath, MAXSTRINGSIZE-1);
1358
1359 if (argc > 1) { // config file specified as option
1360 // 1. : Parse options that just set variables or print help
1361 argptr = 1;
1362 do {
1363 if (argv[argptr][0] == '-') {
1364 cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n";
1365 argptr++;
1366 switch(argv[argptr-1][1]) {
1367 case 'h':
1368 case 'H':
1369 case '?':
1370 cout << "MoleCuilder suite" << endl << "==================" << endl << endl;
1371 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl;
1372 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl;
1373 cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl;
1374 cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl;
1375 cout << "\t-b xx xy xz yy yz zz\tCenter atoms in domain with given symmetric matrix of (xx,xy,xz,yy,yz,zz)." << endl;
1376 cout << "\t-B xx xy xz yy yz zz\tBound atoms by domain with given symmetric matrix of (xx,xy,xz,yy,yz,zz)." << endl;
1377 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl;
1378 cout << "\t-C\tPair Correlation analysis." << endl;
1379 cout << "\t-d x1 x2 x3\tDuplicate cell along each axis by given factor." << endl;
1380 cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl;
1381 cout << "\t-e <file>\tSets the databases path to be parsed (default: ./)." << endl;
1382 cout << "\t-E <id> <Z>\tChange atom <id>'s element to <Z>, <id> begins at 0." << endl;
1383 cout << "\t-f/F <dist> <order>\tFragments the molecule in BOSSANOVA manner (with/out rings compressed) and stores config files in same dir as config (return code 0 - fragmented, 2 - no fragmentation necessary)." << endl;
1384 cout << "\t-h/-H/-?\tGive this help screen." << endl;
1385 cout << "\t-L <step0> <step1> <prefix>\tStore a linear interpolation between two configurations <step0> and <step1> into single config files with prefix <prefix> and as Trajectories into the current config file." << endl;
1386 cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl;
1387 cout << "\t-M <basis>\tSetting basis to store to MPQC config files." << endl;
1388 cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl;
1389 cout << "\t-N <radius> <file>\tGet non-convex-envelope." << endl;
1390 cout << "\t-o <out>\tGet volume of the convex envelope (and store to tecplot file)." << endl;
1391 cout << "\t-O\tCenter atoms in origin." << endl;
1392 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;
1393 cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl;
1394 cout << "\t-r <id>\t\tRemove an atom with given id." << endl;
1395 cout << "\t-R <id> <radius>\t\tRemove all atoms out of sphere around a given one." << endl;
1396 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl;
1397 cout << "\t-S <file> Store temperatures from the config file in <file>." << endl;
1398 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl;
1399 cout << "\t-T x1 x2 x3\tTranslate periodically all atoms by this vector (x1,x2,x3)." << endl;
1400 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl;
1401 cout << "\t-v/-V\t\tGives version information." << endl;
1402 cout << "Note: config files must not begin with '-' !" << endl;
1403 return (1);
1404 break;
1405 case 'v':
1406 case 'V':
1407 cout << argv[0] << " " << VERSIONSTRING << endl;
1408 cout << "Build your own molecule position set." << endl;
1409 return (1);
1410 break;
1411 case 'e':
1412 if ((argptr >= argc) || (argv[argptr][0] == '-')) {
1413 cerr << "Not enough or invalid arguments for specifying element db: -e <db file>" << endl;
1414 } else {
1415 cout << "Using " << argv[argptr] << " as elements database." << endl;
1416 strncpy (configuration.databasepath, argv[argptr], MAXSTRINGSIZE-1);
1417 argptr+=1;
1418 }
1419 break;
1420 case 'n':
1421 cout << "I won't parse trajectories." << endl;
1422 configuration.FastParsing = true;
1423 break;
1424 default: // no match? Step on
1425 argptr++;
1426 break;
1427 }
1428 } else
1429 argptr++;
1430 } while (argptr < argc);
1431
1432 // 2. Parse the element database
1433 if (periode->LoadPeriodentafel(configuration.databasepath)) {
1434 cout << Verbose(0) << "Element list loaded successfully." << endl;
1435 //periode->Output((ofstream *)&cout);
1436 } else {
1437 cout << Verbose(0) << "Element list loading failed." << endl;
1438 return 1;
1439 }
1440 // 3. Find config file name and parse if possible
1441 if (argv[1][0] != '-') {
1442 // simply create a new molecule, wherein the config file is loaded and the manipulation takes place
1443 mol = new molecule(periode);
1444 mol->ActiveFlag = true;
1445 molecules->insert(mol);
1446
1447 cout << Verbose(0) << "Config file given." << endl;
1448 test.open(argv[1], ios::in);
1449 if (test == NULL) {
1450 //return (1);
1451 output.open(argv[1], ios::out);
1452 if (output == NULL) {
1453 cout << Verbose(1) << "Specified config file " << argv[1] << " not found." << endl;
1454 configPresent = absent;
1455 } else {
1456 cout << "Empty configuration file." << endl;
1457 ConfigFileName = argv[1];
1458 configPresent = empty;
1459 output.close();
1460 }
1461 } else {
1462 test.close();
1463 ConfigFileName = argv[1];
1464 cout << Verbose(1) << "Specified config file found, parsing ... ";
1465 switch (configuration.TestSyntax(ConfigFileName, periode, mol)) {
1466 case 1:
1467 cout << "new syntax." << endl;
1468 configuration.Load(ConfigFileName, periode, mol);
1469 configPresent = present;
1470 break;
1471 case 0:
1472 cout << "old syntax." << endl;
1473 configuration.LoadOld(ConfigFileName, periode, mol);
1474 configPresent = present;
1475 break;
1476 default:
1477 cout << "Unknown syntax or empty, yet present file." << endl;
1478 configPresent = empty;
1479 }
1480 }
1481 } else
1482 configPresent = absent;
1483 // 4. parse again through options, now for those depending on elements db and config presence
1484 argptr = 1;
1485 do {
1486 cout << "Current Command line argument: " << argv[argptr] << "." << endl;
1487 if (argv[argptr][0] == '-') {
1488 argptr++;
1489 if ((configPresent == present) || (configPresent == empty)) {
1490 switch(argv[argptr-1][1]) {
1491 case 'p':
1492 if (ExitFlag == 0) ExitFlag = 1;
1493 if ((argptr >= argc) || (argv[argptr][0] == '-')) {
1494 ExitFlag = 255;
1495 cerr << "Not enough arguments for parsing: -p <xyz file>" << endl;
1496 } else {
1497 SaveFlag = true;
1498 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl;
1499 if (!mol->AddXYZFile(argv[argptr]))
1500 cout << Verbose(2) << "File not found." << endl;
1501 else {
1502 cout << Verbose(2) << "File found and parsed." << endl;
1503 configPresent = present;
1504 }
1505 }
1506 break;
1507 case 'a':
1508 if (ExitFlag == 0) ExitFlag = 1;
1509 if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr+1]))) {
1510 ExitFlag = 255;
1511 cerr << "Not enough or invalid arguments for adding atom: -a <element> <x> <y> <z>" << endl;
1512 } else {
1513 SaveFlag = true;
1514 cout << Verbose(1) << "Adding new atom with element " << argv[argptr] << " at (" << argv[argptr+1] << "," << argv[argptr+2] << "," << argv[argptr+3] << "), ";
1515 first = new atom;
1516 first->type = periode->FindElement(atoi(argv[argptr]));
1517 if (first->type != NULL)
1518 cout << Verbose(2) << "found element " << first->type->name << endl;
1519 for (int i=NDIM;i--;)
1520 first->x.x[i] = atof(argv[argptr+1+i]);
1521 if (first->type != NULL) {
1522 mol->AddAtom(first); // add to molecule
1523 if ((configPresent == empty) && (mol->AtomCount != 0))
1524 configPresent = present;
1525 } else
1526 cerr << Verbose(1) << "Could not find the specified element." << endl;
1527 argptr+=4;
1528 }
1529 break;
1530 default: // no match? Don't step on (this is done in next switch's default)
1531 break;
1532 }
1533 }
1534 if (configPresent == present) {
1535 switch(argv[argptr-1][1]) {
1536 case 'M':
1537 if ((argptr >= argc) || (argv[argptr][0] == '-')) {
1538 ExitFlag = 255;
1539 cerr << "Not enough or invalid arguments given for setting MPQC basis: -B <basis name>" << endl;
1540 } else {
1541 configuration.basis = argv[argptr];
1542 cout << Verbose(1) << "Setting MPQC basis to " << configuration.basis << "." << endl;
1543 argptr+=1;
1544 }
1545 break;
1546 case 'D':
1547 if (ExitFlag == 0) ExitFlag = 1;
1548 {
1549 cout << Verbose(1) << "Depth-First-Search Analysis." << endl;
1550 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis
1551 int *MinimumRingSize = new int[mol->AtomCount];
1552 atom ***ListOfLocalAtoms = NULL;
1553 int FragmentCounter = 0;
1554 class StackClass<bond *> *BackEdgeStack = NULL;
1555 class StackClass<bond *> *LocalBackEdgeStack = NULL;
1556 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr]), configuration.GetIsAngstroem());
1557 mol->CreateListOfBondsPerAtom((ofstream *)&cout);
1558 Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack);
1559 if (Subgraphs != NULL) {
1560 Subgraphs->next->FillBondStructureFromReference((ofstream *)&cout, mol, (FragmentCounter = 0), ListOfLocalAtoms, false); // we want to keep the created ListOfLocalAtoms
1561 while (Subgraphs->next != NULL) {
1562 Subgraphs = Subgraphs->next;
1563 LocalBackEdgeStack = new StackClass<bond *> (Subgraphs->Leaf->BondCount);
1564 Subgraphs->Leaf->PickLocalBackEdges((ofstream *)&cout, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);
1565 Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize);
1566 delete(LocalBackEdgeStack);
1567 delete(Subgraphs->previous);
1568 }
1569 delete(Subgraphs);
1570 for (int i=0;i<FragmentCounter;i++)
1571 Free(&ListOfLocalAtoms[FragmentCounter]);
1572 Free(&ListOfLocalAtoms);
1573 }
1574 delete(BackEdgeStack);
1575 delete[](MinimumRingSize);
1576 }
1577 //argptr+=1;
1578 break;
1579 case 'C':
1580 if (ExitFlag == 0) ExitFlag = 1;
1581 if ((argptr+1 >= argc) || (argv[argptr+1][0] == '-') || (argv[argptr+2][0] == '-')) {
1582 ExitFlag = 255;
1583 cerr << "Not enough or invalid arguments given for pair correlation analysis: -C <output> <bin output>" << endl;
1584 } else {
1585 SaveFlag = false;
1586 ofstream output(argv[argptr]);
1587 ofstream binoutput(argv[argptr+1]);
1588 class Tesselation T;
1589 const double radius = 5.;
1590 LinkedCell LCList(mol, 2.*radius);
1591 element *oxygen = periode->FindElement(8);
1592 FindNonConvexBorder((ofstream *)&cout, mol, &LCList, radius, NULL);
1593 CorrelationToSurfaceMap *surfacemap = CorrelationToSurface( (ofstream *)&cout, mol, oxygen, mol->TesselStruct, &LCList );
1594 BinPairMap *binmap = BinData( (ofstream *)&cout, surfacemap, 0.5, 0., 0. );
1595 OutputCorrelation ( &binoutput, binmap );
1596 output.close();
1597 binoutput.close();
1598 argptr+=2;
1599 }
1600 break;
1601 case 'E':
1602 if (ExitFlag == 0) ExitFlag = 1;
1603 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr+1][0] == '-')) {
1604 ExitFlag = 255;
1605 cerr << "Not enough or invalid arguments given for changing element: -E <atom nr.> <element>" << endl;
1606 } else {
1607 SaveFlag = true;
1608 cout << Verbose(1) << "Changing atom " << argv[argptr] << " to element " << argv[argptr+1] << "." << endl;
1609 first = mol->FindAtom(atoi(argv[argptr]));
1610 first->type = periode->FindElement(atoi(argv[argptr+1]));
1611 argptr+=2;
1612 }
1613 break;
1614 case 'F':
1615 if (ExitFlag == 0) ExitFlag = 1;
1616 if (argptr+5 >=argc) {
1617 ExitFlag = 255;
1618 cerr << "Not enough or invalid arguments given for filling box with water: -F <dist_x> <dist_y> <dist_z> <randatom> <randmol> <DoRotate>" << endl;
1619 } else {
1620 SaveFlag = true;
1621 cout << Verbose(1) << "Filling Box with water molecules." << endl;
1622 // construct water molecule
1623 molecule *filler = new molecule(periode);;
1624 molecule *Filling = NULL;
1625 atom *second = NULL, *third = NULL;
1626 first = new atom();
1627 first->type = periode->FindElement(1);
1628 first->x.Init(0.441, -0.143, 0.);
1629 filler->AddAtom(first);
1630 second = new atom();
1631 second->type = periode->FindElement(1);
1632 second->x.Init(-0.464, 1.137, 0.0);
1633 filler->AddAtom(second);
1634 third = new atom();
1635 third->type = periode->FindElement(8);
1636 third->x.Init(-0.464, 0.177, 0.);
1637 filler->AddAtom(third);
1638 filler->AddBond(first, third, 1);
1639 filler->AddBond(second, third, 1);
1640 // call routine
1641 double distance[NDIM];
1642 for (int i=0;i<NDIM;i++)
1643 distance[i] = atof(argv[argptr+i]);
1644 Filling = FillBoxWithMolecule((ofstream *)&cout, molecules, filler, configuration, distance, atof(argv[argptr+3]), atof(argv[argptr+4]), atoi(argv[argptr+5]));
1645 if (Filling != NULL) {
1646 molecules->insert(Filling);
1647 }
1648 delete(filler);
1649 argptr+=6;
1650 }
1651 break;
1652 case 'A':
1653 if (ExitFlag == 0) ExitFlag = 1;
1654 if ((argptr >= argc) || (argv[argptr][0] == '-')) {
1655 ExitFlag =255;
1656 cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl;
1657 } else {
1658 cout << "Parsing bonds from " << argv[argptr] << "." << endl;
1659 ifstream *input = new ifstream(argv[argptr]);
1660 mol->CreateAdjacencyList2((ofstream *)&cout, input);
1661 input->close();
1662 argptr+=1;
1663 }
1664 break;
1665 case 'N':
1666 if (ExitFlag == 0) ExitFlag = 1;
1667 if ((argptr+1 >= argc) || (argv[argptr+1][0] == '-')){
1668 ExitFlag = 255;
1669 cerr << "Not enough or invalid arguments given for non-convex envelope: -o <radius> <tecplot output file>" << endl;
1670 } else {
1671 class Tesselation T;
1672 string filename(argv[argptr+1]);
1673 filename.append(".csv");
1674 cout << Verbose(0) << "Evaluating non-convex envelope.";
1675 cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl;
1676 start = clock();
1677 LinkedCell LCList(mol, atof(argv[argptr])*2.);
1678 FindNonConvexBorder((ofstream *)&cout, mol, &LCList, atof(argv[argptr]), argv[argptr+1]);
1679 //FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str());
1680 end = clock();
1681 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
1682 argptr+=2;
1683 }
1684 break;
1685 case 'S':
1686 if (ExitFlag == 0) ExitFlag = 1;
1687 if ((argptr >= argc) || (argv[argptr][0] == '-')) {
1688 ExitFlag = 255;
1689 cerr << "Not enough or invalid arguments given for storing tempature: -S <temperature file>" << endl;
1690 } else {
1691 cout << Verbose(1) << "Storing temperatures in " << argv[argptr] << "." << endl;
1692 ofstream *output = new ofstream(argv[argptr], ios::trunc);
1693 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output))
1694 cout << Verbose(2) << "File could not be written." << endl;
1695 else
1696 cout << Verbose(2) << "File stored." << endl;
1697 output->close();
1698 delete(output);
1699 argptr+=1;
1700 }
1701 break;
1702 case 'L':
1703 if (ExitFlag == 0) ExitFlag = 1;
1704 if ((argptr >= argc) || (argv[argptr][0] == '-')) {
1705 ExitFlag = 255;
1706 cerr << "Not enough or invalid arguments given for storing tempature: -L <step0> <step1> <prefix> <identity mapping?>" << endl;
1707 } else {
1708 SaveFlag = true;
1709 cout << Verbose(1) << "Linear interpolation between configuration " << argv[argptr] << " and " << argv[argptr+1] << "." << endl;
1710 if (atoi(argv[argptr+3]) == 1)
1711 cout << Verbose(1) << "Using Identity for the permutation map." << endl;
1712 if (!mol->LinearInterpolationBetweenConfiguration((ofstream *)&cout, atoi(argv[argptr]), atoi(argv[argptr+1]), argv[argptr+2], configuration, atoi(argv[argptr+3])) == 1 ? true : false)
1713 cout << Verbose(2) << "Could not store " << argv[argptr+2] << " files." << endl;
1714 else
1715 cout << Verbose(2) << "Steps created and " << argv[argptr+2] << " files stored." << endl;
1716 argptr+=4;
1717 }
1718 break;
1719 case 'P':
1720 if (ExitFlag == 0) ExitFlag = 1;
1721 if ((argptr >= argc) || (argv[argptr][0] == '-')) {
1722 ExitFlag = 255;
1723 cerr << "Not enough or invalid arguments given for parsing and integrating forces: -P <forces file>" << endl;
1724 } else {
1725 SaveFlag = true;
1726 cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl;
1727 if (!mol->VerletForceIntegration((ofstream *)&cout, argv[argptr], configuration))
1728 cout << Verbose(2) << "File not found." << endl;
1729 else
1730 cout << Verbose(2) << "File found and parsed." << endl;
1731 argptr+=1;
1732 }
1733 break;
1734 case 'R':
1735 if (ExitFlag == 0) ExitFlag = 1;
1736 if ((argptr+1 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) {
1737 ExitFlag = 255;
1738 cerr << "Not enough or invalid arguments given for removing atoms: -R <id> <distance>" << endl;
1739 } else {
1740 SaveFlag = true;
1741 cout << Verbose(1) << "Removing atoms around " << argv[argptr] << " with radius " << argv[argptr+1] << "." << endl;
1742 double tmp1 = atof(argv[argptr+1]);
1743 atom *third = mol->FindAtom(atoi(argv[argptr]));
1744 atom *first = mol->start;
1745 if ((third != NULL) && (first != mol->end)) {
1746 atom *second = first->next;
1747 while(second != mol->end) {
1748 first = second;
1749 second = first->next;
1750 if (first->x.DistanceSquared((const Vector *)&third->x) > tmp1*tmp1) // distance to first above radius ...
1751 mol->RemoveAtom(first);
1752 }
1753 } else {
1754 cerr << "Removal failed due to missing atoms on molecule or wrong id." << endl;
1755 }
1756 argptr+=2;
1757 }
1758 break;
1759 case 't':
1760 if (ExitFlag == 0) ExitFlag = 1;
1761 if ((argptr+2 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
1762 ExitFlag = 255;
1763 cerr << "Not enough or invalid arguments given for translation: -t <x> <y> <z>" << endl;
1764 } else {
1765 if (ExitFlag == 0) ExitFlag = 1;
1766 SaveFlag = true;
1767 cout << Verbose(1) << "Translating all ions by given vector." << endl;
1768 for (int i=NDIM;i--;)
1769 x.x[i] = atof(argv[argptr+i]);
1770 mol->Translate((const Vector *)&x);
1771 argptr+=3;
1772 }
1773 break;
1774 case 'T':
1775 if (ExitFlag == 0) ExitFlag = 1;
1776 if ((argptr+2 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
1777 ExitFlag = 255;
1778 cerr << "Not enough or invalid arguments given for periodic translation: -T <x> <y> <z>" << endl;
1779 } else {
1780 if (ExitFlag == 0) ExitFlag = 1;
1781 SaveFlag = true;
1782 cout << Verbose(1) << "Translating all ions periodically by given vector." << endl;
1783 for (int i=NDIM;i--;)
1784 x.x[i] = atof(argv[argptr+i]);
1785 mol->TranslatePeriodically((const Vector *)&x);
1786 argptr+=3;
1787 }
1788 break;
1789 case 's':
1790 if (ExitFlag == 0) ExitFlag = 1;
1791 if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) ) {
1792 ExitFlag = 255;
1793 cerr << "Not enough or invalid arguments given for scaling: -s <factor/[factor_x]> [factor_y] [factor_z]" << endl;
1794 } else {
1795 SaveFlag = true;
1796 j = -1;
1797 cout << Verbose(1) << "Scaling all ion positions by factor." << endl;
1798 factor = new double[NDIM];
1799 factor[0] = atof(argv[argptr]);
1800 if ((argptr < argc) && (IsValidNumber(argv[argptr])))
1801 argptr++;
1802 factor[1] = atof(argv[argptr]);
1803 if ((argptr < argc) && (IsValidNumber(argv[argptr])))
1804 argptr++;
1805 factor[2] = atof(argv[argptr]);
1806 mol->Scale(&factor);
1807 for (int i=0;i<NDIM;i++) {
1808 j += i+1;
1809 x.x[i] = atof(argv[NDIM+i]);
1810 mol->cell_size[j]*=factor[i];
1811 }
1812 delete[](factor);
1813 argptr+=1;
1814 }
1815 break;
1816 case 'b':
1817 if (ExitFlag == 0) ExitFlag = 1;
1818 if ((argptr+5 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) || (!IsValidNumber(argv[argptr+3])) || (!IsValidNumber(argv[argptr+4])) || (!IsValidNumber(argv[argptr+5])) ) {
1819 ExitFlag = 255;
1820 cerr << "Not enough or invalid arguments given for centering in box: -b <xx> <xy> <xz> <yy> <yz> <zz>" << endl;
1821 } else {
1822 SaveFlag = true;
1823 j = -1;
1824 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
1825 for (int i=0;i<6;i++) {
1826 mol->cell_size[i] = atof(argv[argptr+i]);
1827 }
1828 // center
1829 mol->CenterInBox((ofstream *)&cout);
1830 argptr+=6;
1831 }
1832 break;
1833 case 'B':
1834 if (ExitFlag == 0) ExitFlag = 1;
1835 if ((argptr+5 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) || (!IsValidNumber(argv[argptr+3])) || (!IsValidNumber(argv[argptr+4])) || (!IsValidNumber(argv[argptr+5])) ) {
1836 ExitFlag = 255;
1837 cerr << "Not enough or invalid arguments given for bounding in box: -B <xx> <xy> <xz> <yy> <yz> <zz>" << endl;
1838 } else {
1839 SaveFlag = true;
1840 j = -1;
1841 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
1842 for (int i=0;i<6;i++) {
1843 mol->cell_size[i] = atof(argv[argptr+i]);
1844 }
1845 // center
1846 mol->BoundInBox((ofstream *)&cout);
1847 argptr+=6;
1848 }
1849 break;
1850 case 'c':
1851 if (ExitFlag == 0) ExitFlag = 1;
1852 if ((argptr+2 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
1853 ExitFlag = 255;
1854 cerr << "Not enough or invalid arguments given for centering with boundary: -c <boundary_x> <boundary_y> <boundary_z>" << endl;
1855 } else {
1856 SaveFlag = true;
1857 j = -1;
1858 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl;
1859 // make every coordinate positive
1860 mol->CenterEdge((ofstream *)&cout, &x);
1861 // update Box of atoms by boundary
1862 mol->SetBoxDimension(&x);
1863 // translate each coordinate by boundary
1864 j=-1;
1865 for (int i=0;i<NDIM;i++) {
1866 j += i+1;
1867 x.x[i] = atof(argv[argptr+i]);
1868 mol->cell_size[j] += x.x[i]*2.;
1869 }
1870 mol->Translate((const Vector *)&x);
1871 argptr+=3;
1872 }
1873 break;
1874 case 'O':
1875 if (ExitFlag == 0) ExitFlag = 1;
1876 SaveFlag = true;
1877 cout << Verbose(1) << "Centering atoms on edge and setting box dimensions." << endl;
1878 x.Zero();
1879 mol->CenterEdge((ofstream *)&cout, &x);
1880 mol->SetBoxDimension(&x);
1881 argptr+=0;
1882 break;
1883 case 'r':
1884 if (ExitFlag == 0) ExitFlag = 1;
1885 if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr]))) {
1886 ExitFlag = 255;
1887 cerr << "Not enough or invalid arguments given for removing atoms: -r <id>" << endl;
1888 } else {
1889 SaveFlag = true;
1890 cout << Verbose(1) << "Removing atom " << argv[argptr] << "." << endl;
1891 atom *first = mol->FindAtom(atoi(argv[argptr]));
1892 mol->RemoveAtom(first);
1893 argptr+=1;
1894 }
1895 break;
1896 case 'f':
1897 if (ExitFlag == 0) ExitFlag = 1;
1898 if ((argptr+1 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) {
1899 ExitFlag = 255;
1900 cerr << "Not enough or invalid arguments for fragmentation: -f <max. bond distance> <bond order>" << endl;
1901 } else {
1902 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl;
1903 cout << Verbose(0) << "Creating connection matrix..." << endl;
1904 start = clock();
1905 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]), configuration.GetIsAngstroem());
1906 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
1907 if (mol->first->next != mol->last) {
1908 ExitFlag = mol->FragmentMolecule((ofstream *)&cout, atoi(argv[argptr]), &configuration);
1909 }
1910 end = clock();
1911 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
1912 argptr+=2;
1913 }
1914 break;
1915 case 'm':
1916 if (ExitFlag == 0) ExitFlag = 1;
1917 j = atoi(argv[argptr++]);
1918 if ((j<0) || (j>1)) {
1919 cerr << Verbose(1) << "ERROR: Argument of '-m' should be either 0 for no-rotate or 1 for rotate." << endl;
1920 j = 0;
1921 }
1922 if (j) {
1923 SaveFlag = true;
1924 cout << Verbose(0) << "Converting to prinicipal axis system." << endl;
1925 } else
1926 cout << Verbose(0) << "Evaluating prinicipal axis." << endl;
1927 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)j);
1928 break;
1929 case 'o':
1930 if (ExitFlag == 0) ExitFlag = 1;
1931 if ((argptr+1 >= argc) || (argv[argptr][0] == '-')){
1932 ExitFlag = 255;
1933 cerr << "Not enough or invalid arguments given for convex envelope: -o <convex output file> <non-convex output file>" << endl;
1934 } else {
1935 cout << Verbose(0) << "Evaluating volume of the convex envelope.";
1936 cout << Verbose(1) << "Storing tecplot convex data in " << argv[argptr] << "." << endl;
1937 cout << Verbose(1) << "Storing tecplot non-convex data in " << argv[argptr+1] << "." << endl;
1938 LinkedCell LCList(mol, 10.);
1939 //FindConvexBorder((ofstream *)&cout, mol, &LCList, argv[argptr]);
1940 FindNonConvexBorder((ofstream *)&cout, mol, &LCList, 5., argv[argptr+1]);
1941// RemoveAllBoundaryPoints((ofstream *)&cout, mol->TesselStruct, mol, argv[argptr]);
1942 double volumedifference = ConvexizeNonconvexEnvelope((ofstream *)&cout, mol->TesselStruct, mol, argv[argptr]);
1943 double clustervolume = VolumeOfConvexEnvelope((ofstream *)&cout, mol->TesselStruct, &configuration);
1944 cout << Verbose(0) << "The tesselated volume area is " << clustervolume << " " << (configuration.GetIsAngstroem() ? "angstrom" : "atomiclength") << "^3." << endl;
1945 cout << Verbose(0) << "The non-convex tesselated volume area is " << clustervolume-volumedifference << " " << (configuration.GetIsAngstroem() ? "angstrom" : "atomiclength") << "^3." << endl;
1946 argptr+=2;
1947 }
1948 break;
1949 case 'U':
1950 if (ExitFlag == 0) ExitFlag = 1;
1951 if ((argptr+1 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) {
1952 ExitFlag = 255;
1953 cerr << "Not enough or invalid arguments given for suspension with specified volume: -U <volume> <density>" << endl;
1954 volume = -1; // for case 'u': don't print error again
1955 } else {
1956 volume = atof(argv[argptr++]);
1957 cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl;
1958 }
1959 case 'u':
1960 if (ExitFlag == 0) ExitFlag = 1;
1961 if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) ) {
1962 if (volume != -1)
1963 ExitFlag = 255;
1964 cerr << "Not enough arguments given for suspension: -u <density>" << endl;
1965 } else {
1966 double density;
1967 SaveFlag = true;
1968 cout << Verbose(0) << "Evaluating necessary cell volume for a cluster suspended in water.";
1969 density = atof(argv[argptr++]);
1970 if (density < 1.0) {
1971 cerr << Verbose(0) << "Density must be greater than 1.0g/cm^3 !" << endl;
1972 density = 1.3;
1973 }
1974// for(int i=0;i<NDIM;i++) {
1975// repetition[i] = atoi(argv[argptr++]);
1976// if (repetition[i] < 1)
1977// cerr << Verbose(0) << "ERROR: repetition value must be greater 1!" << endl;
1978// repetition[i] = 1;
1979// }
1980 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density); // if volume == 0, will calculate from ConvexEnvelope
1981 }
1982 break;
1983 case 'd':
1984 if (ExitFlag == 0) ExitFlag = 1;
1985 if ((argptr+2 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
1986 ExitFlag = 255;
1987 cerr << "Not enough or invalid arguments given for repeating cells: -d <repeat_x> <repeat_y> <repeat_z>" << endl;
1988 } else {
1989 SaveFlag = true;
1990 for (int axis = 1; axis <= NDIM; axis++) {
1991 int faktor = atoi(argv[argptr++]);
1992 int count;
1993 element ** Elements;
1994 Vector ** vectors;
1995 if (faktor < 1) {
1996 cerr << Verbose(0) << "ERROR: Repetition faktor mus be greater than 1!" << endl;
1997 faktor = 1;
1998 }
1999 mol->CountAtoms((ofstream *)&cout); // recount atoms
2000 if (mol->AtomCount != 0) { // if there is more than none
2001 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand
2002 Elements = new element *[count];
2003 vectors = new Vector *[count];
2004 j = 0;
2005 first = mol->start;
2006 while (first->next != mol->end) { // make a list of all atoms with coordinates and element
2007 first = first->next;
2008 Elements[j] = first->type;
2009 vectors[j] = &first->x;
2010 j++;
2011 }
2012 if (count != j)
2013 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;
2014 x.Zero();
2015 y.Zero();
2016 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
2017 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times
2018 x.AddVector(&y); // per factor one cell width further
2019 for (int k=count;k--;) { // go through every atom of the original cell
2020 first = new atom(); // create a new body
2021 first->x.CopyVector(vectors[k]); // use coordinate of original atom
2022 first->x.AddVector(&x); // translate the coordinates
2023 first->type = Elements[k]; // insert original element
2024 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)
2025 }
2026 }
2027 // free memory
2028 delete[](Elements);
2029 delete[](vectors);
2030 // correct cell size
2031 if (axis < 0) { // if sign was negative, we have to translate everything
2032 x.Zero();
2033 x.AddVector(&y);
2034 x.Scale(-(faktor-1));
2035 mol->Translate(&x);
2036 }
2037 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;
2038 }
2039 }
2040 }
2041 break;
2042 default: // no match? Step on
2043 if ((argptr < argc) && (argv[argptr][0] != '-')) // if it started with a '-' we've already made a step!
2044 argptr++;
2045 break;
2046 }
2047 }
2048 } else argptr++;
2049 } while (argptr < argc);
2050 if (SaveFlag)
2051 SaveConfig(ConfigFileName, &configuration, periode, molecules);
2052 } else { // no arguments, hence scan the elements db
2053 if (periode->LoadPeriodentafel(configuration.databasepath))
2054 cout << Verbose(0) << "Element list loaded successfully." << endl;
2055 else
2056 cout << Verbose(0) << "Element list loading failed." << endl;
2057 configuration.RetrieveConfigPathAndName("main_pcp_linux");
2058 }
2059 return(ExitFlag);
2060};
2061
2062/********************************************** Main routine **************************************/
2063
2064int main(int argc, char **argv)
2065{
2066 periodentafel *periode = new periodentafel; // and a period table of all elements
2067 MoleculeListClass *molecules = new MoleculeListClass; // list of all molecules
2068 molecule *mol = NULL;
2069 config *configuration = new config;
2070 char choice; // menu choice char
2071 Vector x,y,z,n; // coordinates for absolute point in cell volume
2072 ifstream test;
2073 ofstream output;
2074 string line;
2075 char *ConfigFileName = NULL;
2076 int j;
2077
2078 // =========================== PARSE COMMAND LINE OPTIONS ====================================
2079 j = ParseCommandLineOptions(argc, argv, molecules, periode, *configuration, ConfigFileName);
2080 switch(j) {
2081 case 255: // something went wrong
2082 delete(molecules); // also free's all molecules contained
2083 delete(periode);
2084 cout << Verbose(0) << "Maximum of allocated memory: "
2085 << MemoryUsageObserver::getInstance()->getMaximumUsedMemory() << endl;
2086 cout << Verbose(0) << "Remaining non-freed memory: "
2087 << MemoryUsageObserver::getInstance()->getUsedMemorySize() << endl;
2088 return j;
2089 break;
2090 case 1: // just for -v and -h options
2091 delete(molecules); // also free's all molecules contained
2092 delete(periode);
2093 cout << Verbose(0) << "Maximum of allocated memory: "
2094 << MemoryUsageObserver::getInstance()->getMaximumUsedMemory() << endl;
2095 cout << Verbose(0) << "Remaining non-freed memory: "
2096 << MemoryUsageObserver::getInstance()->getUsedMemorySize() << endl;
2097 return 0;
2098 break;
2099 case 2: // just for -f option
2100 delete(molecules); // also free's all molecules contained
2101 delete(periode);
2102 cout << Verbose(0) << "Maximum of allocated memory: "
2103 << MemoryUsageObserver::getInstance()->getMaximumUsedMemory() << endl;
2104 cout << Verbose(0) << "Remaining non-freed memory: "
2105 << MemoryUsageObserver::getInstance()->getUsedMemorySize() << endl;
2106 return 2;
2107 break;
2108 default:
2109 break;
2110 }
2111
2112 // General stuff
2113 if (molecules->ListOfMolecules.size() == 0) {
2114 mol = new molecule(periode);
2115 if (mol->cell_size[0] == 0.) {
2116 cout << Verbose(0) << "enter lower tridiagonal form of basis matrix" << endl << endl;
2117 for (int i=0;i<6;i++) {
2118 cout << Verbose(1) << "Cell size" << i << ": ";
2119 cin >> mol->cell_size[i];
2120 }
2121 }
2122 molecules->insert(mol);
2123 }
2124
2125 // =========================== START INTERACTIVE SESSION ====================================
2126
2127 // now the main construction loop
2128 cout << Verbose(0) << endl << "Now comes the real construction..." << endl;
2129 do {
2130 cout << Verbose(0) << endl << endl;
2131 cout << Verbose(0) << "============Molecule list=======================" << endl;
2132 molecules->Enumerate((ofstream *)&cout);
2133 cout << Verbose(0) << "============Menu===============================" << endl;
2134 cout << Verbose(0) << "a - set molecule (in)active" << endl;
2135 cout << Verbose(0) << "e - edit molecules (load, parse, save)" << endl;
2136 cout << Verbose(0) << "g - globally manipulate atoms in molecule" << endl;
2137 cout << Verbose(0) << "M - Merge molecules" << endl;
2138 cout << Verbose(0) << "m - manipulate atoms" << endl;
2139 cout << Verbose(0) << "-----------------------------------------------" << endl;
2140 cout << Verbose(0) << "c - edit the current configuration" << endl;
2141 cout << Verbose(0) << "-----------------------------------------------" << endl;
2142 cout << Verbose(0) << "s - save current setup to config file" << endl;
2143 cout << Verbose(0) << "T - call the current test routine" << endl;
2144 cout << Verbose(0) << "q - quit" << endl;
2145 cout << Verbose(0) << "===============================================" << endl;
2146 cout << Verbose(0) << "Input: ";
2147 cin >> choice;
2148
2149 switch (choice) {
2150 case 'a': // (in)activate molecule
2151 {
2152 cout << "Enter index of molecule: ";
2153 cin >> j;
2154 for(MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
2155 if ((*ListRunner)->IndexNr == j)
2156 (*ListRunner)->ActiveFlag = !(*ListRunner)->ActiveFlag;
2157 }
2158 break;
2159
2160 case 'c': // edit each field of the configuration
2161 configuration->Edit();
2162 break;
2163
2164 case 'e': // create molecule
2165 EditMolecules(periode, molecules);
2166 break;
2167
2168 case 'g': // manipulate molecules
2169 ManipulateMolecules(periode, molecules, configuration);
2170 break;
2171
2172 case 'M': // merge molecules
2173 MergeMolecules(periode, molecules);
2174 break;
2175
2176 case 'm': // manipulate atoms
2177 ManipulateAtoms(periode, molecules, configuration);
2178 break;
2179
2180 case 'q': // quit
2181 break;
2182
2183 case 's': // save to config file
2184 SaveConfig(ConfigFileName, configuration, periode, molecules);
2185 break;
2186
2187 case 'T':
2188 testroutine(molecules);
2189 break;
2190
2191 default:
2192 break;
2193 };
2194 } while (choice != 'q');
2195
2196 // save element data base
2197 if (periode->StorePeriodentafel(configuration->databasepath)) //ElementsFileName
2198 cout << Verbose(0) << "Saving of elements.db successful." << endl;
2199 else
2200 cout << Verbose(0) << "Saving of elements.db failed." << endl;
2201
2202 delete(molecules); // also free's all molecules contained
2203 delete(periode);
2204 delete(configuration);
2205
2206 cout << Verbose(0) << "Maximum of allocated memory: "
2207 << MemoryUsageObserver::getInstance()->getMaximumUsedMemory() << endl;
2208 cout << Verbose(0) << "Remaining non-freed memory: "
2209 << MemoryUsageObserver::getInstance()->getUsedMemorySize() << endl;
2210 MemoryUsageObserver::purgeInstance();
2211
2212 return (0);
2213}
2214
2215/********************************************** E N D **************************************************/
Note: See TracBrowser for help on using the repository browser.