Changeset b3aaf4 for src/Dynamics
- Timestamp:
- Jun 20, 2018, 8:21:13 AM (7 years ago)
- Branches:
- Candidate_v1.6.1, ChemicalSpaceEvaluator, Exclude_Hydrogens_annealWithBondGraph, ForceAnnealing_with_BondGraph_contraction-expansion
- Children:
- 31baf0
- Parents:
- 883d98
- git-author:
- Frederik Heber <frederik.heber@…> (12/05/17 09:10:11)
- git-committer:
- Frederik Heber <frederik.heber@…> (06/20/18 08:21:13)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Dynamics/ForceAnnealing.hpp
r883d98 rb3aaf4 17 17 #include <functional> 18 18 #include <iterator> 19 #include <math.h> 19 20 20 21 #include <boost/bind.hpp> … … 167 168 { 168 169 double stepwidth = 0.; 169 if (_GradientDifference.Norm Squared() > MYEPSILON)170 if (_GradientDifference.Norm() > MYEPSILON) 170 171 stepwidth = fabs(_PositionDifference.ScalarProduct(_GradientDifference))/ 171 172 _GradientDifference.NormSquared(); … … 200 201 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) { 201 202 // atom's force vector gives steepest descent direction 202 const Vector currentPosition = (*iter)->getPositionAtStep(CurrentTimeStep);203 const Vector currentGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep);203 const Vector ¤tPosition = (*iter)->getPositionAtStep(CurrentTimeStep); 204 const Vector ¤tGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep); 204 205 LOG(4, "DEBUG: currentPosition for atom #" << (*iter)->getId() << " is " << currentPosition); 205 206 LOG(4, "DEBUG: currentGradient for atom #" << (*iter)->getId() << " is " << currentGradient); … … 248 249 } 249 250 251 /** Performs Gradient optimization on a single atom using BarzilaiBorwein step width. 252 * 253 * \param _atom atom to anneal 254 * \param OldTimeStep old time step 255 * \param CurrentTimeStep current time step whose gradient we've just calculated 256 * \param TimeStepToSet time step to update (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet) 257 */ 258 void annealAtom_BarzilaiBorwein( 259 atom * const _atom, 260 const int &OldTimeStep, 261 const int &CurrentTimeStep, 262 const int &TimeStepToSet 263 ) 264 { 265 // atom's force vector gives steepest descent direction 266 const Vector &oldPosition = _atom->getPositionAtStep(OldTimeStep); 267 const Vector ¤tPosition = _atom->getPositionAtStep(CurrentTimeStep); 268 const Vector &oldGradient = _atom->getAtomicForceAtStep(OldTimeStep); 269 const Vector ¤tGradient = _atom->getAtomicForceAtStep(CurrentTimeStep); 270 LOG(4, "DEBUG: oldPosition for atom #" << _atom->getId() << " is " << oldPosition); 271 LOG(4, "DEBUG: currentPosition for atom #" << _atom->getId() << " is " << currentPosition); 272 LOG(4, "DEBUG: oldGradient for atom #" << _atom->getId() << " is " << oldGradient); 273 LOG(4, "DEBUG: currentGradient for atom #" << _atom->getId() << " is " << currentGradient); 274 // LOG(4, "DEBUG: Force for atom #" << _atom->getId() << " is " << currentGradient); 275 276 // we use Barzilai-Borwein update with position reversed to get descent 277 const Vector PositionDifference = currentPosition - oldPosition; 278 const Vector GradientDifference = (currentGradient - oldGradient); 279 double stepwidth = getBarzilaiBorweinStepwidth(PositionDifference, GradientDifference); 280 Vector PositionUpdate = stepwidth * currentGradient; 281 LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate); 282 283 // finally set new values 284 _atom->setPositionAtStep(TimeStepToSet, currentPosition + PositionUpdate); 285 } 286 250 287 /** Performs Gradient optimization on the atoms using BarzilaiBorwein step width. 251 288 * 252 289 * \note this can only be called when there are at least two optimization 253 * time steps present, i.e. this must be prece eded by a simple anneal().290 * time steps present, i.e. this must be preceded by a simple anneal(). 254 291 * 255 292 * We assume that forces have just been calculated. … … 274 311 for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin(); 275 312 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) { 276 // atom's force vector gives steepest descent direction 277 const Vector &oldPosition = (*iter)->getPositionAtStep(OldTimeStep);278 const Vector ¤tPosition = (*iter)->getPositionAtStep(CurrentTimeStep); 279 const Vector &oldGradient = (*iter)->getAtomicForceAtStep(OldTimeStep);313 314 annealAtom_BarzilaiBorwein(*iter, OldTimeStep, CurrentTimeStep, _TimeStep); 315 316 // extract largest components for showing progress of annealing 280 317 const Vector ¤tGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep); 281 LOG(4, "DEBUG: oldPosition for atom #" << (*iter)->getId() << " is " << oldPosition);282 LOG(4, "DEBUG: currentPosition for atom #" << (*iter)->getId() << " is " << currentPosition);283 LOG(4, "DEBUG: oldGradient for atom #" << (*iter)->getId() << " is " << oldGradient);284 LOG(4, "DEBUG: currentGradient for atom #" << (*iter)->getId() << " is " << currentGradient);285 // LOG(4, "DEBUG: Force for atom #" << (*iter)->getId() << " is " << currentGradient);286 287 // we use Barzilai-Borwein update with position reversed to get descent288 const Vector PositionDifference = currentPosition - oldPosition;289 const Vector GradientDifference = (currentGradient - oldGradient);290 double stepwidth = getBarzilaiBorweinStepwidth(PositionDifference, GradientDifference);291 Vector PositionUpdate = stepwidth * currentGradient;292 LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate);293 294 // extract largest components for showing progress of annealing295 318 for(size_t i=0;i<NDIM;++i) 296 319 maxComponents[i] = std::max(maxComponents[i], fabs(currentGradient[i])); 297 298 // finally set new values299 (*iter)->setPositionAtStep(_TimeStep, currentPosition + PositionUpdate);300 320 } 301 321 … … 399 419 400 420 std::map<atomId_t, Vector> GatheredUpdates; //!< gathers all updates which are applied at the end 421 std::map<atomId_t, double> LargestUpdate_per_Atom; //!< check whether updates cancelled each other 401 422 for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin(); 402 423 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) { … … 428 449 } 429 450 Vector PositionUpdate = stepwidth * currentGradient; 451 // cap updates (if non-zero) at 0.2 angstroem. BB tends to overshoot. 452 for (size_t i=0;i<NDIM;++i) 453 if (fabs(PositionUpdate[i]) > MYEPSILON) 454 PositionUpdate[i] = std::min(0.5, fabs(PositionUpdate[i]))*PositionUpdate[i]/fabs(PositionUpdate[i]); 430 455 LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate); 431 456 … … 558 583 // hence, the decision is only based on sides once we have picked a side 559 584 // depending on all bonds associated with have same good type. 560 const double sign = sides[first_per_side[sideno]]; 585 586 // away from gradient (minus) and contracting 587 // or towards gradient (plus) and expanding 588 // gather all on same side and remove 589 const double sign = 590 (sides[first_per_side[sideno]] == types[first_per_side[sideno]]) 591 ? sides[first_per_side[sideno]] : -1.*sides[first_per_side[sideno]]; 592 561 593 LOG(4, "DEBUG: Removing edges from side with sign " << sign); 562 594 BondList::const_iterator bonditer = ListOfBonds.begin(); … … 603 635 if (GatheredUpdates.count((*setiter))) { 604 636 GatheredUpdates[(*setiter)] += factor*PositionUpdate; 637 LargestUpdate_per_Atom[(*setiter)] = 638 std::max(LargestUpdate_per_Atom[(*setiter)], factor*PositionUpdate.Norm()); 605 639 } else { 606 640 GatheredUpdates.insert( … … 608 642 (*setiter), 609 643 factor*PositionUpdate) ); 644 LargestUpdate_per_Atom.insert( 645 std::make_pair( 646 (*setiter), 647 factor*PositionUpdate.Norm()) ); 610 648 } 611 649 } … … 617 655 walker.getId(), 618 656 PositionUpdate) ); 657 LargestUpdate_per_Atom.insert( 658 std::make_pair( 659 walker.getId(), 660 PositionUpdate.Norm()) ); 619 661 } 620 662 } … … 624 666 atom &walker = *(*iter); 625 667 // extract largest components for showing progress of annealing 626 const Vector currentGradient = walker.getAtomicForceAtStep(CurrentTimeStep);668 const Vector ¤tGradient = walker.getAtomicForceAtStep(CurrentTimeStep); 627 669 for(size_t i=0;i<NDIM;++i) 628 670 maxComponents[i] = std::max(maxComponents[i], fabs(currentGradient[i])); … … 653 695 for (size_t i=0;i<NDIM;++i) 654 696 LargestUpdate[i] = std::max(LargestUpdate[i], fabs(update[i])); 655 walker->setPositionAtStep(_TimeStep, 656 walker->getPositionAtStep(CurrentTimeStep) + update); // - CommonTranslation); 697 698 std::map<atomId_t, double>::const_iterator largestiter = LargestUpdate_per_Atom.find(atomid); 699 ASSERT( largestiter != LargestUpdate_per_Atom.end(), 700 "ForceAnnealing() - walker with id "+toString(atomid)+" not in LargestUpdates."); 701 // if we had large updates but their sum is very small 702 if (update.Norm()/largestiter->second > MYEPSILON) { 703 walker->setPositionAtStep(_TimeStep, 704 walker->getPositionAtStep(CurrentTimeStep) + update); // - CommonTranslation); 705 } else { 706 // then recalc update with simple anneal 707 LOG(2, "WARNING: Updates on atom " << *iter << " cancel themselves, performing simple anneal step."); 708 annealAtom_BarzilaiBorwein(walker, OldTimeStep, CurrentTimeStep, _TimeStep); 709 } 657 710 } 658 711 LOG(1, "STATUS: Largest absolute update components are " << LargestUpdate);
Note:
See TracChangeset
for help on using the changeset viewer.