Changeset fcc860 for src/Dynamics/ForceAnnealing.hpp
- Timestamp:
- Aug 3, 2017, 10:44:57 AM (8 years ago)
- Branches:
- ForceAnnealing_with_BondGraph_continued
- Children:
- 4919f0
- Parents:
- 93fd2a6
- git-author:
- Frederik Heber <frederik.heber@…> (08/03/17 09:24:07)
- git-committer:
- Frederik Heber <frederik.heber@…> (08/03/17 10:44:57)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Dynamics/ForceAnnealing.hpp
r93fd2a6 rfcc860 92 92 * 93 93 * 94 * \param CurrentTimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)94 * \param _TimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet) 95 95 * \param offset offset in matrix file to the first force component 96 96 * \todo This is not yet checked if it is correctly working with DoConstrainedMD set >0. 97 97 */ 98 98 void operator()( 99 const int _ CurrentTimeStep,99 const int _TimeStep, 100 100 const size_t _offset, 101 101 const bool _UseBondgraph) 102 102 { 103 const int CurrentTimeStep = _TimeStep-1; 104 ASSERT( CurrentTimeStep >= 0, 105 "ForceAnnealing::operator() - a new time step (upon which we work) must already have been copied."); 106 103 107 // make sum of forces equal zero 104 108 AtomicForceManipulator<T>::correctForceMatrixForFixedCenterOfMass( 105 109 _offset, 106 _CurrentTimeStep-1>=0 ? _CurrentTimeStep - 1 : 0);110 CurrentTimeStep); 107 111 108 112 // are we in initial step? Then set static entities … … 114 118 115 119 // always use atomic annealing on first step 116 maxComponents = anneal(_ CurrentTimeStep);120 maxComponents = anneal(_TimeStep); 117 121 } else { 118 122 ++currentStep; … … 121 125 // bond graph annealing is always followed by a normal annealing 122 126 if (_UseBondgraph) 123 maxComponents = annealWithBondGraph (_CurrentTimeStep);127 maxComponents = annealWithBondGraph_BarzilaiBorwein(_TimeStep); 124 128 // cannot store RemnantGradient in Atom's Force as it ruins BB stepwidth calculation 125 129 else 126 maxComponents = anneal (_CurrentTimeStep);130 maxComponents = anneal_BarzilaiBorwein(_TimeStep); 127 131 } 128 132 … … 141 145 * We assume that forces have just been calculated. 142 146 * 143 * \param CurrentTimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)147 * \param _TimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet) 144 148 * \return to be filled with maximum force component over all atoms 145 149 */ 146 150 Vector anneal( 147 const int CurrentTimeStep)151 const int _TimeStep) 148 152 { 153 const int CurrentTimeStep = _TimeStep-1; 154 ASSERT( CurrentTimeStep >= 0, 155 "ForceAnnealing::anneal() - a new time step (upon which we work) must already have been copied."); 156 157 LOG(1, "STATUS: performing simple anneal with default stepwidth " << currentDeltat << " at step #" << currentStep); 158 149 159 Vector maxComponents; 150 160 bool deltat_decreased = false; … … 152 162 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) { 153 163 // atom's force vector gives steepest descent direction 154 const Vector oldPosition = (*iter)->getPositionAtStep(CurrentTimeStep-2 >= 0 ? CurrentTimeStep - 2 : 0); 155 const Vector currentPosition = (*iter)->getPositionAtStep(CurrentTimeStep-1>=0 ? CurrentTimeStep - 1 : 0); 156 const Vector oldGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep-2 >= 0 ? CurrentTimeStep - 2 : 0); 157 const Vector currentGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep-1>=0 ? CurrentTimeStep - 1 : 0); 158 LOG(4, "DEBUG: oldPosition for atom " << **iter << " is " << oldPosition); 159 LOG(4, "DEBUG: currentPosition for atom " << **iter << " is " << currentPosition); 160 LOG(4, "DEBUG: oldGradient for atom " << **iter << " is " << oldGradient); 161 LOG(4, "DEBUG: currentGradient for atom " << **iter << " is " << currentGradient); 164 const Vector currentPosition = (*iter)->getPositionAtStep(CurrentTimeStep); 165 const Vector currentGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep); 166 LOG(4, "DEBUG: currentPosition for atom #" << (*iter)->getId() << " is " << currentPosition); 167 LOG(4, "DEBUG: currentGradient for atom #" << (*iter)->getId() << " is " << currentGradient); 162 168 // LOG(4, "DEBUG: Force for atom " << **iter << " is " << currentGradient); 163 169 164 170 // we use Barzilai-Borwein update with position reversed to get descent 165 const Vector PositionDifference = currentPosition - oldPosition; 166 const Vector GradientDifference = (currentGradient - oldGradient); 167 double stepwidth = 0.; 168 if (GradientDifference.Norm() > MYEPSILON) 169 stepwidth = fabs(PositionDifference.ScalarProduct(GradientDifference))/ 170 GradientDifference.NormSquared(); 171 if (fabs(stepwidth) < 1e-10) { 172 // dont' warn in first step, deltat usage normal 173 if (currentStep != 1) 174 ELOG(1, "INFO: Barzilai-Borwein stepwidth is zero, using deltat " << currentDeltat << " instead."); 175 stepwidth = currentDeltat; 176 } 171 double stepwidth = currentDeltat; 177 172 Vector PositionUpdate = stepwidth * currentGradient; 178 173 LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate); … … 186 181 // have different sign: Check whether this is the case and one step with 187 182 // deltat to interrupt this sequence 188 if ((currentStep > 1) && (!PositionDifference.IsZero())) 183 if (currentStep > 1) { 184 const int OldTimeStep = _TimeStep-2; 185 ASSERT( OldTimeStep >= 0, 186 "ForceAnnealing::anneal() - if currentStep is "+toString(currentStep) 187 +", then there should be at least three time steps."); 188 const Vector oldPosition = (*iter)->getPositionAtStep(OldTimeStep); 189 const Vector PositionDifference = currentPosition - oldPosition; 190 LOG(4, "DEBUG: oldPosition for atom #" << (*iter)->getId() << " is " << oldPosition); 191 LOG(4, "DEBUG: PositionDifference for atom #" << (*iter)->getId() << " is " << PositionDifference); 189 192 if ((PositionUpdate.ScalarProduct(PositionDifference) < 0) 190 193 && (fabs(PositionUpdate.NormSquared()-PositionDifference.NormSquared()) < 1e-3)) { … … 198 201 << ", using deltat: " << currentDeltat); 199 202 PositionUpdate = currentDeltat * currentGradient; 203 } 200 204 } 201 205 202 206 // finally set new values 203 (*iter)->setPosition (currentPosition + PositionUpdate);207 (*iter)->setPositionAtStep(_TimeStep, currentPosition + PositionUpdate); 204 208 } 209 210 return maxComponents; 211 } 212 213 /** Performs Gradient optimization on the atoms using BarzilaiBorwein step width. 214 * 215 * \note this can only be called when there are at least two optimization 216 * time steps present, i.e. this must be preceeded by a simple anneal(). 217 * 218 * We assume that forces have just been calculated. 219 * 220 * \param _TimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet) 221 * \return to be filled with maximum force component over all atoms 222 */ 223 Vector anneal_BarzilaiBorwein( 224 const int _TimeStep) 225 { 226 const int OldTimeStep = _TimeStep-2; 227 const int CurrentTimeStep = _TimeStep-1; 228 ASSERT( OldTimeStep >= 0, 229 "ForceAnnealing::anneal_BarzilaiBorwein() - we need two present optimization steps to compute stepwidth."); 230 ASSERT(currentStep > 1, 231 "ForceAnnealing::anneal_BarzilaiBorwein() - we need two present optimization steps to compute stepwidth."); 232 233 LOG(1, "STATUS: performing BarzilaiBorwein anneal at step #" << currentStep); 234 235 Vector maxComponents; 236 bool deltat_decreased = false; 237 for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin(); 238 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) { 239 // atom's force vector gives steepest descent direction 240 const Vector oldPosition = (*iter)->getPositionAtStep(OldTimeStep); 241 const Vector currentPosition = (*iter)->getPositionAtStep(CurrentTimeStep); 242 const Vector oldGradient = (*iter)->getAtomicForceAtStep(OldTimeStep); 243 const Vector currentGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep); 244 LOG(4, "DEBUG: oldPosition for atom #" << (*iter)->getId() << " is " << oldPosition); 245 LOG(4, "DEBUG: currentPosition for atom #" << (*iter)->getId() << " is " << currentPosition); 246 LOG(4, "DEBUG: oldGradient for atom #" << (*iter)->getId() << " is " << oldGradient); 247 LOG(4, "DEBUG: currentGradient for atom #" << (*iter)->getId() << " is " << currentGradient); 248 // LOG(4, "DEBUG: Force for atom #" << (*iter)->getId() << " is " << currentGradient); 249 250 // we use Barzilai-Borwein update with position reversed to get descent 251 const Vector PositionDifference = currentPosition - oldPosition; 252 const Vector GradientDifference = (currentGradient - oldGradient); 253 double stepwidth = 0.; 254 if (GradientDifference.Norm() > MYEPSILON) 255 stepwidth = fabs(PositionDifference.ScalarProduct(GradientDifference))/ 256 GradientDifference.NormSquared(); 257 if (fabs(stepwidth) < 1e-10) { 258 // dont' warn in first step, deltat usage normal 259 if (currentStep != 1) 260 ELOG(1, "INFO: Barzilai-Borwein stepwidth is zero, using deltat " << currentDeltat << " instead."); 261 stepwidth = currentDeltat; 262 } 263 Vector PositionUpdate = stepwidth * currentGradient; 264 LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate); 265 266 // extract largest components for showing progress of annealing 267 for(size_t i=0;i<NDIM;++i) 268 if (currentGradient[i] > maxComponents[i]) 269 maxComponents[i] = currentGradient[i]; 270 271 // steps may go back and forth again (updates are of same magnitude but 272 // have different sign: Check whether this is the case and one step with 273 // deltat to interrupt this sequence 274 if (!PositionDifference.IsZero()) 275 if ((PositionUpdate.ScalarProduct(PositionDifference) < 0) 276 && (fabs(PositionUpdate.NormSquared()-PositionDifference.NormSquared()) < 1e-3)) { 277 // for convergence we want a null sequence here, too 278 if (!deltat_decreased) { 279 deltat_decreased = true; 280 currentDeltat = .5*currentDeltat; 281 } 282 LOG(2, "DEBUG: Upgrade in other direction: " << PositionUpdate 283 << " > " << PositionDifference 284 << ", using deltat: " << currentDeltat); 285 PositionUpdate = currentDeltat * currentGradient; 286 } 287 288 // finally set new values 289 (*iter)->setPositionAtStep(_TimeStep, currentPosition + PositionUpdate); 290 } 205 291 206 292 return maxComponents; … … 244 330 } 245 331 246 /** Performs Gradient optimization on the bonds. 332 /** Performs Gradient optimization on the bonds with BarzilaiBorwein stepwdith. 333 * 334 * \note this can only be called when there are at least two optimization 335 * time steps present, i.e. this must be preceeded by a simple anneal(). 247 336 * 248 337 * We assume that forces have just been calculated. These forces are projected … … 251 340 * 252 341 * 253 * \param CurrentTimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)342 * \param _TimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet) 254 343 * \param maxComponents to be filled with maximum force component over all atoms 255 344 */ 256 Vector annealWithBondGraph (257 const int CurrentTimeStep)345 Vector annealWithBondGraph_BarzilaiBorwein( 346 const int _TimeStep) 258 347 { 348 const int OldTimeStep = _TimeStep-2; 349 const int CurrentTimeStep = _TimeStep-1; 350 ASSERT(currentStep > 1, 351 "annealWithBondGraph_BarzilaiBorwein() - we need two present optimization steps to compute stepwidth."); 352 ASSERT(OldTimeStep >= 0, 353 "annealWithBondGraph_BarzilaiBorwein() - we need two present optimization steps to compute stepwidth, and the new one to update on already present."); 354 355 LOG(1, "STATUS: performing BarzilaiBorwein anneal on bonds at step #" << currentStep); 356 259 357 Vector maxComponents; 260 358 … … 297 395 AtomicForceManipulator<T>::atoms.begin(), 298 396 AtomicForceManipulator<T>::atoms.end(), 299 CurrentTimeStep);397 _TimeStep); 300 398 const BondVectors::container_t &sorted_bonds = bv.getSorted(); 301 399 … … 316 414 RemnantGradient_per_atom_t RemnantGradient_per_atom; 317 415 for (size_t timestep = 0; timestep <= 1; ++timestep) { 318 const size_t CurrentStep = CurrentTimeStep-timestep-1 >= 0 ? CurrentTimeStep-timestep-1 : 0;319 LOG(2, "DEBUG: CurrentTimeStep is " << CurrentTimeStep416 const size_t ReferenceTimeStep = _TimeStep-timestep-1; 417 LOG(2, "DEBUG: given time step is " << _TimeStep 320 418 << ", timestep is " << timestep 321 << ", and CurrentStep is " << CurrentStep);419 << ", and ReferenceTimeStep is " << ReferenceTimeStep); 322 420 323 421 for(typename AtomSetMixin<T>::const_iterator iter = AtomicForceManipulator<T>::atoms.begin(); 324 422 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) { 325 423 const atom &walker = *(*iter); 326 const Vector &walkerGradient = walker.getAtomicForceAtStep( CurrentStep);424 const Vector &walkerGradient = walker.getAtomicForceAtStep(ReferenceTimeStep); 327 425 LOG(3, "DEBUG: Gradient of atom #" << walker.getId() << ", namely " 328 426 << walker << " is " << walkerGradient); … … 333 431 // gather subset of BondVectors for the current atom 334 432 const std::vector<Vector> BondVectors = 335 bv.getAtomsBondVectorsAtStep(walker, CurrentStep);433 bv.getAtomsBondVectorsAtStep(walker, ReferenceTimeStep); 336 434 337 435 // go through all its bonds and calculate what magnitude is represented … … 340 438 weights_per_atom[timestep].insert( 341 439 std::make_pair(walker.getId(), 342 bv.getWeightsForAtomAtStep(walker, BondVectors, CurrentStep)) );440 bv.getWeightsForAtomAtStep(walker, BondVectors, ReferenceTimeStep)) ); 343 441 ASSERT( inserter.second, 344 442 "ForceAnnealing::operator() - weight map for atom "+toString(walker) … … 428 526 LOG(4, "DEBUG: current projected gradient for " 429 527 << (side == leftside ? "left" : "right") << " side of bond is " << currentGradient); 430 const Vector &oldPosition = bondatom[side]->getPositionAtStep( CurrentTimeStep-2 >= 0 ? CurrentTimeStep - 2 : 0);431 const Vector ¤tPosition = bondatom[side]->getPositionAtStep(CurrentTimeStep -1>=0 ? CurrentTimeStep - 1 : 0);528 const Vector &oldPosition = bondatom[side]->getPositionAtStep(OldTimeStep); 529 const Vector ¤tPosition = bondatom[side]->getPositionAtStep(CurrentTimeStep); 432 530 const Vector PositionDifference = currentPosition - oldPosition; 433 531 LOG(4, "DEBUG: old position is " << oldPosition); … … 478 576 atom &walker = *(*iter); 479 577 // extract largest components for showing progress of annealing 480 const Vector currentGradient = walker.getAtomicForceAtStep(CurrentTimeStep -1>=0 ? CurrentTimeStep-1 : 0);578 const Vector currentGradient = walker.getAtomicForceAtStep(CurrentTimeStep); 481 579 for(size_t i=0;i<NDIM;++i) 482 580 if (currentGradient[i] > maxComponents[i]) … … 505 603 LOG(3, "DEBUG: Applying update " << update << " to atom #" << atomid 506 604 << ", namely " << *walker); 507 walker->setPosition( 508 walker->getPositionAtStep(CurrentTimeStep-1>=0 ? CurrentTimeStep - 1 : 0) 509 + update - CommonTranslation); 605 walker->setPositionAtStep(_TimeStep, 606 walker->getPositionAtStep(CurrentTimeStep) + update - CommonTranslation); 510 607 // walker->setAtomicForce( RemnantGradient_per_atom[walker->getId()] ); 511 608 }
Note:
See TracChangeset
for help on using the changeset viewer.