source: src/builder.cpp@ 018741

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

BUGFIX: LinkedCell list had to created with 2.*RADIUS of sphere

Some points were missed during the checking for the third point in tesselation due to the linked cell edge length being too small. We have to check TWICE the radius (i.e. the diameter) of the rolling sphere. NOTE: This was even suggested by a comment in that very line ... argh

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