source: src/Dynamics/ForceAnnealing.hpp@ 9d3846

ForceAnnealing_with_BondGraph_continued
Last change on this file since 9d3846 was 6d360a, checked in by Frederik Heber <frederik.heber@…>, 8 years ago

ForceAnnealing can now be used either atom- or bond-centered.

  • new keyword "use-bondgraph" to use either case.
  • atom is old annealing method, bond graph is new annealing method where the bond neighborhood is shifted as well to anneal to force projected onto the BondVector.
  • In the first step we always use atom-centered annealing where we use the given deltat step width. Afterwards Barzilai-Borwein may then proceed.
  • Property mode set to 100644
File size: 24.2 KB
Line 
1/*
2 * ForceAnnealing.hpp
3 *
4 * Created on: Aug 02, 2014
5 * Author: heber
6 */
7
8#ifndef FORCEANNEALING_HPP_
9#define FORCEANNEALING_HPP_
10
11// include config.h
12#ifdef HAVE_CONFIG_H
13#include <config.h>
14#endif
15
16#include <algorithm>
17#include <functional>
18#include <iterator>
19
20#include <boost/bind.hpp>
21
22#include "Atom/atom.hpp"
23#include "Atom/AtomSet.hpp"
24#include "CodePatterns/Assert.hpp"
25#include "CodePatterns/Info.hpp"
26#include "CodePatterns/Log.hpp"
27#include "CodePatterns/Verbose.hpp"
28#include "Descriptors/AtomIdDescriptor.hpp"
29#include "Dynamics/AtomicForceManipulator.hpp"
30#include "Dynamics/BondVectors.hpp"
31#include "Fragmentation/ForceMatrix.hpp"
32#include "Graph/BoostGraphCreator.hpp"
33#include "Graph/BoostGraphHelpers.hpp"
34#include "Graph/BreadthFirstSearchGatherer.hpp"
35#include "Helpers/helpers.hpp"
36#include "Helpers/defs.hpp"
37#include "LinearAlgebra/LinearSystemOfEquations.hpp"
38#include "LinearAlgebra/MatrixContent.hpp"
39#include "LinearAlgebra/Vector.hpp"
40#include "LinearAlgebra/VectorContent.hpp"
41#include "Thermostats/ThermoStatContainer.hpp"
42#include "Thermostats/Thermostat.hpp"
43#include "World.hpp"
44
45/** This class is the essential build block for performing structural optimization.
46 *
47 * Sadly, we have to use some static instances as so far values cannot be passed
48 * between actions. Hence, we need to store the current step and the adaptive-
49 * step width (we cannot perform a line search, as we have no control over the
50 * calculation of the forces).
51 *
52 * However, we do use the bond graph, i.e. if a single atom needs to be shifted
53 * to the left, then the whole molecule left of it is shifted, too. This is
54 * controlled by the \a max_distance parameter.
55 */
56template <class T>
57class ForceAnnealing : public AtomicForceManipulator<T>
58{
59public:
60 /** Constructor of class ForceAnnealing.
61 *
62 * \note We use a fixed delta t of 1.
63 *
64 * \param _atoms set of atoms to integrate
65 * \param _Deltat time step width in atomic units
66 * \param _IsAngstroem whether length units are in angstroem or bohr radii
67 * \param _maxSteps number of optimization steps to perform
68 * \param _max_distance up to this bond order is bond graph taken into account.
69 */
70 ForceAnnealing(
71 AtomSetMixin<T> &_atoms,
72 bool _IsAngstroem,
73 const size_t _maxSteps,
74 const int _max_distance,
75 const double _damping_factor) :
76 AtomicForceManipulator<T>(_atoms, 1., _IsAngstroem),
77 maxSteps(_maxSteps),
78 max_distance(_max_distance),
79 damping_factor(_damping_factor)
80 {}
81 /** Destructor of class ForceAnnealing.
82 *
83 */
84 ~ForceAnnealing()
85 {}
86
87 /** Performs Gradient optimization.
88 *
89 * We assume that forces have just been calculated.
90 *
91 *
92 * \param CurrentTimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)
93 * \param offset offset in matrix file to the first force component
94 * \todo This is not yet checked if it is correctly working with DoConstrainedMD set >0.
95 */
96 void operator()(
97 const int _CurrentTimeStep,
98 const size_t _offset,
99 const bool _UseBondgraph)
100 {
101 // make sum of forces equal zero
102 AtomicForceManipulator<T>::correctForceMatrixForFixedCenterOfMass(_offset, _CurrentTimeStep);
103
104 // are we in initial step? Then set static entities
105 Vector maxComponents(zeroVec);
106 if (currentStep == 0) {
107 currentDeltat = AtomicForceManipulator<T>::Deltat;
108 currentStep = 1;
109 LOG(2, "DEBUG: Initial step, setting values, current step is #" << currentStep);
110
111 // always use atomic annealing on first step
112 anneal(_CurrentTimeStep, _offset, maxComponents);
113 } else {
114 ++currentStep;
115 LOG(2, "DEBUG: current step is #" << currentStep);
116
117 if (_UseBondgraph)
118 annealWithBondGraph(_CurrentTimeStep, _offset, maxComponents);
119 else
120 anneal(_CurrentTimeStep, _offset, maxComponents);
121 }
122
123
124 LOG(1, "STATUS: Largest remaining force components at step #"
125 << currentStep << " are " << maxComponents);
126
127 // are we in final step? Remember to reset static entities
128 if (currentStep == maxSteps) {
129 LOG(2, "DEBUG: Final step, resetting values");
130 reset();
131 }
132 }
133
134 /** Performs Gradient optimization on the atoms.
135 *
136 * We assume that forces have just been calculated.
137 *
138 * \param CurrentTimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)
139 * \param offset offset in matrix file to the first force component
140 * \param maxComponents to be filled with maximum force component over all atoms
141 */
142 void anneal(
143 const int CurrentTimeStep,
144 const size_t offset,
145 Vector &maxComponents)
146 {
147 for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
148 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
149 // atom's force vector gives steepest descent direction
150 const Vector oldPosition = (*iter)->getPositionAtStep(CurrentTimeStep-2 >= 0 ? CurrentTimeStep - 2 : 0);
151 const Vector currentPosition = (*iter)->getPosition();
152 const Vector oldGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep-2 >= 0 ? CurrentTimeStep - 2 : 0);
153 const Vector currentGradient = (*iter)->getAtomicForce();
154 LOG(4, "DEBUG: oldPosition for atom " << **iter << " is " << oldPosition);
155 LOG(4, "DEBUG: currentPosition for atom " << **iter << " is " << currentPosition);
156 LOG(4, "DEBUG: oldGradient for atom " << **iter << " is " << oldGradient);
157 LOG(4, "DEBUG: currentGradient for atom " << **iter << " is " << currentGradient);
158// LOG(4, "DEBUG: Force for atom " << **iter << " is " << currentGradient);
159
160 // we use Barzilai-Borwein update with position reversed to get descent
161 const Vector PositionDifference = currentPosition - oldPosition;
162 const Vector GradientDifference = (currentGradient - oldGradient);
163 double stepwidth = 0.;
164 if (GradientDifference.Norm() > MYEPSILON)
165 stepwidth = fabs(PositionDifference.ScalarProduct(GradientDifference))/
166 GradientDifference.NormSquared();
167 if (fabs(stepwidth) < 1e-10) {
168 // dont' warn in first step, deltat usage normal
169 if (currentStep != 1)
170 ELOG(1, "INFO: Barzilai-Borwein stepwidth is zero, using deltat " << currentDeltat << " instead.");
171 stepwidth = currentDeltat;
172 }
173 Vector PositionUpdate = stepwidth * currentGradient;
174 LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate);
175
176 // extract largest components for showing progress of annealing
177 for(size_t i=0;i<NDIM;++i)
178 if (currentGradient[i] > maxComponents[i])
179 maxComponents[i] = currentGradient[i];
180
181 // are we in initial step? Then don't check against velocity
182 if ((currentStep > 1) && (!(*iter)->getAtomicVelocity().IsZero()))
183 // update with currentDelta tells us how the current gradient relates to
184 // the last one: If it has become larger, reduce currentDelta
185 if ((PositionUpdate.ScalarProduct((*iter)->getAtomicVelocity()) < 0)
186 && (currentDeltat > MinimumDeltat)) {
187 currentDeltat = .5*currentDeltat;
188 LOG(2, "DEBUG: Upgrade in other direction: " << PositionUpdate.NormSquared()
189 << " > " << (*iter)->getAtomicVelocity().NormSquared()
190 << ", decreasing deltat: " << currentDeltat);
191 PositionUpdate = currentDeltat * currentGradient;
192 }
193 // finally set new values
194 (*iter)->setPosition(currentPosition + PositionUpdate);
195 (*iter)->setAtomicVelocity(PositionUpdate);
196 //std::cout << "Id of atom is " << (*iter)->getId() << std::endl;
197// (*iter)->VelocityVerletUpdateU((*iter)->getId(), CurrentTimeStep-1, Deltat, IsAngstroem);
198
199 // reset force vector for next step except on final one
200 if (currentStep != maxSteps)
201 (*iter)->setAtomicForce(zeroVec);
202 }
203
204 LOG(1, "STATUS: Largest remaining force components at step #"
205 << currentStep << " are " << maxComponents);
206
207 // are we in final step? Remember to reset static entities
208 if (currentStep == maxSteps) {
209 LOG(2, "DEBUG: Final step, resetting values");
210 reset();
211 }
212 }
213
214 /** Performs Gradient optimization on the bonds.
215 *
216 * We assume that forces have just been calculated. These forces are projected
217 * onto the bonds and these are annealed subsequently by moving atoms in the
218 * bond neighborhood on either side conjunctively.
219 *
220 *
221 * \param CurrentTimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)
222 * \param offset offset in matrix file to the first force component
223 * \param maxComponents to be filled with maximum force component over all atoms
224 */
225 void annealWithBondGraph(
226 const int CurrentTimeStep,
227 const size_t offset,
228 Vector &maxComponents)
229 {
230 // get nodes on either side of selected bond via BFS discovery
231 BoostGraphCreator BGcreator;
232 BGcreator.createFromRange(
233 AtomicForceManipulator<T>::atoms.begin(),
234 AtomicForceManipulator<T>::atoms.end(),
235 AtomicForceManipulator<T>::atoms.size(),
236 BreadthFirstSearchGatherer::AlwaysTruePredicate);
237 BreadthFirstSearchGatherer NodeGatherer(BGcreator);
238
239 /// We assume that a force is local, i.e. a bond is too short yet and hence
240 /// the atom needs to be moved. However, all the adjacent (bound) atoms might
241 /// already be at the perfect distance. If we just move the atom alone, we ruin
242 /// all the other bonds. Hence, it would be sensible to move every atom found
243 /// through the bond graph in the direction of the force as well by the same
244 /// PositionUpdate. This is almost what we are going to do.
245
246 /// One issue is: If we need to shorten bond, then we use the PositionUpdate
247 /// also on the the other bond partner already. This is because it is in the
248 /// direction of the bond. Therefore, the update is actually performed twice on
249 /// each bond partner, i.e. the step size is twice as large as it should be.
250 /// This problem only occurs when bonds need to be shortened, not when they
251 /// need to be made longer (then the force vector is facing the other
252 /// direction than the bond vector).
253 /// As a remedy we need to average the force on either end of the bond and
254 /// check whether each gradient points inwards out or outwards with respect
255 /// to the bond and then shift accordingly.
256
257 /// One more issue is that the projection onto the bond directions does not
258 /// recover the gradient but may be larger as the bond directions are a
259 /// generating system and not a basis (e.g. 3 bonds on a plane where 2 would
260 /// suffice to span the plane). To this end, we need to account for the
261 /// overestimation and obtain a weighting for each bond.
262
263 // initialize helper class for bond vectors using bonds from range of atoms
264 BondVectors bv;
265 bv.setFromAtomRange< T >(
266 AtomicForceManipulator<T>::atoms.begin(),
267 AtomicForceManipulator<T>::atoms.end(),
268 currentStep);
269 const BondVectors::container_t &sorted_bonds = bv.getSorted();
270
271 // knowing the number of bonds in total, we can setup the storage for the
272 // projected forces
273 enum whichatom_t {
274 leftside=0,
275 rightside=1,
276 MAX_sides
277 };
278 std::vector< // time step
279 std::vector< // which bond side
280 std::vector<double> > // over all bonds
281 > projected_forces(2); // one for leftatoms, one for rightatoms (and for both time steps)
282 for (size_t i=0;i<2;++i) {
283 projected_forces[i].resize(MAX_sides);
284 for (size_t j=0;j<MAX_sides;++j)
285 projected_forces[i][j].resize(sorted_bonds.size(), 0.);
286 }
287
288 // for each atom we need to gather weights and then project the gradient
289 typedef std::deque<double> weights_t;
290 typedef std::map<atomId_t, weights_t > weights_per_atom_t;
291 std::vector<weights_per_atom_t> weights_per_atom(2);
292 for (size_t timestep = 0; timestep <= 1; ++timestep) {
293 // TODO: We have this extra step in between because of DoOutput copying
294 // change this making the code easier to understand
295 const size_t CurrentStep = CurrentTimeStep-2*timestep >= 0 ? CurrentTimeStep - 2*timestep : 0;
296
297 // get all bond vectors for this time step (from the perspective of the
298 // bonds taken from the currentStep)
299 const BondVectors::mapped_t bondvectors = bv.getBondVectorsAtStep(CurrentStep);
300
301 for(typename AtomSetMixin<T>::const_iterator iter = AtomicForceManipulator<T>::atoms.begin();
302 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
303 const atom &walker = *(*iter);
304 const Vector &walkerGradient = walker.getAtomicForceAtStep(CurrentStep);
305 LOG(3, "DEBUG: Gradient of atom #" << walker.getId() << ", namely "
306 << walker << " is " << walkerGradient);
307
308 const BondList& ListOfBonds = walker.getListOfBonds();
309 if (walkerGradient.Norm() > MYEPSILON) {
310
311 // gather subset of BondVectors for the current atom
312 std::vector<Vector> BondVectors;
313 for(BondList::const_iterator bonditer = ListOfBonds.begin();
314 bonditer != ListOfBonds.end(); ++bonditer) {
315 const bond::ptr &current_bond = *bonditer;
316 const BondVectors::mapped_t::const_iterator bviter =
317 bondvectors.find(current_bond);
318 ASSERT( bviter != bondvectors.end(),
319 "ForceAnnealing() - cannot find current_bond ?");
320 ASSERT( bviter != bondvectors.end(),
321 "ForceAnnealing - cannot find current bond "+toString(*current_bond)
322 +" in bonds.");
323 BondVectors.push_back(bviter->second);
324 }
325 LOG(4, "DEBUG: BondVectors for atom #" << walker.getId() << ": " << BondVectors);
326
327 // go through all its bonds and calculate what magnitude is represented
328 // by the others i.e. sum of scalar products against other bonds
329 std::pair<weights_per_atom_t::iterator, bool> inserter =
330 weights_per_atom[timestep].insert(
331 std::make_pair(walker.getId(), weights_t()) );
332 ASSERT( inserter.second,
333 "ForceAnnealing::operator() - weight map for atom "+toString(walker)
334 +" and time step "+toString(timestep)+" already filled?");
335 weights_t &weights = inserter.first->second;
336 for (std::vector<Vector>::const_iterator iter = BondVectors.begin();
337 iter != BondVectors.end(); ++iter) {
338 std::vector<double> scps;
339 scps.reserve(BondVectors.size());
340 std::transform(
341 BondVectors.begin(), BondVectors.end(),
342 std::back_inserter(scps),
343 boost::bind(static_cast< double (*)(double) >(&fabs),
344 boost::bind(&Vector::ScalarProduct, boost::cref(*iter), _1))
345 );
346 const double scp_sum = std::accumulate(scps.begin(), scps.end(), 0.);
347 ASSERT( (scp_sum-1.) > -MYEPSILON,
348 "ForceAnnealing() - sum of weights must be equal or larger one but is "
349 +toString(scp_sum));
350 weights.push_back( 1./scp_sum );
351 }
352 LOG(4, "DEBUG: Weights for atom #" << walker.getId() << ": " << weights);
353
354 // for testing we check whether all weighted scalar products now come out as 1.
355#ifndef NDEBUG
356 for (std::vector<Vector>::const_iterator iter = BondVectors.begin();
357 iter != BondVectors.end(); ++iter) {
358 std::vector<double> scps;
359 scps.reserve(BondVectors.size());
360 std::transform(
361 BondVectors.begin(), BondVectors.end(),
362 weights.begin(),
363 std::back_inserter(scps),
364 boost::bind(static_cast< double (*)(double) >(&fabs),
365 boost::bind(std::multiplies<double>(),
366 boost::bind(&Vector::ScalarProduct, boost::cref(*iter), _1),
367 _2))
368 );
369 const double scp_sum = std::accumulate(scps.begin(), scps.end(), 0.);
370 ASSERT( fabs(scp_sum - 1.) < MYEPSILON,
371 "ForceAnnealing::operator() - for BondVector "+toString(*iter)
372 +" we have weighted scalar product of "+toString(scp_sum)+" != 1.");
373 }
374#endif
375
376 // projected gradient over all bonds and place in one of projected_forces
377 // using the obtained weights
378 {
379 weights_t::const_iterator weightiter = weights.begin();
380 std::vector<Vector>::const_iterator vectoriter = BondVectors.begin();
381 Vector forcesum_check;
382 for(BondList::const_iterator bonditer = ListOfBonds.begin();
383 bonditer != ListOfBonds.end(); ++bonditer, ++weightiter, ++vectoriter) {
384 const bond::ptr &current_bond = *bonditer;
385 const Vector &BondVector = *vectoriter;
386
387 std::vector<double> &forcelist = (&walker == current_bond->leftatom) ?
388 projected_forces[timestep][leftside] : projected_forces[timestep][rightside];
389 const size_t index = bv.getIndexForBond(current_bond);
390 ASSERT( index != (size_t)-1,
391 "ForceAnnealing() - could not find bond "+toString(*current_bond)
392 +" in bondvectors");
393 forcelist[index] = (*weightiter)*walkerGradient.ScalarProduct(BondVector);
394 LOG(4, "DEBUG: BondVector " << BondVector << " receives projected force of "
395 << forcelist[index]);
396 forcesum_check += forcelist[index] * BondVector;
397 }
398 ASSERT( weightiter == weights.end(),
399 "ForceAnnealing - weightiter is not at end when it should be.");
400 ASSERT( vectoriter == BondVectors.end(),
401 "ForceAnnealing - vectoriter is not at end when it should be.");
402 LOG(3, "DEBUG: sum of projected forces is " << forcesum_check);
403 }
404
405 } else {
406 LOG(2, "DEBUG: Gradient is " << walkerGradient << " less than "
407 << MYEPSILON << " for atom " << walker);
408 // note that projected_forces is initialized to full length and filled
409 // with zeros. Hence, nothing to do here
410 }
411 }
412 }
413
414 // step through each bond and shift the atoms
415 std::map<atomId_t, Vector> GatheredUpdates; //!< gathers all updates which are applied at the end
416
417 LOG(3, "DEBUG: current step is " << currentStep << ", given time step is " << CurrentTimeStep);
418 const BondVectors::mapped_t bondvectors = bv.getBondVectorsAtStep(currentStep);
419
420 for (BondVectors::container_t::const_iterator bondsiter = sorted_bonds.begin();
421 bondsiter != sorted_bonds.end(); ++bondsiter) {
422 const bond::ptr &current_bond = *bondsiter;
423 const size_t index = bv.getIndexForBond(current_bond);
424 const atom* bondatom[MAX_sides] = {
425 current_bond->leftatom,
426 current_bond->rightatom
427 };
428
429 // remove the edge
430#ifndef NDEBUG
431 const bool status =
432#endif
433 BGcreator.removeEdge(bondatom[leftside]->getId(), bondatom[rightside]->getId());
434 ASSERT( status, "ForceAnnealing() - edge to found bond is not present?");
435
436 // gather nodes for either atom
437 BoostGraphHelpers::Nodeset_t bondside_set[MAX_sides];
438 BreadthFirstSearchGatherer::distance_map_t distance_map[MAX_sides];
439 for (size_t side=leftside;side<MAX_sides;++side) {
440 bondside_set[side] = NodeGatherer(bondatom[side]->getId(), max_distance);
441 distance_map[side] = NodeGatherer.getDistances();
442 std::sort(bondside_set[side].begin(), bondside_set[side].end());
443 }
444
445 // re-add edge
446 BGcreator.addEdge(bondatom[leftside]->getId(), bondatom[rightside]->getId());
447
448 // do for both leftatom and rightatom of bond
449 for (size_t side = leftside; side < MAX_sides; ++side) {
450 const double &bondforce = projected_forces[0][side][index];
451 const double &oldbondforce = projected_forces[1][side][index];
452 const double bondforcedifference = (bondforce - oldbondforce);
453 // if difference or bondforce itself is zero, do nothing
454 if ((fabs(bondforce) < MYEPSILON) || (fabs(bondforcedifference) < MYEPSILON))
455 continue;
456 const BondVectors::mapped_t::const_iterator bviter =
457 bondvectors.find(current_bond);
458 ASSERT( bviter != bondvectors.end(),
459 "ForceAnnealing() - cannot find current_bond ?");
460 const Vector &BondVector = bviter->second;
461 const Vector &oldPosition = bondatom[side]->getPositionAtStep(CurrentTimeStep-1 >= 0 ? CurrentTimeStep - 1 : 0);
462 const Vector &currentPosition = bondatom[side]->getPosition();
463 const double stepwidth =
464 fabs((currentPosition - oldPosition).ScalarProduct(BondVector))/bondforcedifference;
465 Vector PositionUpdate = stepwidth * BondVector;
466 if (fabs(stepwidth) < 1e-10) {
467 // dont' warn in first step, deltat usage normal
468 if (currentStep != 1)
469 ELOG(1, "INFO: Barzilai-Borwein stepwidth is zero, using deltat " << currentDeltat << " instead.");
470 PositionUpdate = currentDeltat * BondVector;
471 }
472 LOG(3, "DEBUG: Update would be " << PositionUpdate);
473
474 // add PositionUpdate for all nodes in the bondside_set
475 for (BoostGraphHelpers::Nodeset_t::const_iterator setiter = bondside_set[side].begin();
476 setiter != bondside_set[side].end(); ++setiter) {
477 const BreadthFirstSearchGatherer::distance_map_t::const_iterator diter
478 = distance_map[side].find(*setiter);
479 ASSERT( diter != distance_map[side].end(),
480 "ForceAnnealing() - could not find distance to an atom.");
481 const double factor = pow(damping_factor, diter->second);
482 LOG(3, "DEBUG: Update for atom #" << *setiter << " will be "
483 << factor << "*" << PositionUpdate);
484 if (GatheredUpdates.count((*setiter))) {
485 GatheredUpdates[(*setiter)] += factor*PositionUpdate;
486 } else {
487 GatheredUpdates.insert(
488 std::make_pair(
489 (*setiter),
490 factor*PositionUpdate) );
491 }
492 }
493 }
494 }
495
496 for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
497 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
498 atom &walker = *(*iter);
499 // extract largest components for showing progress of annealing
500 const Vector currentGradient = walker.getAtomicForce();
501 for(size_t i=0;i<NDIM;++i)
502 if (currentGradient[i] > maxComponents[i])
503 maxComponents[i] = currentGradient[i];
504
505 // reset force vector for next step except on final one
506 if (currentStep != maxSteps)
507 walker.setAtomicForce(zeroVec);
508 }
509
510 // apply the gathered updates
511 for (std::map<atomId_t, Vector>::const_iterator iter = GatheredUpdates.begin();
512 iter != GatheredUpdates.end(); ++iter) {
513 const atomId_t &atomid = iter->first;
514 const Vector &update = iter->second;
515 atom* const walker = World::getInstance().getAtom(AtomById(atomid));
516 ASSERT( walker != NULL,
517 "ForceAnnealing() - walker with id "+toString(atomid)+" has suddenly disappeared.");
518 walker->setPosition( walker->getPosition() + update );
519 walker->setAtomicVelocity(update);
520 LOG(3, "DEBUG: Applying update " << update << " to atom " << *walker);
521 }
522 }
523
524 /** Reset function to unset static entities and artificial velocities.
525 *
526 */
527 void reset()
528 {
529 currentDeltat = 0.;
530 currentStep = 0;
531
532 // reset (artifical) velocities
533 for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
534 iter != AtomicForceManipulator<T>::atoms.end(); ++iter)
535 (*iter)->setAtomicVelocity(zeroVec);
536 }
537
538private:
539 //!> contains the current step in relation to maxsteps
540 static size_t currentStep;
541 //!> contains the maximum number of steps, determines initial and final step with currentStep
542 size_t maxSteps;
543 static double currentDeltat;
544 //!> minimum deltat for internal while loop (adaptive step width)
545 static double MinimumDeltat;
546 //!> contains the maximum bond graph distance up to which shifts of a single atom are spread
547 const int max_distance;
548 //!> the shifted is dampened by this factor with the power of the bond graph distance to the shift causing atom
549 const double damping_factor;
550};
551
552template <class T>
553double ForceAnnealing<T>::currentDeltat = 0.;
554template <class T>
555size_t ForceAnnealing<T>::currentStep = 0;
556template <class T>
557double ForceAnnealing<T>::MinimumDeltat = 1e-8;
558
559#endif /* FORCEANNEALING_HPP_ */
Note: See TracBrowser for help on using the repository browser.