source: src/Atom/atom_atominfo.cpp@ 440ac3

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 440ac3 was f946b2, checked in by Frederik Heber <heber@…>, 8 years ago

FIX: AtomInfo::CopyStepOnStep() did require present of velocity and forces with position.

  • however, if we parse steps from a file, then forces and velocity are not necessarily contained. If we need equally sized trajectories, then we need to enforce this in the Atom class.
  • Property mode set to 100644
File size: 17.6 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 * Copyright (C) 2014 Frederik Heber. All rights reserved.
6 *
7 *
8 * This file is part of MoleCuilder.
9 *
10 * MoleCuilder is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * MoleCuilder is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24/*
25 * atom_atominfo.cpp
26 *
27 * Created on: Oct 19, 2009
28 * Author: heber
29 */
30
31// include config.h
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36#include "CodePatterns/MemDebug.hpp"
37
38#include "CodePatterns/Verbose.hpp"
39
40#include "atom_atominfo.hpp"
41#include "CodePatterns/Log.hpp"
42#include "config.hpp"
43#include "Element/element.hpp"
44#include "Element/periodentafel.hpp"
45#include "Fragmentation/ForceMatrix.hpp"
46#include "World.hpp"
47#include "WorldTime.hpp"
48
49#include <iomanip>
50
51/** Constructor of class AtomInfo.
52 */
53AtomInfo::AtomInfo() :
54 AtomicElement(1),
55 FixedIon(false),
56 charge(0.)
57{
58 AtomicPosition.insert( std::make_pair(0, zeroVec) );
59 AtomicVelocity.insert( std::make_pair(0, zeroVec) );
60 AtomicForce.insert( std::make_pair(0, zeroVec) );
61}
62
63/** Copy constructor of class AtomInfo.
64 */
65AtomInfo::AtomInfo(const AtomInfo &_atom) :
66 AtomicPosition(_atom.AtomicPosition),
67 AtomicVelocity(_atom.AtomicVelocity),
68 AtomicForce(_atom.AtomicForce),
69 AtomicElement(_atom.AtomicElement),
70 FixedIon(_atom.FixedIon),
71 charge(_atom.charge)
72{
73}
74
75AtomInfo::AtomInfo(const VectorInterface &_v) :
76 AtomicElement(1),
77 FixedIon(false),
78 charge(0.)
79{
80 AtomicPosition.insert( std::make_pair(0, _v.getPosition()) );
81 AtomicVelocity.insert( std::make_pair(0, zeroVec) );
82 AtomicForce.insert( std::make_pair(0, zeroVec) );
83};
84
85/** Destructor of class AtomInfo.
86 */
87AtomInfo::~AtomInfo()
88{
89};
90
91void AtomInfo::AppendTrajectoryStep(const unsigned int _step)
92{
93 ASSERT (WorldTime::getTime() != _step,
94 "AtomInfo::AppendTrajectoryStep() - cannot append current time step.");
95 NOTIFY(TrajectoryChanged);
96 AtomicPosition.insert( std::make_pair(_step, zeroVec) );
97 AtomicVelocity.insert( std::make_pair(_step, zeroVec) );
98 AtomicForce.insert( std::make_pair(_step, zeroVec) );
99 LOG(5,"AtomInfo::AppendTrajectoryStep() called, size is ("
100 << AtomicPosition.size() << ","
101 << AtomicVelocity.size() << ","
102 << AtomicForce.size() << ")");
103}
104
105void AtomInfo::removeTrajectoryStep(const unsigned int _step)
106{
107 ASSERT (WorldTime::getTime() != _step,
108 "AtomInfo::removeTrajectoryStep() - cannot remove current time step.");
109 NOTIFY(TrajectoryChanged);
110 AtomicPosition.erase(_step);
111 AtomicVelocity.erase(_step);
112 AtomicForce.erase(_step);
113 LOG(5,"AtomInfo::removeTrajectoryStep() called, size is ("
114 << AtomicPosition.size() << ","
115 << AtomicVelocity.size() << ","
116 << AtomicForce.size() << ")");
117}
118
119const element *AtomInfo::getType() const
120{
121 const element *elem = World::getInstance().getPeriode()->FindElement(AtomicElement);
122 return elem;
123}
124
125const element &AtomInfo::getElement() const
126{
127 const element &elem = *World::getInstance().getPeriode()->FindElement(AtomicElement);
128 return elem;
129}
130
131atomicNumber_t AtomInfo::getElementNo() const
132{
133 return AtomicElement;
134}
135
136const std::string &AtomInfo::getParticleName() const
137{
138 return particlename;
139}
140
141void AtomInfo::setParticleName(const std::string & _name)
142{
143 particlename = _name;
144}
145
146const double& AtomInfo::operator[](size_t i) const
147{
148 return atStep(i, WorldTime::getTime());
149}
150
151const double& AtomInfo::at(size_t i) const
152{
153 return atStep(i, WorldTime::getTime());
154}
155
156const double& AtomInfo::atStep(size_t i, unsigned int _step) const
157{
158 ASSERT(!AtomicPosition.empty(),
159 "AtomInfo::operator[]() - AtomicPosition is empty.");
160 VectorTrajectory_t::const_iterator iter =
161 AtomicPosition.lower_bound(_step);
162 return iter->second[i];
163}
164
165void AtomInfo::set(size_t i, const double value)
166{
167 OBSERVE;
168 NOTIFY(AtomObservable::PositionChanged);
169 VectorTrajectory_t::iterator iter = AtomicPosition.find(WorldTime::getTime());
170 if (iter != AtomicPosition.end()) {
171 iter->second[i] = value;
172 } else {
173 Vector newPos;
174 newPos[i] = value;
175#ifndef NDEBUG
176 std::pair<VectorTrajectory_t::iterator, bool> inserter =
177#endif
178 AtomicPosition.insert( std::make_pair(WorldTime::getTime(), newPos) );
179 ASSERT( inserter.second,
180 "AtomInfo::set() - time step "+toString(WorldTime::getTime())
181 +" present after all?");
182 }
183}
184
185/** Helps to determine whether the current step really exists or getPosition() has just
186 * delivered the one closest to it in the past.
187 *
188 * \param _step step to check
189 * \param true - step exists, false - step does not exist, getPosition() delivers closest
190 */
191bool AtomInfo::isStepPresent(const unsigned int _step) const
192{
193 VectorTrajectory_t::const_iterator iter =
194 AtomicPosition.find(_step);
195 return iter != AtomicPosition.end();
196}
197
198const Vector& AtomInfo::getPosition() const
199{
200 return getPositionAtStep(WorldTime::getTime());
201}
202
203const Vector& AtomInfo::getPositionAtStep(const unsigned int _step) const
204{
205 ASSERT(!AtomicPosition.empty(),
206 "AtomInfo::operator[]() - AtomicPosition is empty.");
207 VectorTrajectory_t::const_iterator iter =
208 AtomicPosition.lower_bound(_step);
209 return iter->second;
210}
211
212void AtomInfo::setType(const element* _type)
213{
214 OBSERVE;
215 NOTIFY(AtomObservable::ElementChanged);
216 AtomicElement = _type->getAtomicNumber();
217}
218
219void AtomInfo::setType(const int Z)
220{
221 const element *elem = World::getInstance().getPeriode()->FindElement(Z);
222 setType(elem);
223}
224
225const Vector& AtomInfo::getAtomicVelocity() const
226{
227 return getAtomicVelocityAtStep(WorldTime::getTime());
228}
229
230const Vector& AtomInfo::getAtomicVelocityAtStep(const unsigned int _step) const
231{
232 ASSERT(!AtomicVelocity.empty(),
233 "AtomInfo::operator[]() - AtomicVelocity is empty.");
234 VectorTrajectory_t::const_iterator iter =
235 AtomicVelocity.lower_bound(_step);
236 // special, we only interpolate between present time steps not into the future
237 if (_step > AtomicVelocity.begin()->first)
238 return zeroVec;
239 else
240 return iter->second;
241}
242
243void AtomInfo::setAtomicVelocity(const Vector &_newvelocity)
244{
245 setAtomicVelocityAtStep(WorldTime::getTime(), _newvelocity);
246}
247
248void AtomInfo::setAtomicVelocityAtStep(const unsigned int _step, const Vector &_newvelocity)
249{
250 OBSERVE;
251 VectorTrajectory_t::iterator iter = AtomicVelocity.find(_step);
252 if (iter != AtomicVelocity.end()) {
253 iter->second = _newvelocity;
254 } else {
255#ifndef NDEBUG
256 std::pair<VectorTrajectory_t::iterator, bool> inserter =
257#endif
258 AtomicVelocity.insert( std::make_pair(_step, _newvelocity) );
259 ASSERT( inserter.second,
260 "AtomInfo::set() - time step "+toString(_step)
261 +" present after all?");
262 }
263 if (WorldTime::getTime() == _step)
264 NOTIFY(AtomObservable::VelocityChanged);
265}
266
267const Vector& AtomInfo::getAtomicForce() const
268{
269 return getAtomicForceAtStep(WorldTime::getTime());
270}
271
272const Vector& AtomInfo::getAtomicForceAtStep(const unsigned int _step) const
273{
274 ASSERT(!AtomicForce.empty(),
275 "AtomInfo::operator[]() - AtomicForce is empty.");
276 VectorTrajectory_t::const_iterator iter =
277 AtomicForce.lower_bound(_step);
278 // special, we only interpolate between present time steps not into the future
279 if (_step > AtomicForce.begin()->first)
280 return zeroVec;
281 else
282 return iter->second;
283}
284
285void AtomInfo::setAtomicForce(const Vector &_newforce)
286{
287 setAtomicForceAtStep(WorldTime::getTime(), _newforce);
288}
289
290void AtomInfo::setAtomicForceAtStep(const unsigned int _step, const Vector &_newforce)
291{
292 OBSERVE;
293 VectorTrajectory_t::iterator iter = AtomicForce.find(_step);
294 if (iter != AtomicForce.end()) {
295 iter->second = _newforce;
296 } else {
297#ifndef NDEBUG
298 std::pair<VectorTrajectory_t::iterator, bool> inserter =
299#endif
300 AtomicForce.insert( std::make_pair(_step, _newforce) );
301 ASSERT( inserter.second,
302 "AtomInfo::set() - time step "+toString(_step)
303 +" present after all?");
304 }
305 if (WorldTime::getTime() == _step)
306 NOTIFY(AtomObservable::ForceChanged);
307}
308
309bool AtomInfo::getFixedIon() const
310{
311 return FixedIon;
312}
313
314void AtomInfo::setFixedIon(const bool _fixedion)
315{
316 OBSERVE;
317 NOTIFY(AtomObservable::PropertyChanged);
318 FixedIon = _fixedion;
319}
320
321void AtomInfo::setPosition(const Vector& _vector)
322{
323 setPositionAtStep(WorldTime::getTime(), _vector);
324}
325
326void AtomInfo::setPositionAtStep(unsigned int _step, const Vector& _vector)
327{
328 OBSERVE;
329 VectorTrajectory_t::iterator iter = AtomicPosition.find(_step);
330 if (iter != AtomicPosition.end()) {
331 iter->second = _vector;
332 } else {
333#ifndef NDEBUG
334 std::pair<VectorTrajectory_t::iterator, bool> inserter =
335#endif
336 AtomicPosition.insert( std::make_pair(_step, _vector) );
337 ASSERT( inserter.second,
338 "AtomInfo::set() - time step "+toString(_step)
339 +" present after all?");
340 }
341 if (WorldTime::getTime() == _step)
342 NOTIFY(AtomObservable::PositionChanged);
343}
344
345const VectorInterface& AtomInfo::operator+=(const Vector& b)
346{
347 setPosition(getPosition()+b);
348 return *this;
349}
350
351const VectorInterface& AtomInfo::operator-=(const Vector& b)
352{
353 setPosition(getPosition()-b);
354 return *this;
355}
356
357Vector const AtomInfo::operator+(const Vector& b) const
358{
359 Vector a(getPosition());
360 a += b;
361 return a;
362}
363
364Vector const AtomInfo::operator-(const Vector& b) const
365{
366 Vector a(getPosition());
367 a -= b;
368 return a;
369}
370
371double AtomInfo::distance(const Vector &point) const
372{
373 return getPosition().distance(point);
374}
375
376double AtomInfo::DistanceSquared(const Vector &y) const
377{
378 return getPosition().DistanceSquared(y);
379}
380
381double AtomInfo::distance(const VectorInterface &_atom) const
382{
383 return _atom.distance(getPosition());
384}
385
386double AtomInfo::DistanceSquared(const VectorInterface &_atom) const
387{
388 return _atom.DistanceSquared(getPosition());
389}
390
391VectorInterface &AtomInfo::operator=(const Vector& _vector)
392{
393 setPosition(_vector);
394 return *this;
395}
396
397void AtomInfo::ScaleAll(const double *factor)
398{
399 Vector temp(getPosition());
400 temp.ScaleAll(factor);
401 setPosition(temp);
402}
403
404void AtomInfo::ScaleAll(const Vector &factor)
405{
406 Vector temp(getPosition());
407 temp.ScaleAll(factor);
408 setPosition(temp);
409}
410
411void AtomInfo::Scale(const double factor)
412{
413 Vector temp(getPosition());
414 temp.Scale(factor);
415 setPosition(temp);
416}
417
418void AtomInfo::Zero()
419{
420 setPosition(zeroVec);
421}
422
423void AtomInfo::One(const double one)
424{
425 setPosition(Vector(one,one,one));
426}
427
428void AtomInfo::LinearCombinationOfVectors(const Vector &x1, const Vector &x2, const Vector &x3, const double * const factors)
429{
430 Vector newPos;
431 newPos.LinearCombinationOfVectors(x1,x2,x3,factors);
432 setPosition(newPos);
433}
434
435/**
436 * returns the kinetic energy of this atom at a given time step
437 */
438double AtomInfo::getKineticEnergy(const unsigned int _step) const
439{
440 return getMass() * getAtomicVelocityAtStep(_step).NormSquared();
441}
442
443Vector AtomInfo::getMomentum(const unsigned int _step) const
444{
445 return getMass() * getAtomicVelocityAtStep(_step);
446}
447
448/** Decrease the trajectory if given \a MaxSteps is smaller.
449 * Does nothing if \a MaxSteps is larger than current size.
450 *
451 * \param MaxSteps
452 */
453void AtomInfo::ResizeTrajectory(size_t MaxSteps)
454{
455 // mind the reverse ordering due to std::greater, latest time steps are at beginning
456 VectorTrajectory_t::iterator positer = AtomicPosition.lower_bound(MaxSteps);
457 if (positer != AtomicPosition.begin()) {
458 if (positer->first == MaxSteps)
459 --positer;
460 AtomicPosition.erase(AtomicPosition.begin(), positer);
461 }
462 VectorTrajectory_t::iterator veliter = AtomicVelocity.lower_bound(MaxSteps);
463 if (veliter != AtomicVelocity.begin()) {
464 if (veliter->first == MaxSteps)
465 --veliter;
466 AtomicVelocity.erase(AtomicVelocity.begin(), veliter);
467 }
468 VectorTrajectory_t::iterator forceiter = AtomicForce.lower_bound(MaxSteps);
469 if (forceiter != AtomicForce.begin()) {
470 if (forceiter->first == MaxSteps)
471 --forceiter;
472 AtomicForce.erase(AtomicForce.begin(), forceiter);
473 }
474}
475
476size_t AtomInfo::getTrajectorySize() const
477{
478 // mind greater comp for map here: first element is latest in time steps!
479 return AtomicPosition.begin()->first+1;
480}
481
482double AtomInfo::getMass() const
483{
484 return getType()->getMass();
485}
486
487/** Helper function to either insert or assign, depending on the element being
488 * present already.
489 *
490 * \param _trajectory vector of Vectors to assign
491 * \param dest step to insert/assign to
492 * \param _newvalue new Vector value
493 */
494void assignTrajectoryElement(
495 std::map<unsigned int, Vector, std::greater<unsigned int> > &_trajectory,
496 const unsigned int dest,
497 const Vector &_newvalue)
498{
499 std::pair<std::map<unsigned int, Vector, std::greater<unsigned int> >::iterator, bool> inserter =
500 _trajectory.insert( std::make_pair(dest, _newvalue) );
501 if (!inserter.second)
502 inserter.first->second = _newvalue;
503}
504
505/** Copies a given trajectory step \a src onto another \a dest
506 * \param dest index of destination step
507 * \param src index of source step
508 */
509void AtomInfo::CopyStepOnStep(const unsigned int dest, const unsigned int src)
510{
511 if (dest == src) // self assignment check
512 return;
513
514 if (WorldTime::getTime() == dest){
515 NOTIFY(AtomObservable::PositionChanged);
516 NOTIFY(AtomObservable::VelocityChanged);
517 NOTIFY(AtomObservable::ForceChanged);
518 }
519
520 VectorTrajectory_t::iterator positer = AtomicPosition.find(src);
521 ASSERT( positer != AtomicPosition.end(),
522 "AtomInfo::CopyStepOnStep() - step "
523 +toString(src)+" to copy from not present in AtomicPosition.");
524 assignTrajectoryElement(AtomicPosition, dest, positer->second);
525 VectorTrajectory_t::iterator veliter = AtomicVelocity.find(src);
526 if (veliter != AtomicVelocity.end())
527 assignTrajectoryElement(AtomicVelocity, dest, veliter->second);
528 VectorTrajectory_t::iterator forceiter = AtomicForce.find(src);
529 if (forceiter != AtomicForce.end())
530 assignTrajectoryElement(AtomicForce, dest, forceiter->second);
531};
532
533/** Performs a velocity verlet update of the position at \a NextStep from \a LastStep information only.
534 *
535 * We calculate \f$x(t + \delta t) = x(t) + v(t)* \delta t + .5 * \delta t * \delta t * F(t)/m \f$.
536 *
537 *
538 * \param NextStep index of sequential step to set
539 * \param Deltat time step width
540 * \param IsAngstroem whether the force's underlying unit of length is angstroem or bohr radii
541 */
542void AtomInfo::VelocityVerletUpdateX(int nr, const unsigned int NextStep, double Deltat, bool IsAngstroem)
543{
544 const unsigned int LastStep = NextStep == 0 ? 0 : NextStep-1;
545
546 LOG(2, "INFO: Particle that currently " << *this);
547 LOG(2, "INFO: Integrating position with mass=" << getMass() << " and Deltat="
548 << Deltat << " at NextStep=" << NextStep);
549
550 // update position
551 {
552 Vector tempVector = getPositionAtStep(LastStep);
553 LOG(4, "INFO: initial position from last step " << setprecision(4) << tempVector);
554 tempVector += Deltat*(getAtomicVelocityAtStep(LastStep)); // s(t) = s(0) + v * deltat + 1/2 a * deltat^2
555 LOG(4, "INFO: position with velocity " << getAtomicVelocityAtStep(LastStep) << " from last step " << tempVector);
556 tempVector += .5*Deltat*Deltat*(getAtomicForceAtStep(LastStep))*(1./getMass()); // F = m * a and s =
557 LOG(4, "INFO: position with force " << getAtomicForceAtStep(LastStep) << " from last step " << tempVector);
558 setPositionAtStep(NextStep, tempVector);
559 LOG(3, "INFO: Position at step " << NextStep << " set to " << tempVector);
560 }
561};
562
563/** Performs a velocity verlet update of the velocity at \a NextStep.
564 *
565 * \note forces at NextStep should have been calculated based on position at NextStep prior
566 * to calling this function.
567 *
568 * We calculate \f$v(t) = v(t - \delta t) + \delta _t * .5 * (F(t - \delta t) + F(t))/m \f$.
569 *
570 * Parameters are according to those in configuration class.
571 * \param NextStep index of sequential step to set
572 * \param Deltat time step width
573 * \param IsAngstroem whether the force's underlying unit of length is angstroem or bohr radii
574 */
575void AtomInfo::VelocityVerletUpdateU(int nr, const unsigned int NextStep, double Deltat, bool IsAngstroem)
576{
577 const unsigned int LastStep = NextStep == 0 ? 0 : NextStep-1;
578
579 LOG(2, "INFO: Particle that currently " << *this);
580 LOG(2, "INFO: Integrating velocity with mass=" << getMass() << " and Deltat="
581 << Deltat << " at NextStep=" << NextStep);
582
583 // Update U
584 {
585 Vector tempVector = getAtomicVelocityAtStep(LastStep);
586 LOG(4, "INFO: initial velocity from last step " << tempVector);
587 tempVector += Deltat * .5*(getAtomicForceAtStep(LastStep)+getAtomicForceAtStep(NextStep))*(1./getMass()); // v = F/m * t
588 LOG(4, "INFO: Velocity with force from last " << getAtomicForceAtStep(LastStep)
589 << " and present " << getAtomicForceAtStep(NextStep) << " step " << tempVector);
590 setAtomicVelocityAtStep(NextStep, tempVector);
591 LOG(3, "INFO: Velocity at step " << NextStep << " set to " << tempVector);
592 }
593};
594
595std::ostream & AtomInfo::operator << (std::ostream &ost) const
596{
597 return (ost << getPosition());
598}
599
600std::ostream & operator << (std::ostream &ost, const AtomInfo &a)
601{
602 const size_t terminalstep = a.getTrajectorySize()-1;
603 if (terminalstep) {
604 ost << "starts at "
605 << a.getPositionAtStep(0) << " and ends at "
606 << a.getPositionAtStep(terminalstep)
607 << " at time step " << terminalstep;
608 } else {
609 ost << "is at "
610 << a.getPositionAtStep(0) << " with a single time step only";
611 }
612 return ost;
613}
614
Note: See TracBrowser for help on using the repository browser.