source: src/builder.cpp@ e4b5de

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 Candidate_v1.7.0 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 e4b5de was e4b5de, checked in by Frederik Heber <heber@…>, 15 years ago

Case 'f' is now handled by CommandLineUI.

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