source: src/builder.cpp@ c695c9

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

Huge change: Log() << Verbose(.) --> DoLog(.) && (Log() << Verbose(.) << ...);

Most of the files are affected, but this is necessary as if DoLog() says verbosity is not enough, all the stream operators won"t get executed which saves substantial amount of computation time.

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

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