source: src/menu.cpp@ b28524

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since b28524 was 992a54, checked in by Frederik Heber <heber@…>, 16 years ago

Minor changes to menu::SaveConfig() Signed-off-by: Tillmann Crueger <crueger@…>

  • Property mode set to 100644
File size: 52.6 KB
Line 
1/** \file menu.cpp
2 * The class in this file is responsible for displaying the menu and enabling choices.
3 *
4 * This class is currently being refactored. Functions were copied from builder.cpp and are
5 * to be imported into the menu class.
6 *
7 */
8
9#include "menu.hpp"
10#include "analysis_correlation.hpp"
11#include "atom.hpp"
12#include "bond.hpp"
13#include "bondgraph.hpp"
14#include "boundary.hpp"
15#include "config.hpp"
16#include "element.hpp"
17#include "ellipsoid.hpp"
18#include "helpers.hpp"
19#include "leastsquaremin.hpp"
20#include "linkedcell.hpp"
21#include "log.hpp"
22#include "memoryusageobserverunittest.hpp"
23#include "molecule.hpp"
24#include "periodentafel.hpp"
25
26/* copied methods for refactoring */
27/*TODO: Move these methods inside menu class
28 * and restructure menu class*/
29
30/********************************************* Subsubmenu routine ************************************/
31
32/** Submenu for adding atoms to the molecule.
33 * \param *periode periodentafel
34 * \param *molecule molecules with atoms
35 */
36void menu::AddAtoms(periodentafel *periode, molecule *mol)
37{
38 atom *first, *second, *third, *fourth;
39 Vector **atoms;
40 Vector x,y,z,n; // coordinates for absolute point in cell volume
41 double a,b,c;
42 char choice; // menu choice char
43 bool valid;
44
45 Log() << Verbose(0) << "===========ADD ATOM============================" << endl;
46 Log() << Verbose(0) << " a - state absolute coordinates of atom" << endl;
47 Log() << Verbose(0) << " b - state relative coordinates of atom wrt to reference point" << endl;
48 Log() << Verbose(0) << " c - state relative coordinates of atom wrt to already placed atom" << endl;
49 Log() << Verbose(0) << " d - state two atoms, two angles and a distance" << endl;
50 Log() << Verbose(0) << " e - least square distance position to a set of atoms" << endl;
51 Log() << Verbose(0) << "all else - go back" << endl;
52 Log() << Verbose(0) << "===============================================" << endl;
53 Log() << Verbose(0) << "Note: Specifiy angles in degrees not multiples of Pi!" << endl;
54 Log() << Verbose(0) << "INPUT: ";
55 cin >> choice;
56
57 switch (choice) {
58 default:
59 eLog() << Verbose(2) << "Not a valid choice." << endl;
60 break;
61 case 'a': // absolute coordinates of atom
62 Log() << Verbose(0) << "Enter absolute coordinates." << endl;
63 first = new atom;
64 first->x.AskPosition(mol->cell_size, false);
65 first->type = periode->AskElement(); // give type
66 mol->AddAtom(first); // add to molecule
67 break;
68
69 case 'b': // relative coordinates of atom wrt to reference point
70 first = new atom;
71 valid = true;
72 do {
73 if (!valid) eLog() << Verbose(2) << "Resulting position out of cell." << endl;
74 Log() << Verbose(0) << "Enter reference coordinates." << endl;
75 x.AskPosition(mol->cell_size, true);
76 Log() << Verbose(0) << "Enter relative coordinates." << endl;
77 first->x.AskPosition(mol->cell_size, false);
78 first->x.AddVector((const Vector *)&x);
79 Log() << Verbose(0) << "\n";
80 } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
81 first->type = periode->AskElement(); // give type
82 mol->AddAtom(first); // add to molecule
83 break;
84
85 case 'c': // relative coordinates of atom wrt to already placed atom
86 first = new atom;
87 valid = true;
88 do {
89 if (!valid) eLog() << Verbose(2) << "Resulting position out of cell." << endl;
90 second = mol->AskAtom("Enter atom number: ");
91 Log() << Verbose(0) << "Enter relative coordinates." << endl;
92 first->x.AskPosition(mol->cell_size, false);
93 for (int i=NDIM;i--;) {
94 first->x.x[i] += second->x.x[i];
95 }
96 } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
97 first->type = periode->AskElement(); // give type
98 mol->AddAtom(first); // add to molecule
99 break;
100
101 case 'd': // two atoms, two angles and a distance
102 first = new atom;
103 valid = true;
104 do {
105 if (!valid) {
106 eLog() << Verbose(2) << "Resulting coordinates out of cell - " << first->x << endl;
107 }
108 Log() << Verbose(0) << "First, we need two atoms, the first atom is the central, while the second is the outer one." << endl;
109 second = mol->AskAtom("Enter central atom: ");
110 third = mol->AskAtom("Enter second atom (specifying the axis for first angle): ");
111 fourth = mol->AskAtom("Enter third atom (specifying a plane for second angle): ");
112 a = ask_value("Enter distance between central (first) and new atom: ");
113 b = ask_value("Enter angle between new, first and second atom (degrees): ");
114 b *= M_PI/180.;
115 bound(&b, 0., 2.*M_PI);
116 c = ask_value("Enter second angle between new and normal vector of plane defined by first, second and third atom (degrees): ");
117 c *= M_PI/180.;
118 bound(&c, -M_PI, M_PI);
119 Log() << Verbose(0) << "radius: " << a << "\t phi: " << b*180./M_PI << "\t theta: " << c*180./M_PI << endl;
120/*
121 second->Output(1,1,(ofstream *)&cout);
122 third->Output(1,2,(ofstream *)&cout);
123 fourth->Output(1,3,(ofstream *)&cout);
124 n.MakeNormalvector((const vector *)&second->x, (const vector *)&third->x, (const vector *)&fourth->x);
125 x.Copyvector(&second->x);
126 x.SubtractVector(&third->x);
127 x.Copyvector(&fourth->x);
128 x.SubtractVector(&third->x);
129
130 if (!z.SolveSystem(&x,&y,&n, b, c, a)) {
131 Log() << Verbose(0) << "Failure solving self-dependent linear system!" << endl;
132 continue;
133 }
134 Log() << Verbose(0) << "resulting relative coordinates: ";
135 z.Output();
136 Log() << Verbose(0) << endl;
137 */
138 // calc axis vector
139 x.CopyVector(&second->x);
140 x.SubtractVector(&third->x);
141 x.Normalize();
142 Log() << Verbose(0) << "x: ",
143 x.Output();
144 Log() << Verbose(0) << endl;
145 z.MakeNormalVector(&second->x,&third->x,&fourth->x);
146 Log() << Verbose(0) << "z: ",
147 z.Output();
148 Log() << Verbose(0) << endl;
149 y.MakeNormalVector(&x,&z);
150 Log() << Verbose(0) << "y: ",
151 y.Output();
152 Log() << Verbose(0) << endl;
153
154 // rotate vector around first angle
155 first->x.CopyVector(&x);
156 first->x.RotateVector(&z,b - M_PI);
157 Log() << Verbose(0) << "Rotated vector: ",
158 first->x.Output();
159 Log() << Verbose(0) << endl;
160 // remove the projection onto the rotation plane of the second angle
161 n.CopyVector(&y);
162 n.Scale(first->x.ScalarProduct(&y));
163 Log() << Verbose(0) << "N1: ",
164 n.Output();
165 Log() << Verbose(0) << endl;
166 first->x.SubtractVector(&n);
167 Log() << Verbose(0) << "Subtracted vector: ",
168 first->x.Output();
169 Log() << Verbose(0) << endl;
170 n.CopyVector(&z);
171 n.Scale(first->x.ScalarProduct(&z));
172 Log() << Verbose(0) << "N2: ",
173 n.Output();
174 Log() << Verbose(0) << endl;
175 first->x.SubtractVector(&n);
176 Log() << Verbose(0) << "2nd subtracted vector: ",
177 first->x.Output();
178 Log() << Verbose(0) << endl;
179
180 // rotate another vector around second angle
181 n.CopyVector(&y);
182 n.RotateVector(&x,c - M_PI);
183 Log() << Verbose(0) << "2nd Rotated vector: ",
184 n.Output();
185 Log() << Verbose(0) << endl;
186
187 // add the two linear independent vectors
188 first->x.AddVector(&n);
189 first->x.Normalize();
190 first->x.Scale(a);
191 first->x.AddVector(&second->x);
192
193 Log() << Verbose(0) << "resulting coordinates: ";
194 first->x.Output();
195 Log() << Verbose(0) << endl;
196 } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
197 first->type = periode->AskElement(); // give type
198 mol->AddAtom(first); // add to molecule
199 break;
200
201 case 'e': // least square distance position to a set of atoms
202 first = new atom;
203 atoms = new (Vector*[128]);
204 valid = true;
205 for(int i=128;i--;)
206 atoms[i] = NULL;
207 int i=0, j=0;
208 Log() << Verbose(0) << "Now we need at least three molecules.\n";
209 do {
210 Log() << Verbose(0) << "Enter " << i+1 << "th atom: ";
211 cin >> j;
212 if (j != -1) {
213 second = mol->FindAtom(j);
214 atoms[i++] = &(second->x);
215 }
216 } while ((j != -1) && (i<128));
217 if (i >= 2) {
218 first->x.LSQdistance((const Vector **)atoms, i);
219
220 first->x.Output();
221 first->type = periode->AskElement(); // give type
222 mol->AddAtom(first); // add to molecule
223 } else {
224 delete first;
225 Log() << Verbose(0) << "Please enter at least two vectors!\n";
226 }
227 break;
228 };
229};
230
231/** Submenu for centering the atoms in the molecule.
232 * \param *mol molecule with all the atoms
233 */
234void menu::CenterAtoms(molecule *mol)
235{
236 Vector x, y, helper;
237 char choice; // menu choice char
238
239 Log() << Verbose(0) << "===========CENTER ATOMS=========================" << endl;
240 Log() << Verbose(0) << " a - on origin" << endl;
241 Log() << Verbose(0) << " b - on center of gravity" << endl;
242 Log() << Verbose(0) << " c - within box with additional boundary" << endl;
243 Log() << Verbose(0) << " d - within given simulation box" << endl;
244 Log() << Verbose(0) << "all else - go back" << endl;
245 Log() << Verbose(0) << "===============================================" << endl;
246 Log() << Verbose(0) << "INPUT: ";
247 cin >> choice;
248
249 switch (choice) {
250 default:
251 Log() << Verbose(0) << "Not a valid choice." << endl;
252 break;
253 case 'a':
254 Log() << Verbose(0) << "Centering atoms in config file on origin." << endl;
255 mol->CenterOrigin();
256 break;
257 case 'b':
258 Log() << Verbose(0) << "Centering atoms in config file on center of gravity." << endl;
259 mol->CenterPeriodic();
260 break;
261 case 'c':
262 Log() << Verbose(0) << "Centering atoms in config file within given additional boundary." << endl;
263 for (int i=0;i<NDIM;i++) {
264 Log() << Verbose(0) << "Enter axis " << i << " boundary: ";
265 cin >> y.x[i];
266 }
267 mol->CenterEdge(&x); // make every coordinate positive
268 mol->Center.AddVector(&y); // translate by boundary
269 helper.CopyVector(&y);
270 helper.Scale(2.);
271 helper.AddVector(&x);
272 mol->SetBoxDimension(&helper); // update Box of atoms by boundary
273 break;
274 case 'd':
275 Log() << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
276 for (int i=0;i<NDIM;i++) {
277 Log() << Verbose(0) << "Enter axis " << i << " boundary: ";
278 cin >> x.x[i];
279 }
280 // update Box of atoms by boundary
281 mol->SetBoxDimension(&x);
282 // center
283 mol->CenterInBox();
284 break;
285 }
286};
287
288/** Submenu for aligning the atoms in the molecule.
289 * \param *periode periodentafel
290 * \param *mol molecule with all the atoms
291 */
292void menu::AlignAtoms(periodentafel *periode, molecule *mol)
293{
294 atom *first, *second, *third;
295 Vector x,n;
296 char choice; // menu choice char
297
298 Log() << Verbose(0) << "===========ALIGN ATOMS=========================" << endl;
299 Log() << Verbose(0) << " a - state three atoms defining align plane" << endl;
300 Log() << Verbose(0) << " b - state alignment vector" << endl;
301 Log() << Verbose(0) << " c - state two atoms in alignment direction" << endl;
302 Log() << Verbose(0) << " d - align automatically by least square fit" << endl;
303 Log() << Verbose(0) << "all else - go back" << endl;
304 Log() << Verbose(0) << "===============================================" << endl;
305 Log() << Verbose(0) << "INPUT: ";
306 cin >> choice;
307
308 switch (choice) {
309 default:
310 case 'a': // three atoms defining mirror plane
311 first = mol->AskAtom("Enter first atom: ");
312 second = mol->AskAtom("Enter second atom: ");
313 third = mol->AskAtom("Enter third atom: ");
314
315 n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);
316 break;
317 case 'b': // normal vector of mirror plane
318 Log() << Verbose(0) << "Enter normal vector of mirror plane." << endl;
319 n.AskPosition(mol->cell_size,0);
320 n.Normalize();
321 break;
322 case 'c': // three atoms defining mirror plane
323 first = mol->AskAtom("Enter first atom: ");
324 second = mol->AskAtom("Enter second atom: ");
325
326 n.CopyVector((const Vector *)&first->x);
327 n.SubtractVector((const Vector *)&second->x);
328 n.Normalize();
329 break;
330 case 'd':
331 char shorthand[4];
332 Vector a;
333 struct lsq_params param;
334 do {
335 fprintf(stdout, "Enter the element of atoms to be chosen: ");
336 fscanf(stdin, "%3s", shorthand);
337 } while ((param.type = periode->FindElement(shorthand)) == NULL);
338 Log() << Verbose(0) << "Element is " << param.type->name << endl;
339 mol->GetAlignvector(&param);
340 for (int i=NDIM;i--;) {
341 x.x[i] = gsl_vector_get(param.x,i);
342 n.x[i] = gsl_vector_get(param.x,i+NDIM);
343 }
344 gsl_vector_free(param.x);
345 Log() << Verbose(0) << "Offset vector: ";
346 x.Output();
347 Log() << Verbose(0) << endl;
348 n.Normalize();
349 break;
350 };
351 Log() << Verbose(0) << "Alignment vector: ";
352 n.Output();
353 Log() << Verbose(0) << endl;
354 mol->Align(&n);
355};
356
357/** Submenu for mirroring the atoms in the molecule.
358 * \param *mol molecule with all the atoms
359 */
360void menu::MirrorAtoms(molecule *mol)
361{
362 atom *first, *second, *third;
363 Vector n;
364 char choice; // menu choice char
365
366 Log() << Verbose(0) << "===========MIRROR ATOMS=========================" << endl;
367 Log() << Verbose(0) << " a - state three atoms defining mirror plane" << endl;
368 Log() << Verbose(0) << " b - state normal vector of mirror plane" << endl;
369 Log() << Verbose(0) << " c - state two atoms in normal direction" << endl;
370 Log() << Verbose(0) << "all else - go back" << endl;
371 Log() << Verbose(0) << "===============================================" << endl;
372 Log() << Verbose(0) << "INPUT: ";
373 cin >> choice;
374
375 switch (choice) {
376 default:
377 case 'a': // three atoms defining mirror plane
378 first = mol->AskAtom("Enter first atom: ");
379 second = mol->AskAtom("Enter second atom: ");
380 third = mol->AskAtom("Enter third atom: ");
381
382 n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);
383 break;
384 case 'b': // normal vector of mirror plane
385 Log() << Verbose(0) << "Enter normal vector of mirror plane." << endl;
386 n.AskPosition(mol->cell_size,0);
387 n.Normalize();
388 break;
389 case 'c': // three atoms defining mirror plane
390 first = mol->AskAtom("Enter first atom: ");
391 second = mol->AskAtom("Enter second atom: ");
392
393 n.CopyVector((const Vector *)&first->x);
394 n.SubtractVector((const Vector *)&second->x);
395 n.Normalize();
396 break;
397 };
398 Log() << Verbose(0) << "Normal vector: ";
399 n.Output();
400 Log() << Verbose(0) << endl;
401 mol->Mirror((const Vector *)&n);
402};
403
404/** Submenu for removing the atoms from the molecule.
405 * \param *mol molecule with all the atoms
406 */
407void menu::RemoveAtoms(molecule *mol)
408{
409 atom *first, *second;
410 int axis;
411 double tmp1, tmp2;
412 char choice; // menu choice char
413
414 Log() << Verbose(0) << "===========REMOVE ATOMS=========================" << endl;
415 Log() << Verbose(0) << " a - state atom for removal by number" << endl;
416 Log() << Verbose(0) << " b - keep only in radius around atom" << endl;
417 Log() << Verbose(0) << " c - remove this with one axis greater value" << endl;
418 Log() << Verbose(0) << "all else - go back" << endl;
419 Log() << Verbose(0) << "===============================================" << endl;
420 Log() << Verbose(0) << "INPUT: ";
421 cin >> choice;
422
423 switch (choice) {
424 default:
425 case 'a':
426 if (mol->RemoveAtom(mol->AskAtom("Enter number of atom within molecule: ")))
427 Log() << Verbose(1) << "Atom removed." << endl;
428 else
429 Log() << Verbose(1) << "Atom not found." << endl;
430 break;
431 case 'b':
432 second = mol->AskAtom("Enter number of atom as reference point: ");
433 Log() << Verbose(0) << "Enter radius: ";
434 cin >> tmp1;
435 first = mol->start;
436 second = first->next;
437 while(second != mol->end) {
438 first = second;
439 second = first->next;
440 if (first->x.DistanceSquared((const Vector *)&second->x) > tmp1*tmp1) // distance to first above radius ...
441 mol->RemoveAtom(first);
442 }
443 break;
444 case 'c':
445 Log() << Verbose(0) << "Which axis is it: ";
446 cin >> axis;
447 Log() << Verbose(0) << "Lower boundary: ";
448 cin >> tmp1;
449 Log() << Verbose(0) << "Upper boundary: ";
450 cin >> tmp2;
451 first = mol->start;
452 second = first->next;
453 while(second != mol->end) {
454 first = second;
455 second = first->next;
456 if ((first->x.x[axis] < tmp1) || (first->x.x[axis] > tmp2)) {// out of boundary ...
457 //Log() << Verbose(0) << "Atom " << *first << " with " << first->x.x[axis] << " on axis " << axis << " is out of bounds [" << tmp1 << "," << tmp2 << "]." << endl;
458 mol->RemoveAtom(first);
459 }
460 }
461 break;
462 };
463 //mol->Output();
464 choice = 'r';
465};
466
467/** Submenu for measuring out the atoms in the molecule.
468 * \param *periode periodentafel
469 * \param *mol molecule with all the atoms
470 */
471void menu::MeasureAtoms(periodentafel *periode, molecule *mol, config *configuration)
472{
473 atom *first, *second, *third;
474 Vector x,y;
475 double min[256], tmp1, tmp2, tmp3;
476 int Z;
477 char choice; // menu choice char
478
479 Log() << Verbose(0) << "===========MEASURE ATOMS=========================" << endl;
480 Log() << Verbose(0) << " a - calculate bond length between one atom and all others" << endl;
481 Log() << Verbose(0) << " b - calculate bond length between two atoms" << endl;
482 Log() << Verbose(0) << " c - calculate bond angle" << endl;
483 Log() << Verbose(0) << " d - calculate principal axis of the system" << endl;
484 Log() << Verbose(0) << " e - calculate volume of the convex envelope" << endl;
485 Log() << Verbose(0) << " f - calculate temperature from current velocity" << endl;
486 Log() << Verbose(0) << " g - output all temperatures per step from velocities" << endl;
487 Log() << Verbose(0) << "all else - go back" << endl;
488 Log() << Verbose(0) << "===============================================" << endl;
489 Log() << Verbose(0) << "INPUT: ";
490 cin >> choice;
491
492 switch(choice) {
493 default:
494 Log() << Verbose(1) << "Not a valid choice." << endl;
495 break;
496 case 'a':
497 first = mol->AskAtom("Enter first atom: ");
498 for (int i=MAX_ELEMENTS;i--;)
499 min[i] = 0.;
500
501 second = mol->start;
502 while ((second->next != mol->end)) {
503 second = second->next; // advance
504 Z = second->type->Z;
505 tmp1 = 0.;
506 if (first != second) {
507 x.CopyVector((const Vector *)&first->x);
508 x.SubtractVector((const Vector *)&second->x);
509 tmp1 = x.Norm();
510 }
511 if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1;
512 //Log() << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl;
513 }
514 for (int i=MAX_ELEMENTS;i--;)
515 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;
516 break;
517
518 case 'b':
519 first = mol->AskAtom("Enter first atom: ");
520 second = mol->AskAtom("Enter second atom: ");
521 for (int i=NDIM;i--;)
522 min[i] = 0.;
523 x.CopyVector((const Vector *)&first->x);
524 x.SubtractVector((const Vector *)&second->x);
525 tmp1 = x.Norm();
526 Log() << Verbose(1) << "Distance vector is ";
527 x.Output();
528 Log() << Verbose(0) << "." << endl << "Norm of distance is " << tmp1 << "." << endl;
529 break;
530
531 case 'c':
532 Log() << Verbose(0) << "Evaluating bond angle between three - first, central, last - atoms." << endl;
533 first = mol->AskAtom("Enter first atom: ");
534 second = mol->AskAtom("Enter central atom: ");
535 third = mol->AskAtom("Enter last atom: ");
536 tmp1 = tmp2 = tmp3 = 0.;
537 x.CopyVector((const Vector *)&first->x);
538 x.SubtractVector((const Vector *)&second->x);
539 y.CopyVector((const Vector *)&third->x);
540 y.SubtractVector((const Vector *)&second->x);
541 Log() << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": ";
542 Log() << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl;
543 break;
544 case 'd':
545 Log() << Verbose(0) << "Evaluating prinicipal axis." << endl;
546 Log() << Verbose(0) << "Shall we rotate? [0/1]: ";
547 cin >> Z;
548 if ((Z >=0) && (Z <=1))
549 mol->PrincipalAxisSystem((bool)Z);
550 else
551 mol->PrincipalAxisSystem(false);
552 break;
553 case 'e':
554 {
555 Log() << Verbose(0) << "Evaluating volume of the convex envelope.";
556 class Tesselation *TesselStruct = NULL;
557 const LinkedCell *LCList = NULL;
558 LCList = new LinkedCell(mol, 10.);
559 FindConvexBorder(mol, TesselStruct, LCList, NULL);
560 double clustervolume = VolumeOfConvexEnvelope(TesselStruct, configuration);
561 Log() << Verbose(0) << "The tesselated surface area is " << clustervolume << "." << endl;\
562 delete(LCList);
563 delete(TesselStruct);
564 }
565 break;
566 case 'f':
567 mol->OutputTemperatureFromTrajectories((ofstream *)&cout, mol->MDSteps-1, mol->MDSteps);
568 break;
569 case 'g':
570 {
571 char filename[255];
572 Log() << Verbose(0) << "Please enter filename: " << endl;
573 cin >> filename;
574 Log() << Verbose(1) << "Storing temperatures in " << filename << "." << endl;
575 ofstream *output = new ofstream(filename, ios::trunc);
576 if (!mol->OutputTemperatureFromTrajectories(output, 0, mol->MDSteps))
577 Log() << Verbose(2) << "File could not be written." << endl;
578 else
579 Log() << Verbose(2) << "File stored." << endl;
580 output->close();
581 delete(output);
582 }
583 break;
584 }
585};
586
587/** Submenu for measuring out the atoms in the molecule.
588 * \param *mol molecule with all the atoms
589 * \param *configuration configuration structure for the to be written config files of all fragments
590 */
591void menu::FragmentAtoms(molecule *mol, config *configuration)
592{
593 int Order1;
594 clock_t start, end;
595
596 Log() << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
597 Log() << Verbose(0) << "What's the desired bond order: ";
598 cin >> Order1;
599 if (mol->first->next != mol->last) { // there are bonds
600 start = clock();
601 mol->FragmentMolecule(Order1, configuration);
602 end = clock();
603 Log() << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
604 } else
605 Log() << Verbose(0) << "Connection matrix has not yet been generated!" << endl;
606};
607
608/********************************************** Submenu routine **************************************/
609
610/** Submenu for manipulating atoms.
611 * \param *periode periodentafel
612 * \param *molecules list of molecules whose atoms are to be manipulated
613 */
614void menu::ManipulateAtoms(periodentafel *periode, MoleculeListClass *molecules, config *configuration)
615{
616 atom *first, *second;
617 molecule *mol = NULL;
618 Vector x,y,z,n; // coordinates for absolute point in cell volume
619 double *factor; // unit factor if desired
620 double bond, minBond;
621 char choice; // menu choice char
622 bool valid;
623
624 Log() << Verbose(0) << "=========MANIPULATE ATOMS======================" << endl;
625 Log() << Verbose(0) << "a - add an atom" << endl;
626 Log() << Verbose(0) << "r - remove an atom" << endl;
627 Log() << Verbose(0) << "b - scale a bond between atoms" << endl;
628 Log() << Verbose(0) << "u - change an atoms element" << endl;
629 Log() << Verbose(0) << "l - measure lengths, angles, ... for an atom" << endl;
630 Log() << Verbose(0) << "all else - go back" << endl;
631 Log() << Verbose(0) << "===============================================" << endl;
632 if (molecules->NumberOfActiveMolecules() > 1)
633 eLog() << Verbose(2) << "There is more than one molecule active! Atoms will be added to each." << endl;
634 Log() << Verbose(0) << "INPUT: ";
635 cin >> choice;
636
637 switch (choice) {
638 default:
639 Log() << Verbose(0) << "Not a valid choice." << endl;
640 break;
641
642 case 'a': // add atom
643 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
644 if ((*ListRunner)->ActiveFlag) {
645 mol = *ListRunner;
646 Log() << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
647 AddAtoms(periode, mol);
648 }
649 break;
650
651 case 'b': // scale a bond
652 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
653 if ((*ListRunner)->ActiveFlag) {
654 mol = *ListRunner;
655 Log() << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
656 Log() << Verbose(0) << "Scaling bond length between two atoms." << endl;
657 first = mol->AskAtom("Enter first (fixed) atom: ");
658 second = mol->AskAtom("Enter second (shifting) atom: ");
659 minBond = 0.;
660 for (int i=NDIM;i--;)
661 minBond += (first->x.x[i]-second->x.x[i])*(first->x.x[i] - second->x.x[i]);
662 minBond = sqrt(minBond);
663 Log() << Verbose(0) << "Current Bond length between " << first->type->name << " Atom " << first->nr << " and " << second->type->name << " Atom " << second->nr << ": " << minBond << " a.u." << endl;
664 Log() << Verbose(0) << "Enter new bond length [a.u.]: ";
665 cin >> bond;
666 for (int i=NDIM;i--;) {
667 second->x.x[i] -= (second->x.x[i]-first->x.x[i])/minBond*(minBond-bond);
668 }
669 //Log() << Verbose(0) << "New coordinates of Atom " << second->nr << " are: ";
670 //second->Output(second->type->No, 1);
671 }
672 break;
673
674 case 'c': // unit scaling of the metric
675 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
676 if ((*ListRunner)->ActiveFlag) {
677 mol = *ListRunner;
678 Log() << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
679 Log() << Verbose(0) << "Angstroem -> Bohrradius: 1.8897261\t\tBohrradius -> Angstroem: 0.52917721" << endl;
680 Log() << Verbose(0) << "Enter three factors: ";
681 factor = new double[NDIM];
682 cin >> factor[0];
683 cin >> factor[1];
684 cin >> factor[2];
685 valid = true;
686 mol->Scale((const double ** const)&factor);
687 delete[](factor);
688 }
689 break;
690
691 case 'l': // measure distances or angles
692 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
693 if ((*ListRunner)->ActiveFlag) {
694 mol = *ListRunner;
695 Log() << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
696 MeasureAtoms(periode, mol, configuration);
697 }
698 break;
699
700 case 'r': // remove atom
701 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
702 if ((*ListRunner)->ActiveFlag) {
703 mol = *ListRunner;
704 Log() << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
705 RemoveAtoms(mol);
706 }
707 break;
708
709 case 'u': // change an atom's element
710 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
711 if ((*ListRunner)->ActiveFlag) {
712 int Z;
713 mol = *ListRunner;
714 Log() << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
715 first = NULL;
716 do {
717 Log() << Verbose(0) << "Change the element of which atom: ";
718 cin >> Z;
719 } while ((first = mol->FindAtom(Z)) == NULL);
720 Log() << Verbose(0) << "New element by atomic number Z: ";
721 cin >> Z;
722 first->type = periode->FindElement(Z);
723 Log() << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl;
724 }
725 break;
726 }
727};
728
729/** Submenu for manipulating molecules.
730 * \param *periode periodentafel
731 * \param *molecules list of molecule to manipulate
732 */
733void menu::ManipulateMolecules(periodentafel *periode, MoleculeListClass *molecules, config *configuration)
734{
735 atom *first = NULL;
736 Vector x,y,z,n; // coordinates for absolute point in cell volume
737 int j, axis, count, faktor;
738 char choice; // menu choice char
739 molecule *mol = NULL;
740 element **Elements;
741 Vector **vectors;
742 MoleculeLeafClass *Subgraphs = NULL;
743
744 Log() << Verbose(0) << "=========MANIPULATE GLOBALLY===================" << endl;
745 Log() << Verbose(0) << "c - scale by unit transformation" << endl;
746 Log() << Verbose(0) << "d - duplicate molecule/periodic cell" << endl;
747 Log() << Verbose(0) << "f - fragment molecule many-body bond order style" << endl;
748 Log() << Verbose(0) << "g - center atoms in box" << endl;
749 Log() << Verbose(0) << "i - realign molecule" << endl;
750 Log() << Verbose(0) << "m - mirror all molecules" << endl;
751 Log() << Verbose(0) << "o - create connection matrix" << endl;
752 Log() << Verbose(0) << "t - translate molecule by vector" << endl;
753 Log() << Verbose(0) << "all else - go back" << endl;
754 Log() << Verbose(0) << "===============================================" << endl;
755 if (molecules->NumberOfActiveMolecules() > 1)
756 eLog() << Verbose(2) << "There is more than one molecule active! Atoms will be added to each." << endl;
757 Log() << Verbose(0) << "INPUT: ";
758 cin >> choice;
759
760 switch (choice) {
761 default:
762 Log() << Verbose(0) << "Not a valid choice." << endl;
763 break;
764
765 case 'd': // duplicate the periodic cell along a given axis, given times
766 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
767 if ((*ListRunner)->ActiveFlag) {
768 mol = *ListRunner;
769 Log() << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
770 Log() << Verbose(0) << "State the axis [(+-)123]: ";
771 cin >> axis;
772 Log() << Verbose(0) << "State the factor: ";
773 cin >> faktor;
774
775 mol->CountAtoms(); // recount atoms
776 if (mol->AtomCount != 0) { // if there is more than none
777 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand
778 Elements = new element *[count];
779 vectors = new Vector *[count];
780 j = 0;
781 first = mol->start;
782 while (first->next != mol->end) { // make a list of all atoms with coordinates and element
783 first = first->next;
784 Elements[j] = first->type;
785 vectors[j] = &first->x;
786 j++;
787 }
788 if (count != j)
789 eLog() << Verbose(1) << "AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;
790 x.Zero();
791 y.Zero();
792 y.x[abs(axis)-1] = mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] * abs(axis)/axis; // last term is for sign, first is for magnitude
793 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times
794 x.AddVector(&y); // per factor one cell width further
795 for (int k=count;k--;) { // go through every atom of the original cell
796 first = new atom(); // create a new body
797 first->x.CopyVector(vectors[k]); // use coordinate of original atom
798 first->x.AddVector(&x); // translate the coordinates
799 first->type = Elements[k]; // insert original element
800 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)
801 }
802 }
803 if (mol->first->next != mol->last) // if connect matrix is present already, redo it
804 mol->CreateAdjacencyList(mol->BondDistance, configuration->GetIsAngstroem(), &BondGraph::CovalentMinMaxDistance, NULL);
805 // free memory
806 delete[](Elements);
807 delete[](vectors);
808 // correct cell size
809 if (axis < 0) { // if sign was negative, we have to translate everything
810 x.Zero();
811 x.AddVector(&y);
812 x.Scale(-(faktor-1));
813 mol->Translate(&x);
814 }
815 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;
816 }
817 }
818 break;
819
820 case 'f':
821 FragmentAtoms(mol, configuration);
822 break;
823
824 case 'g': // center the atoms
825 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
826 if ((*ListRunner)->ActiveFlag) {
827 mol = *ListRunner;
828 Log() << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
829 CenterAtoms(mol);
830 }
831 break;
832
833 case 'i': // align all atoms
834 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
835 if ((*ListRunner)->ActiveFlag) {
836 mol = *ListRunner;
837 Log() << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
838 AlignAtoms(periode, mol);
839 }
840 break;
841
842 case 'm': // mirror atoms along a given axis
843 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
844 if ((*ListRunner)->ActiveFlag) {
845 mol = *ListRunner;
846 Log() << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
847 MirrorAtoms(mol);
848 }
849 break;
850
851 case 'o': // create the connection matrix
852 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
853 if ((*ListRunner)->ActiveFlag) {
854 mol = *ListRunner;
855 double bonddistance;
856 clock_t start,end;
857 Log() << Verbose(0) << "What's the maximum bond distance: ";
858 cin >> bonddistance;
859 start = clock();
860 mol->CreateAdjacencyList(bonddistance, configuration->GetIsAngstroem(), &BondGraph::CovalentMinMaxDistance, NULL);
861 end = clock();
862 Log() << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
863 }
864 break;
865
866 case 't': // translate all atoms
867 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
868 if ((*ListRunner)->ActiveFlag) {
869 mol = *ListRunner;
870 Log() << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
871 Log() << Verbose(0) << "Enter translation vector." << endl;
872 x.AskPosition(mol->cell_size,0);
873 mol->Center.AddVector((const Vector *)&x);
874 }
875 break;
876 }
877 // Free all
878 if (Subgraphs != NULL) { // free disconnected subgraph list of DFS analysis was performed
879 while (Subgraphs->next != NULL) {
880 Subgraphs = Subgraphs->next;
881 delete(Subgraphs->previous);
882 }
883 delete(Subgraphs);
884 }
885};
886
887
888/** Submenu for creating new molecules.
889 * \param *periode periodentafel
890 * \param *molecules list of molecules to add to
891 */
892void menu::EditMolecules(periodentafel *periode, MoleculeListClass *molecules)
893{
894 char choice; // menu choice char
895 Vector center;
896 int nr, count;
897 molecule *mol = NULL;
898
899 Log() << Verbose(0) << "==========EDIT MOLECULES=====================" << endl;
900 Log() << Verbose(0) << "c - create new molecule" << endl;
901 Log() << Verbose(0) << "l - load molecule from xyz file" << endl;
902 Log() << Verbose(0) << "n - change molecule's name" << endl;
903 Log() << Verbose(0) << "N - give molecules filename" << endl;
904 Log() << Verbose(0) << "p - parse atoms in xyz file into molecule" << endl;
905 Log() << Verbose(0) << "r - remove a molecule" << endl;
906 Log() << Verbose(0) << "all else - go back" << endl;
907 Log() << Verbose(0) << "===============================================" << endl;
908 Log() << Verbose(0) << "INPUT: ";
909 cin >> choice;
910
911 switch (choice) {
912 default:
913 Log() << Verbose(0) << "Not a valid choice." << endl;
914 break;
915 case 'c':
916 mol = new molecule(periode);
917 molecules->insert(mol);
918 break;
919
920 case 'l': // load from XYZ file
921 {
922 char filename[MAXSTRINGSIZE];
923 Log() << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
924 mol = new molecule(periode);
925 do {
926 Log() << Verbose(0) << "Enter file name: ";
927 cin >> filename;
928 } while (!mol->AddXYZFile(filename));
929 mol->SetNameFromFilename(filename);
930 // center at set box dimensions
931 mol->CenterEdge(&center);
932 mol->cell_size[0] = center.x[0];
933 mol->cell_size[1] = 0;
934 mol->cell_size[2] = center.x[1];
935 mol->cell_size[3] = 0;
936 mol->cell_size[4] = 0;
937 mol->cell_size[5] = center.x[2];
938 molecules->insert(mol);
939 }
940 break;
941
942 case 'n':
943 {
944 char filename[MAXSTRINGSIZE];
945 do {
946 Log() << Verbose(0) << "Enter index of molecule: ";
947 cin >> nr;
948 mol = molecules->ReturnIndex(nr);
949 } while (mol == NULL);
950 Log() << Verbose(0) << "Enter name: ";
951 cin >> filename;
952 strcpy(mol->name, filename);
953 }
954 break;
955
956 case 'N':
957 {
958 char filename[MAXSTRINGSIZE];
959 do {
960 Log() << Verbose(0) << "Enter index of molecule: ";
961 cin >> nr;
962 mol = molecules->ReturnIndex(nr);
963 } while (mol == NULL);
964 Log() << Verbose(0) << "Enter name: ";
965 cin >> filename;
966 mol->SetNameFromFilename(filename);
967 }
968 break;
969
970 case 'p': // parse XYZ file
971 {
972 char filename[MAXSTRINGSIZE];
973 mol = NULL;
974 do {
975 Log() << Verbose(0) << "Enter index of molecule: ";
976 cin >> nr;
977 mol = molecules->ReturnIndex(nr);
978 } while (mol == NULL);
979 Log() << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
980 do {
981 Log() << Verbose(0) << "Enter file name: ";
982 cin >> filename;
983 } while (!mol->AddXYZFile(filename));
984 mol->SetNameFromFilename(filename);
985 }
986 break;
987
988 case 'r':
989 Log() << Verbose(0) << "Enter index of molecule: ";
990 cin >> nr;
991 count = 1;
992 for(MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
993 if (nr == (*ListRunner)->IndexNr) {
994 mol = *ListRunner;
995 molecules->ListOfMolecules.erase(ListRunner);
996 delete(mol);
997 break;
998 }
999 break;
1000 }
1001};
1002
1003
1004/** Submenu for merging molecules.
1005 * \param *periode periodentafel
1006 * \param *molecules list of molecules to add to
1007 */
1008void menu::MergeMolecules(periodentafel *periode, MoleculeListClass *molecules)
1009{
1010 char choice; // menu choice char
1011
1012 Log() << Verbose(0) << "===========MERGE MOLECULES=====================" << endl;
1013 Log() << Verbose(0) << "a - simple add of one molecule to another" << endl;
1014 Log() << Verbose(0) << "e - embedding merge of two molecules" << endl;
1015 Log() << Verbose(0) << "m - multi-merge of all molecules" << endl;
1016 Log() << Verbose(0) << "s - scatter merge of two molecules" << endl;
1017 Log() << Verbose(0) << "t - simple merge of two molecules" << endl;
1018 Log() << Verbose(0) << "all else - go back" << endl;
1019 Log() << Verbose(0) << "===============================================" << endl;
1020 Log() << Verbose(0) << "INPUT: ";
1021 cin >> choice;
1022
1023 switch (choice) {
1024 default:
1025 Log() << Verbose(0) << "Not a valid choice." << endl;
1026 break;
1027
1028 case 'a':
1029 {
1030 int src, dest;
1031 molecule *srcmol = NULL, *destmol = NULL;
1032 {
1033 do {
1034 Log() << Verbose(0) << "Enter index of destination molecule: ";
1035 cin >> dest;
1036 destmol = molecules->ReturnIndex(dest);
1037 } while ((destmol == NULL) && (dest != -1));
1038 do {
1039 Log() << Verbose(0) << "Enter index of source molecule to add from: ";
1040 cin >> src;
1041 srcmol = molecules->ReturnIndex(src);
1042 } while ((srcmol == NULL) && (src != -1));
1043 if ((src != -1) && (dest != -1))
1044 molecules->SimpleAdd(srcmol, destmol);
1045 }
1046 }
1047 break;
1048
1049 case 'e':
1050 {
1051 int src, dest;
1052 molecule *srcmol = NULL, *destmol = NULL;
1053 do {
1054 Log() << Verbose(0) << "Enter index of matrix molecule (the variable one): ";
1055 cin >> src;
1056 srcmol = molecules->ReturnIndex(src);
1057 } while ((srcmol == NULL) && (src != -1));
1058 do {
1059 Log() << Verbose(0) << "Enter index of molecule to merge into (the fixed one): ";
1060 cin >> dest;
1061 destmol = molecules->ReturnIndex(dest);
1062 } while ((destmol == NULL) && (dest != -1));
1063 if ((src != -1) && (dest != -1))
1064 molecules->EmbedMerge(destmol, srcmol);
1065 }
1066 break;
1067
1068 case 'm':
1069 {
1070 int nr;
1071 molecule *mol = NULL;
1072 do {
1073 Log() << Verbose(0) << "Enter index of molecule to merge into: ";
1074 cin >> nr;
1075 mol = molecules->ReturnIndex(nr);
1076 } while ((mol == NULL) && (nr != -1));
1077 if (nr != -1) {
1078 int N = molecules->ListOfMolecules.size()-1;
1079 int *src = new int(N);
1080 for(MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
1081 if ((*ListRunner)->IndexNr != nr)
1082 src[N++] = (*ListRunner)->IndexNr;
1083 molecules->SimpleMultiMerge(mol, src, N);
1084 delete[](src);
1085 }
1086 }
1087 break;
1088
1089 case 's':
1090 Log() << Verbose(0) << "Not implemented yet." << endl;
1091 break;
1092
1093 case 't':
1094 {
1095 int src, dest;
1096 molecule *srcmol = NULL, *destmol = NULL;
1097 {
1098 do {
1099 Log() << Verbose(0) << "Enter index of destination molecule: ";
1100 cin >> dest;
1101 destmol = molecules->ReturnIndex(dest);
1102 } while ((destmol == NULL) && (dest != -1));
1103 do {
1104 Log() << Verbose(0) << "Enter index of source molecule to merge into: ";
1105 cin >> src;
1106 srcmol = molecules->ReturnIndex(src);
1107 } while ((srcmol == NULL) && (src != -1));
1108 if ((src != -1) && (dest != -1))
1109 molecules->SimpleMerge(srcmol, destmol);
1110 }
1111 }
1112 break;
1113 }
1114};
1115
1116
1117/********************************************** Test routine **************************************/
1118
1119/** Is called always as option 'T' in the menu.
1120 * \param *molecules list of molecules
1121 */
1122void menu::testroutine(MoleculeListClass *molecules)
1123{
1124 // the current test routine checks the functionality of the KeySet&Graph concept:
1125 // We want to have a multiindex (the KeySet) describing a unique subgraph
1126 int i, comp, counter=0;
1127
1128 // create a clone
1129 molecule *mol = NULL;
1130 if (molecules->ListOfMolecules.size() != 0) // clone
1131 mol = (molecules->ListOfMolecules.front())->CopyMolecule();
1132 else {
1133 eLog() << Verbose(0) << "I don't have anything to test on ... ";
1134 performCriticalExit();
1135 return;
1136 }
1137 atom *Walker = mol->start;
1138
1139 // generate some KeySets
1140 Log() << Verbose(0) << "Generating KeySets." << endl;
1141 KeySet TestSets[mol->AtomCount+1];
1142 i=1;
1143 while (Walker->next != mol->end) {
1144 Walker = Walker->next;
1145 for (int j=0;j<i;j++) {
1146 TestSets[j].insert(Walker->nr);
1147 }
1148 i++;
1149 }
1150 Log() << Verbose(0) << "Testing insertion of already present item in KeySets." << endl;
1151 KeySetTestPair test;
1152 test = TestSets[mol->AtomCount-1].insert(Walker->nr);
1153 if (test.second) {
1154 Log() << Verbose(1) << "Insertion worked?!" << endl;
1155 } else {
1156 Log() << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl;
1157 }
1158 TestSets[mol->AtomCount].insert(mol->end->previous->nr);
1159 TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr);
1160
1161 // constructing Graph structure
1162 Log() << Verbose(0) << "Generating Subgraph class." << endl;
1163 Graph Subgraphs;
1164
1165 // insert KeySets into Subgraphs
1166 Log() << Verbose(0) << "Inserting KeySets into Subgraph class." << endl;
1167 for (int j=0;j<mol->AtomCount;j++) {
1168 Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.)));
1169 }
1170 Log() << Verbose(0) << "Testing insertion of already present item in Subgraph." << endl;
1171 GraphTestPair test2;
1172 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.)));
1173 if (test2.second) {
1174 Log() << Verbose(1) << "Insertion worked?!" << endl;
1175 } else {
1176 Log() << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl;
1177 }
1178
1179 // show graphs
1180 Log() << Verbose(0) << "Showing Subgraph's contents, checking that it's sorted." << endl;
1181 Graph::iterator A = Subgraphs.begin();
1182 while (A != Subgraphs.end()) {
1183 Log() << Verbose(0) << (*A).second.first << ": ";
1184 KeySet::iterator key = (*A).first.begin();
1185 comp = -1;
1186 while (key != (*A).first.end()) {
1187 if ((*key) > comp)
1188 Log() << Verbose(0) << (*key) << " ";
1189 else
1190 Log() << Verbose(0) << (*key) << "! ";
1191 comp = (*key);
1192 key++;
1193 }
1194 Log() << Verbose(0) << endl;
1195 A++;
1196 }
1197 delete(mol);
1198};
1199
1200menu::menu()
1201{
1202 // TODO Auto-generated constructor stub
1203}
1204
1205menu::~menu()
1206{
1207 // TODO Auto-generated destructor stub
1208}
1209
1210void menu::perform(MoleculeListClass *molecules, config *configuration, periodentafel *periode, char *ConfigFileName)
1211{
1212 char choice;
1213 int j;
1214 Log() << Verbose(0) << endl << "Now comes the real construction..." << endl;
1215 do {
1216 Log() << Verbose(0) << endl << endl;
1217 Log() << Verbose(0) << "============Molecule list=======================" << endl;
1218 molecules->Enumerate((ofstream *)&cout);
1219 Log() << Verbose(0) << "============Menu===============================" << endl;
1220 Log() << Verbose(0) << "a - set molecule (in)active" << endl;
1221 Log() << Verbose(0) << "e - edit molecules (load, parse, save)" << endl;
1222 Log() << Verbose(0) << "g - globally manipulate atoms in molecule" << endl;
1223 Log() << Verbose(0) << "M - Merge molecules" << endl;
1224 Log() << Verbose(0) << "m - manipulate atoms" << endl;
1225 Log() << Verbose(0) << "-----------------------------------------------" << endl;
1226 Log() << Verbose(0) << "c - edit the current configuration" << endl;
1227 Log() << Verbose(0) << "-----------------------------------------------" << endl;
1228 Log() << Verbose(0) << "s - save current setup to config file" << endl;
1229 Log() << Verbose(0) << "T - call the current test routine" << endl;
1230 Log() << Verbose(0) << "q - quit" << endl;
1231 Log() << Verbose(0) << "===============================================" << endl;
1232 Log() << Verbose(0) << "Input: ";
1233 cin >> choice;
1234
1235 switch (choice) {
1236 case 'a': // (in)activate molecule
1237 {
1238 Log() << Verbose(0) << "Enter index of molecule: ";
1239 cin >> j;
1240 for(MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
1241 if ((*ListRunner)->IndexNr == j)
1242 (*ListRunner)->ActiveFlag = !(*ListRunner)->ActiveFlag;
1243 }
1244 break;
1245
1246 case 'c': // edit each field of the configuration
1247 configuration->Edit();
1248 break;
1249
1250 case 'e': // create molecule
1251 EditMolecules(periode, molecules);
1252 break;
1253
1254 case 'g': // manipulate molecules
1255 ManipulateMolecules(periode, molecules, configuration);
1256 break;
1257
1258 case 'M': // merge molecules
1259 MergeMolecules(periode, molecules);
1260 break;
1261
1262 case 'm': // manipulate atoms
1263 ManipulateAtoms(periode, molecules, configuration);
1264 break;
1265
1266 case 'q': // quit
1267 break;
1268
1269 case 's': // save to config file
1270 SaveConfig(ConfigFileName, configuration, periode, molecules);
1271 break;
1272
1273 case 'T':
1274 testroutine(molecules);
1275 break;
1276
1277 default:
1278 break;
1279 };
1280 } while (choice != 'q');
1281};
1282
1283/** Tries given filename or standard on saving the config file.
1284 * \param *ConfigFileName name of file
1285 * \param *configuration pointer to configuration structure with all the values
1286 * \param *periode pointer to periodentafel structure with all the elements
1287 * \param *molecules list of molecules structure with all the atoms and coordinates
1288 */
1289void menu::SaveConfig(char *ConfigFileName, config *configuration, periodentafel *periode, MoleculeListClass *molecules)
1290{
1291 char filename[MAXSTRINGSIZE];
1292 ofstream output;
1293 molecule *mol = new molecule(periode);
1294
1295 if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) {
1296 eLog() << Verbose(2) << "config is found under different path then stated in config file::defaultpath!" << endl;
1297 }
1298
1299
1300 // first save as PDB data
1301 if (ConfigFileName != NULL)
1302 strcpy(filename, ConfigFileName);
1303 else
1304 strcpy(filename,"main_pcp_linux");
1305 Log() << Verbose(0) << "Saving as pdb input ";
1306 if (configuration->SavePDB(filename, molecules))
1307 Log() << Verbose(0) << "done." << endl;
1308 else
1309 Log() << Verbose(0) << "failed." << endl;
1310
1311 // then save as tremolo data file
1312 if (ConfigFileName != NULL)
1313 strcpy(filename, ConfigFileName);
1314 else
1315 strcpy(filename,"main_pcp_linux");
1316 Log() << Verbose(0) << "Saving as tremolo data input ";
1317 if (configuration->SaveTREMOLO(filename, molecules))
1318 Log() << Verbose(0) << "done." << endl;
1319 else
1320 Log() << Verbose(0) << "failed." << endl;
1321
1322 // translate each to its center and merge all molecules in MoleculeListClass into this molecule
1323 int N = molecules->ListOfMolecules.size();
1324 int *src = new int[N];
1325 N=0;
1326 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
1327 src[N++] = (*ListRunner)->IndexNr;
1328 (*ListRunner)->Translate(&(*ListRunner)->Center);
1329 }
1330 molecules->SimpleMultiAdd(mol, src, N);
1331 delete[](src);
1332
1333 // ... and translate back
1334 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
1335 (*ListRunner)->Center.Scale(-1.);
1336 (*ListRunner)->Translate(&(*ListRunner)->Center);
1337 (*ListRunner)->Center.Scale(-1.);
1338 }
1339
1340 Log() << Verbose(0) << "Storing configuration ... " << endl;
1341 // get correct valence orbitals
1342 mol->CalculateOrbitals(*configuration);
1343 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble;
1344 if (ConfigFileName != NULL) { // test the file name
1345 strcpy(filename, ConfigFileName);
1346 output.open(filename, ios::trunc);
1347 } else if (strlen(configuration->configname) != 0) {
1348 strcpy(filename, configuration->configname);
1349 output.open(configuration->configname, ios::trunc);
1350 } else {
1351 strcpy(filename, DEFAULTCONFIG);
1352 output.open(DEFAULTCONFIG, ios::trunc);
1353 }
1354 output.close();
1355 output.clear();
1356 Log() << Verbose(0) << "Saving of config file ";
1357 if (configuration->Save(filename, periode, mol))
1358 Log() << Verbose(0) << "successful." << endl;
1359 else
1360 Log() << Verbose(0) << "failed." << endl;
1361
1362 // and save to xyz file
1363 if (ConfigFileName != NULL) {
1364 strcpy(filename, ConfigFileName);
1365 strcat(filename, ".xyz");
1366 output.open(filename, ios::trunc);
1367 }
1368 else {
1369 strcpy(filename,"main_pcp_linux");
1370 strcat(filename, ".xyz");
1371 output.open(filename, ios::trunc);
1372 }
1373 Log() << Verbose(0) << "Saving of XYZ file ";
1374 if (mol->MDSteps <= 1) {
1375 if (mol->OutputXYZ(&output))
1376 Log() << Verbose(0) << "successful." << endl;
1377 else
1378 Log() << Verbose(0) << "failed." << endl;
1379 } else {
1380 if (mol->OutputTrajectoriesXYZ(&output))
1381 Log() << Verbose(0) << "successful." << endl;
1382 else
1383 Log() << Verbose(0) << "failed." << endl;
1384 }
1385 output.close();
1386 output.clear();
1387
1388 // and save as MPQC configuration
1389 if (ConfigFileName != NULL)
1390 strcpy(filename, ConfigFileName);
1391 else
1392 strcpy(filename,"main_pcp_linux");
1393 Log() << Verbose(0) << "Saving as mpqc input ";
1394 if (configuration->SaveMPQC(filename, mol))
1395 Log() << Verbose(0) << "done." << endl;
1396 else
1397 Log() << Verbose(0) << "failed." << endl;
1398
1399 if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) {
1400 eLog() << Verbose(2) << "config is found under different path then stated in config file::defaultpath!" << endl;
1401 }
1402
1403 delete(mol);
1404};
Note: See TracBrowser for help on using the repository browser.