Changeset 8450da for src/Dynamics
- Timestamp:
- Apr 10, 2018, 6:43:31 AM (7 years ago)
- Branches:
- AutomationFragmentation_failures, Candidate_v1.6.1, ChemicalSpaceEvaluator, Exclude_Hydrogens_annealWithBondGraph, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_contraction-expansion, Gui_displays_atomic_force_velocity, PythonUI_with_named_parameters, StoppableMakroAction, TremoloParser_IncreasedPrecision
- Children:
- 6a5921, 897a01
- Parents:
- 90ece9
- git-author:
- Frederik Heber <frederik.heber@…> (08/03/17 09:24:07)
- git-committer:
- Frederik Heber <frederik.heber@…> (04/10/18 06:43:31)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Dynamics/ForceAnnealing.hpp
r90ece9 r8450da 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 time step to update (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 … … 163 167 * We assume that forces have just been calculated. 164 168 * 165 * \param CurrentTimeStep current time step(i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)169 * \param _TimeStep time step to update (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet) 166 170 * \return to be filled with maximum force component over all atoms 167 171 */ 168 172 Vector anneal( 169 const int CurrentTimeStep)173 const int _TimeStep) 170 174 { 175 const int CurrentTimeStep = _TimeStep-1; 176 ASSERT( CurrentTimeStep >= 0, 177 "ForceAnnealing::anneal() - a new time step (upon which we work) must already have been copied."); 178 179 LOG(1, "STATUS: performing simple anneal with default stepwidth " << currentDeltat << " at step #" << currentStep); 180 171 181 Vector maxComponents; 172 182 bool deltat_decreased = false; … … 174 184 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) { 175 185 // atom's force vector gives steepest descent direction 176 const Vector oldPosition = (*iter)->getPositionAtStep(CurrentTimeStep-1 >= 0 ? CurrentTimeStep - 1 : 0);177 186 const Vector currentPosition = (*iter)->getPositionAtStep(CurrentTimeStep); 178 const Vector oldGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep-1 >= 0 ? CurrentTimeStep - 1 : 0);179 187 const Vector currentGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep); 180 LOG(4, "DEBUG: oldPosition for atom " << **iter << " is " << oldPosition); 181 LOG(4, "DEBUG: currentPosition for atom " << **iter << " is " << currentPosition); 182 LOG(4, "DEBUG: oldGradient for atom " << **iter << " is " << oldGradient); 183 LOG(4, "DEBUG: currentGradient for atom " << **iter << " is " << currentGradient); 188 LOG(4, "DEBUG: currentPosition for atom #" << (*iter)->getId() << " is " << currentPosition); 189 LOG(4, "DEBUG: currentGradient for atom #" << (*iter)->getId() << " is " << currentGradient); 184 190 // LOG(4, "DEBUG: Force for atom " << **iter << " is " << currentGradient); 185 191 186 192 // we use Barzilai-Borwein update with position reversed to get descent 187 const double stepwidth = getBarzilaiBorweinStepwidth( 188 currentPosition - oldPosition, currentGradient - oldGradient); 193 double stepwidth = currentDeltat; 189 194 Vector PositionUpdate = stepwidth * currentGradient; 190 195 LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate); … … 197 202 // have different sign: Check whether this is the case and one step with 198 203 // deltat to interrupt this sequence 199 const Vector PositionDifference = currentPosition - oldPosition; 200 if ((currentStep > 1) && (!PositionDifference.IsZero())) 204 if (currentStep > 1) { 205 const int OldTimeStep = CurrentTimeStep-1; 206 ASSERT( OldTimeStep >= 0, 207 "ForceAnnealing::anneal() - if currentStep is "+toString(currentStep) 208 +", then there should be at least three time steps."); 209 const Vector oldPosition = (*iter)->getPositionAtStep(OldTimeStep); 210 const Vector PositionDifference = currentPosition - oldPosition; 211 LOG(4, "DEBUG: oldPosition for atom #" << (*iter)->getId() << " is " << oldPosition); 212 LOG(4, "DEBUG: PositionDifference for atom #" << (*iter)->getId() << " is " << PositionDifference); 201 213 if ((PositionUpdate.ScalarProduct(PositionDifference) < 0) 202 214 && (fabs(PositionUpdate.NormSquared()-PositionDifference.NormSquared()) < 1e-3)) { … … 210 222 << ", using deltat: " << currentDeltat); 211 223 PositionUpdate = currentDeltat * currentGradient; 224 } 212 225 } 213 226 214 227 // finally set new values 215 (*iter)->setPosition(currentPosition + PositionUpdate); 228 (*iter)->setPositionAtStep(_TimeStep, currentPosition + PositionUpdate); 229 } 230 231 return maxComponents; 232 } 233 234 /** Performs Gradient optimization on the atoms using BarzilaiBorwein step width. 235 * 236 * \note this can only be called when there are at least two optimization 237 * time steps present, i.e. this must be preceeded by a simple anneal(). 238 * 239 * We assume that forces have just been calculated. 240 * 241 * \param _TimeStep time step to update (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet) 242 * \return to be filled with maximum force component over all atoms 243 */ 244 Vector anneal_BarzilaiBorwein( 245 const int _TimeStep) 246 { 247 const int OldTimeStep = _TimeStep-2; 248 const int CurrentTimeStep = _TimeStep-1; 249 ASSERT( OldTimeStep >= 0, 250 "ForceAnnealing::anneal_BarzilaiBorwein() - we need two present optimization steps to compute stepwidth."); 251 ASSERT(currentStep > 1, 252 "ForceAnnealing::anneal_BarzilaiBorwein() - we need two present optimization steps to compute stepwidth."); 253 254 LOG(1, "STATUS: performing BarzilaiBorwein anneal at step #" << currentStep); 255 256 Vector maxComponents; 257 bool deltat_decreased = false; 258 for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin(); 259 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) { 260 // atom's force vector gives steepest descent direction 261 const Vector oldPosition = (*iter)->getPositionAtStep(OldTimeStep); 262 const Vector currentPosition = (*iter)->getPositionAtStep(CurrentTimeStep); 263 const Vector oldGradient = (*iter)->getAtomicForceAtStep(OldTimeStep); 264 const Vector currentGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep); 265 LOG(4, "DEBUG: oldPosition for atom #" << (*iter)->getId() << " is " << oldPosition); 266 LOG(4, "DEBUG: currentPosition for atom #" << (*iter)->getId() << " is " << currentPosition); 267 LOG(4, "DEBUG: oldGradient for atom #" << (*iter)->getId() << " is " << oldGradient); 268 LOG(4, "DEBUG: currentGradient for atom #" << (*iter)->getId() << " is " << currentGradient); 269 // LOG(4, "DEBUG: Force for atom #" << (*iter)->getId() << " is " << currentGradient); 270 271 // we use Barzilai-Borwein update with position reversed to get descent 272 const Vector PositionDifference = currentPosition - oldPosition; 273 const Vector GradientDifference = (currentGradient - oldGradient); 274 double stepwidth = getBarzilaiBorweinStepwidth(PositionDifference, GradientDifference); 275 Vector PositionUpdate = stepwidth * currentGradient; 276 LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate); 277 278 // extract largest components for showing progress of annealing 279 for(size_t i=0;i<NDIM;++i) 280 maxComponents[i] = std::max(maxComponents[i], fabs(currentGradient[i])); 281 282 // // steps may go back and forth again (updates are of same magnitude but 283 // // have different sign: Check whether this is the case and one step with 284 // // deltat to interrupt this sequence 285 // if (!PositionDifference.IsZero()) 286 // if ((PositionUpdate.ScalarProduct(PositionDifference) < 0) 287 // && (fabs(PositionUpdate.NormSquared()-PositionDifference.NormSquared()) < 1e-3)) { 288 // // for convergence we want a null sequence here, too 289 // if (!deltat_decreased) { 290 // deltat_decreased = true; 291 // currentDeltat = .5*currentDeltat; 292 // } 293 // LOG(2, "DEBUG: Upgrade in other direction: " << PositionUpdate 294 // << " > " << PositionDifference 295 // << ", using deltat: " << currentDeltat); 296 // PositionUpdate = currentDeltat * currentGradient; 297 // } 298 299 // finally set new values 300 (*iter)->setPositionAtStep(_TimeStep, currentPosition + PositionUpdate); 216 301 } 217 302 … … 256 341 } 257 342 258 /** Performs Gradient optimization on the bonds. 343 /** Performs Gradient optimization on the bonds with BarzilaiBorwein stepwdith. 344 * 345 * \note this can only be called when there are at least two optimization 346 * time steps present, i.e. this must be preceeded by a simple anneal(). 259 347 * 260 348 * We assume that forces have just been calculated. These forces are projected … … 263 351 * 264 352 * 265 * \param CurrentTimeStep current time step(i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)353 * \param _TimeStep time step to update (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet) 266 354 * \param maxComponents to be filled with maximum force component over all atoms 267 355 */ 268 Vector annealWithBondGraph (269 const int CurrentTimeStep)356 Vector annealWithBondGraph_BarzilaiBorwein( 357 const int _TimeStep) 270 358 { 359 const int OldTimeStep = _TimeStep-2; 360 const int CurrentTimeStep = _TimeStep-1; 361 ASSERT(OldTimeStep >= 0, 362 "annealWithBondGraph_BarzilaiBorwein() - we need two present optimization steps to compute stepwidth, and the new one to update on already present."); 363 ASSERT(currentStep > 1, 364 "annealWithBondGraph_BarzilaiBorwein() - we need two present optimization steps to compute stepwidth."); 365 366 LOG(1, "STATUS: performing BarzilaiBorwein anneal on bonds at step #" << currentStep); 367 271 368 Vector maxComponents; 272 369 … … 309 406 AtomicForceManipulator<T>::atoms.begin(), 310 407 AtomicForceManipulator<T>::atoms.end(), 311 CurrentTimeStep);408 _TimeStep); // use time step to update here as this is the current set of bonds 312 409 const BondVectors::container_t &sorted_bonds = bv.getSorted(); 313 410 … … 328 425 RemnantGradient_per_atom_t RemnantGradient_per_atom; 329 426 for (size_t timestep = 0; timestep <= 1; ++timestep) { 330 const size_t CurrentStep = CurrentTimeStep-timestep-1 >= 0 ? CurrentTimeStep-timestep-1 : 0;331 LOG(2, "DEBUG: CurrentTimeStep is " << CurrentTimeStep427 const size_t ReferenceTimeStep = CurrentTimeStep-timestep; 428 LOG(2, "DEBUG: given time step is " << _TimeStep 332 429 << ", timestep is " << timestep 333 << ", and CurrentStep is " << CurrentStep);430 << ", and ReferenceTimeStep is " << ReferenceTimeStep); 334 431 335 432 for(typename AtomSetMixin<T>::const_iterator iter = AtomicForceManipulator<T>::atoms.begin(); 336 433 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) { 337 434 const atom &walker = *(*iter); 338 const Vector &walkerGradient = walker.getAtomicForceAtStep( CurrentStep);435 const Vector &walkerGradient = walker.getAtomicForceAtStep(ReferenceTimeStep); 339 436 LOG(3, "DEBUG: Gradient of atom #" << walker.getId() << ", namely " 340 437 << walker << " is " << walkerGradient << " with magnitude of " … … 346 443 // gather subset of BondVectors for the current atom 347 444 const std::vector<Vector> BondVectors = 348 bv.getAtomsBondVectorsAtStep(walker, CurrentStep);445 bv.getAtomsBondVectorsAtStep(walker, ReferenceTimeStep); 349 446 350 447 // go through all its bonds and calculate what magnitude is represented … … 353 450 weights_per_atom[timestep].insert( 354 451 std::make_pair(walker.getId(), 355 bv.getWeightsForAtomAtStep(walker, BondVectors, CurrentStep)) );452 bv.getWeightsForAtomAtStep(walker, BondVectors, ReferenceTimeStep)) ); 356 453 ASSERT( inserter.second, 357 454 "ForceAnnealing::operator() - weight map for atom "+toString(walker) … … 441 538 LOG(4, "DEBUG: current projected gradient for " 442 539 << (side == leftside ? "left" : "right") << " side of bond is " << currentGradient); 443 const Vector &oldPosition = bondatom[side]->getPositionAtStep( CurrentTimeStep-2 >= 0 ? CurrentTimeStep - 2 : 0);444 const Vector ¤tPosition = bondatom[side]->getPositionAtStep(CurrentTimeStep -1>=0 ? CurrentTimeStep - 1 : 0);540 const Vector &oldPosition = bondatom[side]->getPositionAtStep(OldTimeStep); 541 const Vector ¤tPosition = bondatom[side]->getPositionAtStep(CurrentTimeStep); 445 542 const Vector PositionDifference = currentPosition - oldPosition; 446 543 LOG(4, "DEBUG: old position is " << oldPosition); … … 491 588 atom &walker = *(*iter); 492 589 // extract largest components for showing progress of annealing 493 const Vector currentGradient = walker.getAtomicForceAtStep(CurrentTimeStep -1>=0 ? CurrentTimeStep-1 : 0);590 const Vector currentGradient = walker.getAtomicForceAtStep(CurrentTimeStep); 494 591 for(size_t i=0;i<NDIM;++i) 495 592 maxComponents[i] = std::max(maxComponents[i], fabs(currentGradient[i])); 496 497 // reset force vector for next step except on final one498 if (currentStep != maxSteps)499 walker.setAtomicForce(zeroVec);500 593 } 501 594 … … 521 614 LOG(3, "DEBUG: Applying update " << update << " to atom #" << atomid 522 615 << ", namely " << *walker); 523 walker->setPosition (524 walker->getPositionAtStep(CurrentTimeStep -1>=0 ? CurrentTimeStep - 1 : 0)616 walker->setPositionAtStep(_TimeStep, 617 walker->getPositionAtStep(CurrentTimeStep) 525 618 + update - CommonTranslation); 526 walker->setAtomicVelocity(update);527 619 // walker->setAtomicForce( RemnantGradient_per_atom[walker->getId()] ); 528 620 }
Note:
See TracChangeset
for help on using the changeset viewer.