source: src/molecule.cpp@ 1a6bda

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 1a6bda was 9df680, checked in by Frederik Heber <heber@…>, 14 years ago

FIX: FillVoidWithMolecule() now centers filler molecule at its center of gravity.

  • this is the only sensible option if we later rotate the molecule.
  • atom::clone() reduced a lot, as copy constructors contains it all.
  • FillVoidWithMolecule() - filler is now selected to reside entirely within the domain. Otherwise, we seg'fault on save on exit, as one of the father atoms for all copied atoms is missing and hence, we cannot look at its additional...Data for various parsers.
  • new function molecule::removeAtomsInMolecule() which destroys all the molecule's atoms.

TESTFIXES:

  • Filling/3: filled water box has changed due to different center of water molecules.
  • Property mode set to 100755
File size: 39.9 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/** \file molecules.cpp
9 *
10 * Functions for the class molecule.
11 *
12 */
13
14// include config.h
15#ifdef HAVE_CONFIG_H
16#include <config.h>
17#endif
18
19#include "CodePatterns/MemDebug.hpp"
20
21#include <cstring>
22#include <boost/bind.hpp>
23#include <boost/foreach.hpp>
24
25#include <gsl/gsl_inline.h>
26#include <gsl/gsl_heapsort.h>
27
28#include "World.hpp"
29#include "atom.hpp"
30#include "bond.hpp"
31#include "config.hpp"
32#include "element.hpp"
33#include "graph.hpp"
34#include "Helpers/helpers.hpp"
35#include "LinearAlgebra/leastsquaremin.hpp"
36#include "linkedcell.hpp"
37#include "lists.hpp"
38#include "CodePatterns/Log.hpp"
39#include "molecule.hpp"
40
41#include "periodentafel.hpp"
42#include "tesselation.hpp"
43#include "LinearAlgebra/Vector.hpp"
44#include "LinearAlgebra/RealSpaceMatrix.hpp"
45#include "World.hpp"
46#include "Box.hpp"
47#include "LinearAlgebra/Plane.hpp"
48#include "Exceptions/LinearDependenceException.hpp"
49
50#include "CodePatterns/enumeration.hpp"
51
52/************************************* Functions for class molecule *********************************/
53
54/** Constructor of class molecule.
55 * Initialises molecule list with correctly referenced start and end, and sets molecule::last_atom to zero.
56 */
57molecule::molecule(const periodentafel * const teil) :
58 Observable("molecule"),
59 elemente(teil), MDSteps(0), BondCount(0), NoNonHydrogen(0), NoNonBonds(0),
60 NoCyclicBonds(0), BondDistance(0.), ActiveFlag(false), IndexNr(-1),
61 AtomCount(this,boost::bind(&molecule::doCountAtoms,this),"AtomCount"), last_atom(0), InternalPointer(atoms.begin())
62{
63
64 strcpy(name,World::getInstance().getDefaultName().c_str());
65};
66
67molecule *NewMolecule(){
68 return new molecule(World::getInstance().getPeriode());
69}
70
71/** Destructor of class molecule.
72 * Initialises molecule list with correctly referenced start and end, and sets molecule::last_atom to zero.
73 */
74molecule::~molecule()
75{
76 CleanupMolecule();
77};
78
79
80void DeleteMolecule(molecule *mol){
81 delete mol;
82}
83
84// getter and setter
85const std::string molecule::getName() const{
86 return std::string(name);
87}
88
89int molecule::getAtomCount() const{
90 return *AtomCount;
91}
92
93void molecule::setName(const std::string _name){
94 OBSERVE;
95 cout << "Set name of molecule " << getId() << " to " << _name << endl;
96 strncpy(name,_name.c_str(),MAXSTRINGSIZE);
97}
98
99bool molecule::changeId(moleculeId_t newId){
100 // first we move ourselves in the world
101 // the world lets us know if that succeeded
102 if(World::getInstance().changeMoleculeId(id,newId,this)){
103 id = newId;
104 return true;
105 }
106 else{
107 return false;
108 }
109}
110
111
112moleculeId_t molecule::getId() const {
113 return id;
114}
115
116void molecule::setId(moleculeId_t _id){
117 id =_id;
118}
119
120const Formula &molecule::getFormula() const {
121 return formula;
122}
123
124unsigned int molecule::getElementCount() const{
125 return formula.getElementCount();
126}
127
128bool molecule::hasElement(const element *element) const{
129 return formula.hasElement(element);
130}
131
132bool molecule::hasElement(atomicNumber_t Z) const{
133 return formula.hasElement(Z);
134}
135
136bool molecule::hasElement(const string &shorthand) const{
137 return formula.hasElement(shorthand);
138}
139
140/************************** Access to the List of Atoms ****************/
141
142
143molecule::iterator molecule::begin(){
144 return molecule::iterator(atoms.begin(),this);
145}
146
147molecule::const_iterator molecule::begin() const{
148 return atoms.begin();
149}
150
151molecule::iterator molecule::end(){
152 return molecule::iterator(atoms.end(),this);
153}
154
155molecule::const_iterator molecule::end() const{
156 return atoms.end();
157}
158
159bool molecule::empty() const
160{
161 return (begin() == end());
162}
163
164size_t molecule::size() const
165{
166 size_t counter = 0;
167 for (molecule::const_iterator iter = begin(); iter != end (); ++iter)
168 counter++;
169 return counter;
170}
171
172molecule::const_iterator molecule::erase( const_iterator loc )
173{
174 OBSERVE;
175 molecule::const_iterator iter = loc;
176 iter--;
177 atom* atom = *loc;
178 atomIds.erase( atom->getId() );
179 atoms.remove( atom );
180 formula-=atom->getType();
181 atom->removeFromMolecule();
182 return iter;
183}
184
185molecule::const_iterator molecule::erase( atom * key )
186{
187 OBSERVE;
188 molecule::const_iterator iter = find(key);
189 if (iter != end()){
190 atomIds.erase( key->getId() );
191 atoms.remove( key );
192 formula-=key->getType();
193 key->removeFromMolecule();
194 }
195 return iter;
196}
197
198molecule::const_iterator molecule::find ( atom * key ) const
199{
200 molecule::const_iterator iter;
201 for (molecule::const_iterator Runner = begin(); Runner != end(); ++Runner) {
202 if (*Runner == key)
203 return molecule::const_iterator(Runner);
204 }
205 return molecule::const_iterator(atoms.end());
206}
207
208pair<molecule::iterator,bool> molecule::insert ( atom * const key )
209{
210 OBSERVE;
211 pair<atomIdSet::iterator,bool> res = atomIds.insert(key->getId());
212 if (res.second) { // push atom if went well
213 atoms.push_back(key);
214 formula+=key->getType();
215 return pair<iterator,bool>(molecule::iterator(--end()),res.second);
216 } else {
217 return pair<iterator,bool>(molecule::iterator(end()),res.second);
218 }
219}
220
221bool molecule::containsAtom(atom* key){
222 return (find(key) != end());
223}
224
225/** Adds given atom \a *pointer from molecule list.
226 * Increases molecule::last_atom and gives last number to added atom and names it according to its element::abbrev and molecule::AtomCount
227 * \param *pointer allocated and set atom
228 * \return true - succeeded, false - atom not found in list
229 */
230bool molecule::AddAtom(atom *pointer)
231{
232 OBSERVE;
233 if (pointer != NULL) {
234 pointer->sort = &pointer->nr;
235 if (pointer->getType() != NULL) {
236 if (pointer->getType()->getAtomicNumber() != 1)
237 NoNonHydrogen++;
238 if(pointer->getName() == "Unknown"){
239 stringstream sstr;
240 sstr << pointer->getType()->getSymbol() << pointer->nr+1;
241 pointer->setName(sstr.str());
242 }
243 }
244 insert(pointer);
245 pointer->setMolecule(this);
246 }
247 return true;
248};
249
250/** Adds a copy of the given atom \a *pointer from molecule list.
251 * Increases molecule::last_atom and gives last number to added atom.
252 * \param *pointer allocated and set atom
253 * \return pointer to the newly added atom
254 */
255atom * molecule::AddCopyAtom(atom *pointer)
256{
257 atom *retval = NULL;
258 OBSERVE;
259 if (pointer != NULL) {
260 atom *walker = pointer->clone();
261 walker->setName(pointer->getName());
262 walker->nr = last_atom++; // increase number within molecule
263 insert(walker);
264 if ((pointer->getType() != NULL) && (pointer->getType()->getAtomicNumber() != 1))
265 NoNonHydrogen++;
266 walker->setMolecule(this);
267 retval=walker;
268 }
269 return retval;
270};
271
272/** Adds a Hydrogen atom in replacement for the given atom \a *partner in bond with a *origin.
273 * Here, we have to distinguish between single, double or triple bonds as stated by \a BondDegree, that each demand
274 * a different scheme when adding \a *replacement atom for the given one.
275 * -# Single Bond: Simply add new atom with bond distance rescaled to typical hydrogen one
276 * -# Double Bond: Here, we need the **BondList of the \a *origin atom, by scanning for the other bonds instead of
277 * *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector().
278 * The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two
279 * replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the
280 * element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two
281 * hydrogens forming this angle with *origin.
282 * -# Triple Bond: The idea is to set up a tetraoid (C1-H1-H2-H3) (however the lengths \f$b\f$ of the sides of the base
283 * triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be
284 * determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin):
285 * We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2).
286 * \f[ h = l \cdot \cos{\left (\frac{\alpha}{2} \right )} \qquad b = 2l \cdot \sin{\left (\frac{\alpha}{2} \right)} \quad \rightarrow \quad d = l \cdot \sqrt{\cos^2{\left (\frac{\alpha}{2} \right)}-\frac{1}{3}\cdot\sin^2{\left (\frac{\alpha}{2}\right )}}
287 * \f]
288 * vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates
289 * the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above.
290 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that
291 * the median lines in an isosceles triangle meet in the center point with a ratio 2:1.
292 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2}
293 * \f]
294 * as the coordination of all three atoms in the coordinate system of these three vectors:
295 * \f$\pmatrix{d & f & 0}\f$, \f$\pmatrix{d & -0.5 \cdot f & g}\f$ and \f$\pmatrix{d & -0.5 \cdot f & -g}\f$.
296 *
297 * \param *out output stream for debugging
298 * \param *Bond pointer to bond between \a *origin and \a *replacement
299 * \param *TopOrigin son of \a *origin of upper level molecule (the atom added to this molecule as a copy of \a *origin)
300 * \param *origin pointer to atom which acts as the origin for scaling the added hydrogen to correct bond length
301 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule
302 * \param isAngstroem whether the coordination of the given atoms is in AtomicLength (false) or Angstrom(true)
303 * \return number of atoms added, if < bond::BondDegree then something went wrong
304 * \todo double and triple bonds splitting (always use the tetraeder angle!)
305 */
306bool molecule::AddHydrogenReplacementAtom(bond *TopBond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bool IsAngstroem)
307{
308 bool AllWentWell = true; // flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit
309 OBSERVE;
310 double bondlength; // bond length of the bond to be replaced/cut
311 double bondangle; // bond angle of the bond to be replaced/cut
312 double BondRescale; // rescale value for the hydrogen bond length
313 bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane
314 atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added
315 double b,l,d,f,g, alpha, factors[NDIM]; // hold temporary values in triple bond case for coordination determination
316 Vector Orthovector1, Orthovector2; // temporary vectors in coordination construction
317 Vector InBondvector; // vector in direction of *Bond
318 const RealSpaceMatrix &matrix = World::getInstance().getDomain().getM();
319 bond *Binder = NULL;
320
321// Log() << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl;
322 // create vector in direction of bond
323 InBondvector = TopReplacement->getPosition() - TopOrigin->getPosition();
324 bondlength = InBondvector.Norm();
325
326 // is greater than typical bond distance? Then we have to correct periodically
327 // the problem is not the H being out of the box, but InBondvector have the wrong direction
328 // due to TopReplacement or Origin being on the wrong side!
329 if (bondlength > BondDistance) {
330// Log() << Verbose(4) << "InBondvector is: ";
331// InBondvector.Output(out);
332// Log() << Verbose(0) << endl;
333 Orthovector1.Zero();
334 for (int i=NDIM;i--;) {
335 l = TopReplacement->at(i) - TopOrigin->at(i);
336 if (fabs(l) > BondDistance) { // is component greater than bond distance
337 Orthovector1[i] = (l < 0) ? -1. : +1.;
338 } // (signs are correct, was tested!)
339 }
340 Orthovector1 *= matrix;
341 InBondvector -= Orthovector1; // subtract just the additional translation
342 bondlength = InBondvector.Norm();
343// Log() << Verbose(4) << "Corrected InBondvector is now: ";
344// InBondvector.Output(out);
345// Log() << Verbose(0) << endl;
346 } // periodic correction finished
347
348 InBondvector.Normalize();
349 // get typical bond length and store as scale factor for later
350 ASSERT(TopOrigin->getType() != NULL, "AddHydrogenReplacementAtom: element of TopOrigin is not given.");
351 BondRescale = TopOrigin->getType()->getHBondDistance(TopBond->BondDegree-1);
352 if (BondRescale == -1) {
353 DoeLog(1) && (eLog()<< Verbose(1) << "There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->getName() << "<->" << TopReplacement->getName() << ") of degree " << TopBond->BondDegree << "!" << endl);
354 return false;
355 BondRescale = bondlength;
356 } else {
357 if (!IsAngstroem)
358 BondRescale /= (1.*AtomicLengthToAngstroem);
359 }
360
361 // discern single, double and triple bonds
362 switch(TopBond->BondDegree) {
363 case 1:
364 FirstOtherAtom = World::getInstance().createAtom(); // new atom
365 FirstOtherAtom->setType(1); // element is Hydrogen
366 FirstOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
367 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
368 if (TopReplacement->getType()->getAtomicNumber() == 1) { // neither rescale nor replace if it's already hydrogen
369 FirstOtherAtom->father = TopReplacement;
370 BondRescale = bondlength;
371 } else {
372 FirstOtherAtom->father = NULL; // if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father
373 }
374 InBondvector *= BondRescale; // rescale the distance vector to Hydrogen bond length
375 FirstOtherAtom->setPosition(TopOrigin->getPosition() + InBondvector); // set coordination to origin and add distance vector to replacement atom
376 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
377// Log() << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
378// FirstOtherAtom->x.Output(out);
379// Log() << Verbose(0) << endl;
380 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
381 Binder->Cyclic = false;
382 Binder->Type = TreeEdge;
383 break;
384 case 2:
385 // determine two other bonds (warning if there are more than two other) plus valence sanity check
386 for (BondList::const_iterator Runner = TopOrigin->ListOfBonds.begin(); Runner != TopOrigin->ListOfBonds.end(); (++Runner)) {
387 if ((*Runner) != TopBond) {
388 if (FirstBond == NULL) {
389 FirstBond = (*Runner);
390 FirstOtherAtom = (*Runner)->GetOtherAtom(TopOrigin);
391 } else if (SecondBond == NULL) {
392 SecondBond = (*Runner);
393 SecondOtherAtom = (*Runner)->GetOtherAtom(TopOrigin);
394 } else {
395 DoeLog(2) && (eLog()<< Verbose(2) << "Detected more than four bonds for atom " << TopOrigin->getName());
396 }
397 }
398 }
399 if (SecondOtherAtom == NULL) { // then we have an atom with valence four, but only 3 bonds: one to replace and one which is TopBond (third is FirstBond)
400 SecondBond = TopBond;
401 SecondOtherAtom = TopReplacement;
402 }
403 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all
404// Log() << Verbose(3) << "Regarding the double bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") to be constructed: Taking " << FirstOtherAtom->Name << " and " << SecondOtherAtom->Name << " along with " << TopOrigin->Name << " to determine orthogonal plane." << endl;
405
406 // determine the plane of these two with the *origin
407 try {
408 Orthovector1 =Plane(TopOrigin->getPosition(), FirstOtherAtom->getPosition(), SecondOtherAtom->getPosition()).getNormal();
409 }
410 catch(LinearDependenceException &excp){
411 Log() << Verbose(0) << excp;
412 // TODO: figure out what to do with the Orthovector in this case
413 AllWentWell = false;
414 }
415 } else {
416 Orthovector1.GetOneNormalVector(InBondvector);
417 }
418 //Log() << Verbose(3)<< "Orthovector1: ";
419 //Orthovector1.Output(out);
420 //Log() << Verbose(0) << endl;
421 // orthogonal vector and bond vector between origin and replacement form the new plane
422 Orthovector1.MakeNormalTo(InBondvector);
423 Orthovector1.Normalize();
424 //Log() << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl;
425
426 // create the two Hydrogens ...
427 FirstOtherAtom = World::getInstance().createAtom();
428 SecondOtherAtom = World::getInstance().createAtom();
429 FirstOtherAtom->setType(1);
430 SecondOtherAtom->setType(1);
431 FirstOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
432 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
433 SecondOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
434 SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
435 FirstOtherAtom->father = NULL; // we are just an added hydrogen with no father
436 SecondOtherAtom->father = NULL; // we are just an added hydrogen with no father
437 bondangle = TopOrigin->getType()->getHBondAngle(1);
438 if (bondangle == -1) {
439 DoeLog(1) && (eLog()<< Verbose(1) << "There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->getName() << "<->" << TopReplacement->getName() << ") of degree " << TopBond->BondDegree << "!" << endl);
440 return false;
441 bondangle = 0;
442 }
443 bondangle *= M_PI/180./2.;
444// Log() << Verbose(3) << "ReScaleCheck: InBondvector ";
445// InBondvector.Output(out);
446// Log() << Verbose(0) << endl;
447// Log() << Verbose(3) << "ReScaleCheck: Orthovector ";
448// Orthovector1.Output(out);
449// Log() << Verbose(0) << endl;
450// Log() << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl;
451 FirstOtherAtom->Zero();
452 SecondOtherAtom->Zero();
453 for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction)
454 FirstOtherAtom->set(i, InBondvector[i] * cos(bondangle) + Orthovector1[i] * (sin(bondangle)));
455 SecondOtherAtom->set(i, InBondvector[i] * cos(bondangle) + Orthovector1[i] * (-sin(bondangle)));
456 }
457 FirstOtherAtom->Scale(BondRescale); // rescale by correct BondDistance
458 SecondOtherAtom->Scale(BondRescale);
459 //Log() << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl;
460 *FirstOtherAtom += TopOrigin->getPosition();
461 *SecondOtherAtom += TopOrigin->getPosition();
462 // ... and add to molecule
463 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
464 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
465// Log() << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
466// FirstOtherAtom->x.Output(out);
467// Log() << Verbose(0) << endl;
468// Log() << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
469// SecondOtherAtom->x.Output(out);
470// Log() << Verbose(0) << endl;
471 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
472 Binder->Cyclic = false;
473 Binder->Type = TreeEdge;
474 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
475 Binder->Cyclic = false;
476 Binder->Type = TreeEdge;
477 break;
478 case 3:
479 // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid)
480 FirstOtherAtom = World::getInstance().createAtom();
481 SecondOtherAtom = World::getInstance().createAtom();
482 ThirdOtherAtom = World::getInstance().createAtom();
483 FirstOtherAtom->setType(1);
484 SecondOtherAtom->setType(1);
485 ThirdOtherAtom->setType(1);
486 FirstOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
487 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
488 SecondOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
489 SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
490 ThirdOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
491 ThirdOtherAtom->FixedIon = TopReplacement->FixedIon;
492 FirstOtherAtom->father = NULL; // we are just an added hydrogen with no father
493 SecondOtherAtom->father = NULL; // we are just an added hydrogen with no father
494 ThirdOtherAtom->father = NULL; // we are just an added hydrogen with no father
495
496 // we need to vectors orthonormal the InBondvector
497 AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(InBondvector);
498// Log() << Verbose(3) << "Orthovector1: ";
499// Orthovector1.Output(out);
500// Log() << Verbose(0) << endl;
501 try{
502 Orthovector2 = Plane(InBondvector, Orthovector1,0).getNormal();
503 }
504 catch(LinearDependenceException &excp) {
505 Log() << Verbose(0) << excp;
506 AllWentWell = false;
507 }
508// Log() << Verbose(3) << "Orthovector2: ";
509// Orthovector2.Output(out);
510// Log() << Verbose(0) << endl;
511
512 // create correct coordination for the three atoms
513 alpha = (TopOrigin->getType()->getHBondAngle(2))/180.*M_PI/2.; // retrieve triple bond angle from database
514 l = BondRescale; // desired bond length
515 b = 2.*l*sin(alpha); // base length of isosceles triangle
516 d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.); // length for InBondvector
517 f = b/sqrt(3.); // length for Orthvector1
518 g = b/2.; // length for Orthvector2
519// Log() << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl;
520// Log() << Verbose(3) << "The three Bond lengths: " << sqrt(d*d+f*f) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << endl;
521 factors[0] = d;
522 factors[1] = f;
523 factors[2] = 0.;
524 FirstOtherAtom->LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
525 factors[1] = -0.5*f;
526 factors[2] = g;
527 SecondOtherAtom->LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
528 factors[2] = -g;
529 ThirdOtherAtom->LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
530
531 // rescale each to correct BondDistance
532// FirstOtherAtom->x.Scale(&BondRescale);
533// SecondOtherAtom->x.Scale(&BondRescale);
534// ThirdOtherAtom->x.Scale(&BondRescale);
535
536 // and relative to *origin atom
537 *FirstOtherAtom += TopOrigin->getPosition();
538 *SecondOtherAtom += TopOrigin->getPosition();
539 *ThirdOtherAtom += TopOrigin->getPosition();
540
541 // ... and add to molecule
542 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
543 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
544 AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom);
545// Log() << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
546// FirstOtherAtom->x.Output(out);
547// Log() << Verbose(0) << endl;
548// Log() << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
549// SecondOtherAtom->x.Output(out);
550// Log() << Verbose(0) << endl;
551// Log() << Verbose(4) << "Added " << *ThirdOtherAtom << " at: ";
552// ThirdOtherAtom->x.Output(out);
553// Log() << Verbose(0) << endl;
554 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
555 Binder->Cyclic = false;
556 Binder->Type = TreeEdge;
557 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
558 Binder->Cyclic = false;
559 Binder->Type = TreeEdge;
560 Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1);
561 Binder->Cyclic = false;
562 Binder->Type = TreeEdge;
563 break;
564 default:
565 DoeLog(1) && (eLog()<< Verbose(1) << "BondDegree does not state single, double or triple bond!" << endl);
566 AllWentWell = false;
567 break;
568 }
569
570// Log() << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl;
571 return AllWentWell;
572};
573
574/** Adds given atom \a *pointer from molecule list.
575 * Increases molecule::last_atom and gives last number to added atom.
576 * \param filename name and path of xyz file
577 * \return true - succeeded, false - file not found
578 */
579bool molecule::AddXYZFile(string filename)
580{
581
582 istringstream *input = NULL;
583 int NumberOfAtoms = 0; // atom number in xyz read
584 int i, j; // loop variables
585 atom *Walker = NULL; // pointer to added atom
586 char shorthand[3]; // shorthand for atom name
587 ifstream xyzfile; // xyz file
588 string line; // currently parsed line
589 double x[3]; // atom coordinates
590
591 xyzfile.open(filename.c_str());
592 if (!xyzfile)
593 return false;
594
595 OBSERVE;
596 getline(xyzfile,line,'\n'); // Read numer of atoms in file
597 input = new istringstream(line);
598 *input >> NumberOfAtoms;
599 DoLog(0) && (Log() << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl);
600 getline(xyzfile,line,'\n'); // Read comment
601 DoLog(1) && (Log() << Verbose(1) << "Comment: " << line << endl);
602
603 if (MDSteps == 0) // no atoms yet present
604 MDSteps++;
605 for(i=0;i<NumberOfAtoms;i++){
606 Walker = World::getInstance().createAtom();
607 getline(xyzfile,line,'\n');
608 istringstream *item = new istringstream(line);
609 //istringstream input(line);
610 //Log() << Verbose(1) << "Reading: " << line << endl;
611 *item >> shorthand;
612 *item >> x[0];
613 *item >> x[1];
614 *item >> x[2];
615 Walker->setType(elemente->FindElement(shorthand));
616 if (Walker->getType() == NULL) {
617 DoeLog(1) && (eLog()<< Verbose(1) << "Could not parse the element at line: '" << line << "', setting to H.");
618 Walker->setType(1);
619 }
620 if (Walker->Trajectory.R.size() <= (unsigned int)MDSteps) {
621 Walker->Trajectory.R.resize(MDSteps+10);
622 Walker->Trajectory.U.resize(MDSteps+10);
623 Walker->Trajectory.F.resize(MDSteps+10);
624 }
625 Walker->setPosition(Vector(x));
626 for(j=NDIM;j--;) {
627 Walker->Trajectory.R.at(MDSteps-1)[j] = x[j];
628 Walker->Trajectory.U.at(MDSteps-1)[j] = 0;
629 Walker->Trajectory.F.at(MDSteps-1)[j] = 0;
630 }
631 AddAtom(Walker); // add to molecule
632 delete(item);
633 }
634 xyzfile.close();
635 delete(input);
636 return true;
637};
638
639/** Creates a copy of this molecule.
640 * \return copy of molecule
641 */
642molecule *molecule::CopyMolecule() const
643{
644 molecule *copy = World::getInstance().createMolecule();
645
646 // copy all atoms
647 for_each(atoms.begin(),atoms.end(),bind1st(mem_fun(&molecule::AddCopyAtom),copy));
648
649 // copy all bonds
650 for(molecule::const_iterator AtomRunner = begin(); AtomRunner != end(); ++AtomRunner)
651 for(BondList::const_iterator BondRunner = (*AtomRunner)->ListOfBonds.begin(); BondRunner != (*AtomRunner)->ListOfBonds.end(); ++BondRunner)
652 if ((*BondRunner)->leftatom == *AtomRunner) {
653 bond *Binder = (*BondRunner);
654 // get the pendant atoms of current bond in the copy molecule
655 atomSet::iterator leftiter=find_if(copy->atoms.begin(),copy->atoms.end(),bind2nd(mem_fun(&atom::isFather),Binder->leftatom));
656 atomSet::iterator rightiter=find_if(copy->atoms.begin(),copy->atoms.end(),bind2nd(mem_fun(&atom::isFather),Binder->rightatom));
657 ASSERT(leftiter!=copy->atoms.end(),"No copy of original left atom for bond copy found");
658 ASSERT(leftiter!=copy->atoms.end(),"No copy of original right atom for bond copy found");
659 atom *LeftAtom = *leftiter;
660 atom *RightAtom = *rightiter;
661
662 bond *NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);
663 NewBond->Cyclic = Binder->Cyclic;
664 if (Binder->Cyclic)
665 copy->NoCyclicBonds++;
666 NewBond->Type = Binder->Type;
667 }
668 // correct fathers
669 for_each(atoms.begin(),atoms.end(),mem_fun(&atom::CorrectFather));
670
671 // copy values
672 if (hasBondStructure()) { // if adjaceny list is present
673 copy->BondDistance = BondDistance;
674 }
675
676 return copy;
677};
678
679
680/** Destroys all atoms inside this molecule.
681 */
682void molecule::removeAtomsinMolecule()
683{
684 // remove each atom from world
685 for(molecule::const_iterator AtomRunner = begin(); !empty(); AtomRunner = begin())
686 World::getInstance().destroyAtom(*AtomRunner);
687};
688
689
690/**
691 * Copies all atoms of a molecule which are within the defined parallelepiped.
692 *
693 * @param offest for the origin of the parallelepiped
694 * @param three vectors forming the matrix that defines the shape of the parallelpiped
695 */
696molecule* molecule::CopyMoleculeFromSubRegion(const Shape &region) const {
697 molecule *copy = World::getInstance().createMolecule();
698
699 BOOST_FOREACH(atom *iter,atoms){
700 if(iter->IsInShape(region)){
701 copy->AddCopyAtom(iter);
702 }
703 }
704
705 //TODO: copy->BuildInducedSubgraph(this);
706
707 return copy;
708}
709
710/** Adds a bond to a the molecule specified by two atoms, \a *first and \a *second.
711 * Also updates molecule::BondCount and molecule::NoNonBonds.
712 * \param *first first atom in bond
713 * \param *second atom in bond
714 * \return pointer to bond or NULL on failure
715 */
716bond * molecule::AddBond(atom *atom1, atom *atom2, int degree)
717{
718 OBSERVE;
719 bond *Binder = NULL;
720
721 // some checks to make sure we are able to create the bond
722 ASSERT(atom1, "First atom in bond-creation was an invalid pointer");
723 ASSERT(atom2, "Second atom in bond-creation was an invalid pointer");
724 ASSERT(FindAtom(atom1->nr),"First atom in bond-creation was not part of molecule");
725 ASSERT(FindAtom(atom2->nr),"Second atom in bond-creation was not part of molecule");
726
727 Binder = new bond(atom1, atom2, degree, BondCount++);
728 atom1->RegisterBond(Binder);
729 atom2->RegisterBond(Binder);
730 if ((atom1->getType() != NULL) && (atom1->getType()->getAtomicNumber() != 1) && (atom2->getType() != NULL) && (atom2->getType()->getAtomicNumber() != 1))
731 NoNonBonds++;
732
733 return Binder;
734};
735
736/** Remove bond from bond chain list and from the both atom::ListOfBonds.
737 * \todo Function not implemented yet
738 * \param *pointer bond pointer
739 * \return true - bound found and removed, false - bond not found/removed
740 */
741bool molecule::RemoveBond(bond *pointer)
742{
743 //DoeLog(1) && (eLog()<< Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl);
744 delete(pointer);
745 return true;
746};
747
748/** Remove every bond from bond chain list that atom \a *BondPartner is a constituent of.
749 * \todo Function not implemented yet
750 * \param *BondPartner atom to be removed
751 * \return true - bounds found and removed, false - bonds not found/removed
752 */
753bool molecule::RemoveBonds(atom *BondPartner)
754{
755 //DoeLog(1) && (eLog()<< Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl);
756 BondList::const_iterator ForeRunner;
757 while (!BondPartner->ListOfBonds.empty()) {
758 ForeRunner = BondPartner->ListOfBonds.begin();
759 RemoveBond(*ForeRunner);
760 }
761 return false;
762};
763
764/** Set molecule::name from the basename without suffix in the given \a *filename.
765 * \param *filename filename
766 */
767void molecule::SetNameFromFilename(const char *filename)
768{
769 int length = 0;
770 const char *molname = strrchr(filename, '/');
771 if (molname != NULL)
772 molname += sizeof(char); // search for filename without dirs
773 else
774 molname = filename; // contains no slashes
775 const char *endname = strchr(molname, '.');
776 if ((endname == NULL) || (endname < molname))
777 length = strlen(molname);
778 else
779 length = strlen(molname) - strlen(endname);
780 cout << "Set name of molecule " << getId() << " to " << molname << endl;
781 strncpy(name, molname, length);
782 name[length]='\0';
783};
784
785/** Sets the molecule::cell_size to the components of \a *dim (rectangular box)
786 * \param *dim vector class
787 */
788void molecule::SetBoxDimension(Vector *dim)
789{
790 RealSpaceMatrix domain;
791 for(int i =0; i<NDIM;++i)
792 domain.at(i,i) = dim->at(i);
793 World::getInstance().setDomain(domain);
794};
795
796/** Removes atom from molecule list and removes all of its bonds.
797 * \param *pointer atom to be removed
798 * \return true - succeeded, false - atom not found in list
799 */
800bool molecule::RemoveAtom(atom *pointer)
801{
802 ASSERT(pointer, "Null pointer passed to molecule::RemoveAtom().");
803 OBSERVE;
804 RemoveBonds(pointer);
805 erase(pointer);
806 return true;
807};
808
809/** Removes atom from molecule list, but does not delete it.
810 * \param *pointer atom to be removed
811 * \return true - succeeded, false - atom not found in list
812 */
813bool molecule::UnlinkAtom(atom *pointer)
814{
815 if (pointer == NULL)
816 return false;
817 erase(pointer);
818 return true;
819};
820
821/** Removes every atom from molecule list.
822 * \return true - succeeded, false - atom not found in list
823 */
824bool molecule::CleanupMolecule()
825{
826 for (molecule::iterator iter = begin(); !empty(); iter = begin())
827 erase(*iter);
828 return empty();
829};
830
831/** Finds an atom specified by its continuous number.
832 * \param Nr number of atom withim molecule
833 * \return pointer to atom or NULL
834 */
835atom * molecule::FindAtom(int Nr) const
836{
837 molecule::const_iterator iter = begin();
838 for (; iter != end(); ++iter)
839 if ((*iter)->nr == Nr)
840 break;
841 if (iter != end()) {
842 //Log() << Verbose(0) << "Found Atom Nr. " << walker->nr << endl;
843 return (*iter);
844 } else {
845 DoLog(0) && (Log() << Verbose(0) << "Atom not found in list." << endl);
846 return NULL;
847 }
848};
849
850/** Asks for atom number, and checks whether in list.
851 * \param *text question before entering
852 */
853atom * molecule::AskAtom(string text)
854{
855 int No;
856 atom *ion = NULL;
857 do {
858 //Log() << Verbose(0) << "============Atom list==========================" << endl;
859 //mol->Output((ofstream *)&cout);
860 //Log() << Verbose(0) << "===============================================" << endl;
861 DoLog(0) && (Log() << Verbose(0) << text);
862 cin >> No;
863 ion = this->FindAtom(No);
864 } while (ion == NULL);
865 return ion;
866};
867
868/** Checks if given coordinates are within cell volume.
869 * \param *x array of coordinates
870 * \return true - is within, false - out of cell
871 */
872bool molecule::CheckBounds(const Vector *x) const
873{
874 const RealSpaceMatrix &domain = World::getInstance().getDomain().getM();
875 bool result = true;
876 for (int i=0;i<NDIM;i++) {
877 result = result && ((x->at(i) >= 0) && (x->at(i) < domain.at(i,i)));
878 }
879 //return result;
880 return true; /// probably not gonna use the check no more
881};
882
883/** Prints molecule to *out.
884 * \param *out output stream
885 */
886bool molecule::Output(ostream * const output) const
887{
888 if (output == NULL) {
889 return false;
890 } else {
891 int AtomNo[MAX_ELEMENTS];
892 memset(AtomNo,0,(MAX_ELEMENTS-1)*sizeof(*AtomNo));
893 enumeration<const element*> elementLookup = formula.enumerateElements();
894 *output << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl;
895 for_each(atoms.begin(),atoms.end(),boost::bind(&atom::OutputArrayIndexed,_1,output,elementLookup,AtomNo,(const char*)0));
896 return true;
897 }
898};
899
900/** Prints molecule with all atomic trajectory positions to *out.
901 * \param *out output stream
902 */
903bool molecule::OutputTrajectories(ofstream * const output) const
904{
905 if (output == NULL) {
906 return false;
907 } else {
908 for (int step = 0; step < MDSteps; step++) {
909 if (step == 0) {
910 *output << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl;
911 } else {
912 *output << "# ====== MD step " << step << " =========" << endl;
913 }
914 int AtomNo[MAX_ELEMENTS];
915 memset(AtomNo,0,(MAX_ELEMENTS-1)*sizeof(*AtomNo));
916 enumeration<const element*> elementLookup = formula.enumerateElements();
917 for_each(atoms.begin(),atoms.end(),boost::bind(&atom::OutputTrajectory,_1,output,elementLookup, AtomNo, (const int)step));
918 }
919 return true;
920 }
921};
922
923/** Outputs contents of each atom::ListOfBonds.
924 * \param *out output stream
925 */
926void molecule::OutputListOfBonds() const
927{
928 DoLog(2) && (Log() << Verbose(2) << endl << "From Contents of ListOfBonds, all non-hydrogen atoms:" << endl);
929 for_each(atoms.begin(),atoms.end(),mem_fun(&atom::OutputBondOfAtom));
930 DoLog(0) && (Log() << Verbose(0) << endl);
931};
932
933/** Output of element before the actual coordination list.
934 * \param *out stream pointer
935 */
936bool molecule::Checkout(ofstream * const output) const
937{
938 return formula.checkOut(output);
939};
940
941/** Prints molecule with all its trajectories to *out as xyz file.
942 * \param *out output stream
943 */
944bool molecule::OutputTrajectoriesXYZ(ofstream * const output)
945{
946 time_t now;
947
948 if (output != NULL) {
949 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time'
950 for (int step=0;step<MDSteps;step++) {
951 *output << getAtomCount() << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);
952 for_each(atoms.begin(),atoms.end(),boost::bind(&atom::OutputTrajectoryXYZ,_1,output,step));
953 }
954 return true;
955 } else
956 return false;
957};
958
959/** Prints molecule to *out as xyz file.
960* \param *out output stream
961 */
962bool molecule::OutputXYZ(ofstream * const output) const
963{
964 time_t now;
965
966 if (output != NULL) {
967 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time'
968 *output << getAtomCount() << "\n\tCreated by molecuilder on " << ctime(&now);
969 for_each(atoms.begin(),atoms.end(),bind2nd(mem_fun(&atom::OutputXYZLine),output));
970 return true;
971 } else
972 return false;
973};
974
975/** Brings molecule::AtomCount and atom::*Name up-to-date.
976 * \param *out output stream for debugging
977 */
978int molecule::doCountAtoms()
979{
980 int res = size();
981 int i = 0;
982 NoNonHydrogen = 0;
983 for (molecule::const_iterator iter = atoms.begin(); iter != atoms.end(); ++iter) {
984 (*iter)->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron)
985 if ((*iter)->getType()->getAtomicNumber() != 1) // count non-hydrogen atoms whilst at it
986 NoNonHydrogen++;
987 stringstream sstr;
988 sstr << (*iter)->getType()->getSymbol() << (*iter)->nr+1;
989 (*iter)->setName(sstr.str());
990 DoLog(3) && (Log() << Verbose(3) << "Naming atom nr. " << (*iter)->nr << " " << (*iter)->getName() << "." << endl);
991 i++;
992 }
993 return res;
994};
995
996/** Returns an index map for two father-son-molecules.
997 * The map tells which atom in this molecule corresponds to which one in the other molecul with their fathers.
998 * \param *out output stream for debugging
999 * \param *OtherMolecule corresponding molecule with fathers
1000 * \return allocated map of size molecule::AtomCount with map
1001 * \todo make this with a good sort O(n), not O(n^2)
1002 */
1003int * molecule::GetFatherSonAtomicMap(molecule *OtherMolecule)
1004{
1005 DoLog(3) && (Log() << Verbose(3) << "Begin of GetFatherAtomicMap." << endl);
1006 int *AtomicMap = new int[getAtomCount()];
1007 for (int i=getAtomCount();i--;)
1008 AtomicMap[i] = -1;
1009 if (OtherMolecule == this) { // same molecule
1010 for (int i=getAtomCount();i--;) // no need as -1 means already that there is trivial correspondence
1011 AtomicMap[i] = i;
1012 DoLog(4) && (Log() << Verbose(4) << "Map is trivial." << endl);
1013 } else {
1014 DoLog(4) && (Log() << Verbose(4) << "Map is ");
1015 for (molecule::const_iterator iter = begin(); iter != end(); ++iter) {
1016 if ((*iter)->father == NULL) {
1017 AtomicMap[(*iter)->nr] = -2;
1018 } else {
1019 for (molecule::const_iterator runner = OtherMolecule->begin(); runner != OtherMolecule->end(); ++runner) {
1020 //for (int i=0;i<AtomCount;i++) { // search atom
1021 //for (int j=0;j<OtherMolecule->getAtomCount();j++) {
1022 //Log() << Verbose(4) << "Comparing father " << (*iter)->father << " with the other one " << (*runner)->father << "." << endl;
1023 if ((*iter)->father == (*runner))
1024 AtomicMap[(*iter)->nr] = (*runner)->nr;
1025 }
1026 }
1027 DoLog(0) && (Log() << Verbose(0) << AtomicMap[(*iter)->nr] << "\t");
1028 }
1029 DoLog(0) && (Log() << Verbose(0) << endl);
1030 }
1031 DoLog(3) && (Log() << Verbose(3) << "End of GetFatherAtomicMap." << endl);
1032 return AtomicMap;
1033};
1034
1035/** Stores the temperature evaluated from velocities in molecule::Trajectories.
1036 * We simply use the formula equivaleting temperature and kinetic energy:
1037 * \f$k_B T = \sum_i m_i v_i^2\f$
1038 * \param *output output stream of temperature file
1039 * \param startstep first MD step in molecule::Trajectories
1040 * \param endstep last plus one MD step in molecule::Trajectories
1041 * \return file written (true), failure on writing file (false)
1042 */
1043bool molecule::OutputTemperatureFromTrajectories(ofstream * const output, int startstep, int endstep)
1044{
1045 double temperature;
1046 // test stream
1047 if (output == NULL)
1048 return false;
1049 else
1050 *output << "# Step Temperature [K] Temperature [a.u.]" << endl;
1051 for (int step=startstep;step < endstep; step++) { // loop over all time steps
1052 temperature = atoms.totalTemperatureAtStep(step);
1053 *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl;
1054 }
1055 return true;
1056};
1057
1058void molecule::flipActiveFlag(){
1059 ActiveFlag = !ActiveFlag;
1060}
Note: See TracBrowser for help on using the repository browser.