| [1a48d2] | 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 "Atom/atom.hpp" | 
|---|
|  | 17 | #include "Atom/AtomSet.hpp" | 
|---|
|  | 18 | #include "CodePatterns/Assert.hpp" | 
|---|
|  | 19 | #include "CodePatterns/Info.hpp" | 
|---|
|  | 20 | #include "CodePatterns/Log.hpp" | 
|---|
|  | 21 | #include "CodePatterns/Verbose.hpp" | 
|---|
|  | 22 | #include "Dynamics/AtomicForceManipulator.hpp" | 
|---|
|  | 23 | #include "Fragmentation/ForceMatrix.hpp" | 
|---|
|  | 24 | #include "Helpers/helpers.hpp" | 
|---|
|  | 25 | #include "Helpers/defs.hpp" | 
|---|
|  | 26 | #include "LinearAlgebra/Vector.hpp" | 
|---|
|  | 27 | #include "Thermostats/ThermoStatContainer.hpp" | 
|---|
|  | 28 | #include "Thermostats/Thermostat.hpp" | 
|---|
|  | 29 | #include "World.hpp" | 
|---|
|  | 30 |  | 
|---|
|  | 31 | /** This class is the essential build block for performing structual optimization. | 
|---|
|  | 32 | * | 
|---|
|  | 33 | * Sadly, we have to use some static instances as so far values cannot be passed | 
|---|
|  | 34 | * between actions. Hence, we need to store the current step and the adaptive | 
|---|
|  | 35 | * step width (we cannot perform a linesearch, as we have no control over the | 
|---|
|  | 36 | * calculation of the forces). | 
|---|
|  | 37 | */ | 
|---|
|  | 38 | template <class T> | 
|---|
|  | 39 | class ForceAnnealing : public AtomicForceManipulator<T> | 
|---|
|  | 40 | { | 
|---|
|  | 41 | public: | 
|---|
|  | 42 | /** Constructor of class ForceAnnealing. | 
|---|
|  | 43 | * | 
|---|
|  | 44 | * \param _atoms set of atoms to integrate | 
|---|
|  | 45 | * \param _Deltat time step width in atomic units | 
|---|
|  | 46 | * \param _IsAngstroem whether length units are in angstroem or bohr radii | 
|---|
|  | 47 | * \param _maxSteps number of optimization steps to perform | 
|---|
|  | 48 | */ | 
|---|
|  | 49 | ForceAnnealing( | 
|---|
|  | 50 | AtomSetMixin<T> &_atoms, | 
|---|
|  | 51 | double _Deltat, | 
|---|
|  | 52 | bool _IsAngstroem, | 
|---|
|  | 53 | const size_t _maxSteps) : | 
|---|
|  | 54 | AtomicForceManipulator<T>(_atoms, _Deltat, _IsAngstroem), | 
|---|
|  | 55 | maxSteps(_maxSteps) | 
|---|
|  | 56 | {} | 
|---|
|  | 57 | /** Destructor of class ForceAnnealing. | 
|---|
|  | 58 | * | 
|---|
|  | 59 | */ | 
|---|
|  | 60 | ~ForceAnnealing() | 
|---|
|  | 61 | {} | 
|---|
|  | 62 |  | 
|---|
|  | 63 | /** Performs Gradient optimization. | 
|---|
|  | 64 | * | 
|---|
|  | 65 | * We assume that forces have just been calculated. | 
|---|
|  | 66 | * | 
|---|
|  | 67 | * | 
|---|
|  | 68 | * \param NextStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet) | 
|---|
|  | 69 | * \param offset offset in matrix file to the first force component | 
|---|
|  | 70 | * \todo This is not yet checked if it is correctly working with DoConstrainedMD set >0. | 
|---|
|  | 71 | */ | 
|---|
|  | 72 | void operator()(const int NextStep, const size_t offset) | 
|---|
|  | 73 | { | 
|---|
|  | 74 | // make sum of forces equal zero | 
|---|
|  | 75 | AtomicForceManipulator<T>::correctForceMatrixForFixedCenterOfMass(offset,NextStep); | 
|---|
|  | 76 |  | 
|---|
|  | 77 | // are we in initial step? Then set static entities | 
|---|
|  | 78 | if (currentStep == 0) { | 
|---|
|  | 79 | currentDeltat = AtomicForceManipulator<T>::Deltat; | 
|---|
|  | 80 | currentStep = 1; | 
|---|
|  | 81 | LOG(2, "DEBUG: Initial step, setting values, current step is #" << currentStep); | 
|---|
|  | 82 | } else { | 
|---|
|  | 83 | ++currentStep; | 
|---|
|  | 84 | LOG(2, "DEBUG: current step is #" << currentStep); | 
|---|
|  | 85 | } | 
|---|
|  | 86 |  | 
|---|
|  | 87 | // are we in initial step? Then don't check against velocity | 
|---|
| [7f833c] | 88 | Vector maxComponents(zeroVec); | 
|---|
| [1a48d2] | 89 | for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin(); | 
|---|
|  | 90 | iter != AtomicForceManipulator<T>::atoms.end(); ++iter) { | 
|---|
|  | 91 | // atom's force vector gives steepest descent direction | 
|---|
|  | 92 | const Vector currentPosition = (*iter)->getPosition(); | 
|---|
|  | 93 | const Vector currentGradient = (*iter)->getAtomicForce(); | 
|---|
|  | 94 | LOG(4, "DEBUG: Force for atom " << **iter << " is " << currentGradient); | 
|---|
|  | 95 | Vector PositionUpdate = currentDeltat * currentGradient; | 
|---|
|  | 96 | LOG(3, "DEBUG: Update would be " << PositionUpdate); | 
|---|
|  | 97 |  | 
|---|
| [7f833c] | 98 | // extract largest components for showing progress of annealing | 
|---|
|  | 99 | for(size_t i=0;i<NDIM;++i) | 
|---|
|  | 100 | if (currentGradient[i] > maxComponents[i]) | 
|---|
|  | 101 | maxComponents[i] = currentGradient[i]; | 
|---|
|  | 102 |  | 
|---|
| [1a48d2] | 103 | // update with currentDelta tells us how the current gradient relates to | 
|---|
|  | 104 | // the last one: If it has become larger, reduce currentDelta | 
|---|
|  | 105 | if ((currentStep > 1) && (!(*iter)->getAtomicVelocity().IsZero())) | 
|---|
|  | 106 | if ((PositionUpdate.ScalarProduct((*iter)->getAtomicVelocity()) < 0) | 
|---|
|  | 107 | && (currentDeltat > MinimumDeltat)) { | 
|---|
|  | 108 | currentDeltat = .5*currentDeltat; | 
|---|
|  | 109 | LOG(2, "DEBUG: Upgrade in other direction: " << PositionUpdate.NormSquared() | 
|---|
|  | 110 | << " > " << (*iter)->getAtomicVelocity().NormSquared() | 
|---|
|  | 111 | << ", decreasing deltat: " << currentDeltat); | 
|---|
|  | 112 | PositionUpdate = currentDeltat * currentGradient; | 
|---|
|  | 113 | } | 
|---|
|  | 114 |  | 
|---|
|  | 115 | // finally set new values | 
|---|
|  | 116 | (*iter)->setPosition(currentPosition + PositionUpdate); | 
|---|
|  | 117 | (*iter)->setAtomicVelocity(PositionUpdate); | 
|---|
|  | 118 | //std::cout << "Id of atom is " << (*iter)->getId() << std::endl; | 
|---|
|  | 119 | //        (*iter)->VelocityVerletUpdateU((*iter)->getId(), NextStep-1, Deltat, IsAngstroem); | 
|---|
|  | 120 |  | 
|---|
|  | 121 | // reset force vector for next step except on final one | 
|---|
|  | 122 | if (currentStep != maxSteps) | 
|---|
|  | 123 | (*iter)->setAtomicForce(zeroVec); | 
|---|
|  | 124 | } | 
|---|
|  | 125 |  | 
|---|
| [7f833c] | 126 | LOG(1, "STATUS: Largest remaining force components at step #" | 
|---|
|  | 127 | << currentStep << " are " << maxComponents); | 
|---|
|  | 128 |  | 
|---|
| [1a48d2] | 129 | // are we in final step? Remember to reset static entities | 
|---|
|  | 130 | if (currentStep == maxSteps) { | 
|---|
|  | 131 | LOG(2, "DEBUG: Final step, resetting values"); | 
|---|
|  | 132 | currentDeltat = 0.; | 
|---|
|  | 133 | currentStep = 0; | 
|---|
|  | 134 |  | 
|---|
|  | 135 | // reset (artifical) velocities | 
|---|
|  | 136 | for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin(); | 
|---|
|  | 137 | iter != AtomicForceManipulator<T>::atoms.end(); ++iter) | 
|---|
|  | 138 | (*iter)->setAtomicVelocity(zeroVec); | 
|---|
|  | 139 | } | 
|---|
|  | 140 | } | 
|---|
|  | 141 |  | 
|---|
|  | 142 | private: | 
|---|
|  | 143 | //!> contains the current step in relation to maxsteps | 
|---|
|  | 144 | static size_t currentStep; | 
|---|
|  | 145 | //!> contains the maximum number of steps, determines initial and final step with currentStep | 
|---|
|  | 146 | size_t maxSteps; | 
|---|
|  | 147 | static double currentDeltat; | 
|---|
|  | 148 | //!> minimum deltat for internal while loop (adaptive step width) | 
|---|
|  | 149 | static double MinimumDeltat; | 
|---|
|  | 150 | }; | 
|---|
|  | 151 |  | 
|---|
|  | 152 | template <class T> | 
|---|
|  | 153 | double ForceAnnealing<T>::currentDeltat = 0.; | 
|---|
|  | 154 | template <class T> | 
|---|
|  | 155 | size_t ForceAnnealing<T>::currentStep = 0; | 
|---|
|  | 156 | template <class T> | 
|---|
|  | 157 | double ForceAnnealing<T>::MinimumDeltat = 1e-8; | 
|---|
|  | 158 |  | 
|---|
|  | 159 | #endif /* FORCEANNEALING_HPP_ */ | 
|---|