source: src/builder.cpp@ 3a0b38

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 3a0b38 was 568be7, checked in by Frederik Heber <heber@…>, 15 years ago

Added config::SavePDB() and config::SaveMPQC().

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