source: src/builder.cpp@ 1f1b23

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

Possibility to store all bonds to file added.

So far we only could store the adjacency (i.e. atom along with all bond partners per line) to file.
For plotting molecules with pgfplots (and maybe for other purposes too) we need to have single tupels of two per line.
Hence, the following additions were implemented:

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