Changeset b2acca for src/Dynamics


Ignore:
Timestamp:
Apr 10, 2018, 6:43:11 AM (7 years ago)
Author:
Frederik Heber <frederik.heber@…>
Branches:
AutomationFragmentation_failures, Candidate_v1.6.1, ChemicalSpaceEvaluator, Enhanced_StructuralOptimization_continued, Exclude_Hydrogens_annealWithBondGraph, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_contraction-expansion, Gui_displays_atomic_force_velocity, PythonUI_with_named_parameters, StoppableMakroAction, TremoloParser_IncreasedPrecision
Children:
216840
Parents:
ecfcf6
git-author:
Frederik Heber <frederik.heber@…> (06/20/17 20:26:12)
git-committer:
Frederik Heber <frederik.heber@…> (04/10/18 06:43:11)
Message:

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.
  • TESTS: Removed XFAIL from ForceAnnealing regression tests as they work now again.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Dynamics/ForceAnnealing.hpp

    recfcf6 rb2acca  
    8080   *
    8181   *
    82    * \param NextStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)
     82   * \param CurrentTimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)
    8383   * \param offset offset in matrix file to the first force component
    8484   * \todo This is not yet checked if it is correctly working with DoConstrainedMD set >0.
    8585   */
    86   void operator()(const int NextStep, const size_t offset)
     86  void operator()(
     87      const int _CurrentTimeStep,
     88      const size_t _offset,
     89      const bool _UseBondgraph)
    8790  {
    8891    // make sum of forces equal zero
    89     AtomicForceManipulator<T>::correctForceMatrixForFixedCenterOfMass(offset,NextStep);
     92    AtomicForceManipulator<T>::correctForceMatrixForFixedCenterOfMass(_offset, _CurrentTimeStep);
    9093
    9194    // are we in initial step? Then set static entities
     95    Vector maxComponents(zeroVec);
    9296    if (currentStep == 0) {
    9397      currentDeltat = AtomicForceManipulator<T>::Deltat;
    9498      currentStep = 1;
    9599      LOG(2, "DEBUG: Initial step, setting values, current step is #" << currentStep);
     100
     101      // always use atomic annealing on first step
     102      anneal(_CurrentTimeStep, _offset, maxComponents);
    96103    } else {
    97104      ++currentStep;
    98105      LOG(2, "DEBUG: current step is #" << currentStep);
    99     }
    100 
     106
     107      if (_UseBondgraph)
     108        annealWithBondGraph(_CurrentTimeStep, _offset, maxComponents);
     109      else
     110        anneal(_CurrentTimeStep, _offset, maxComponents);
     111    }
     112
     113
     114    LOG(1, "STATUS: Largest remaining force components at step #"
     115        << currentStep << " are " << maxComponents);
     116
     117    // are we in final step? Remember to reset static entities
     118    if (currentStep == maxSteps) {
     119      LOG(2, "DEBUG: Final step, resetting values");
     120      reset();
     121    }
     122  }
     123
     124  /** Performs Gradient optimization on the atoms.
     125   *
     126   * We assume that forces have just been calculated.
     127   *
     128   * \param CurrentTimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)
     129   * \param offset offset in matrix file to the first force component
     130   * \param maxComponents to be filled with maximum force component over all atoms
     131   */
     132  void anneal(
     133      const int CurrentTimeStep,
     134      const size_t offset,
     135      Vector &maxComponents)
     136  {
     137    for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
     138        iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
     139      // atom's force vector gives steepest descent direction
     140      const Vector oldPosition = (*iter)->getPositionAtStep(CurrentTimeStep-2 >= 0 ? CurrentTimeStep - 2 : 0);
     141      const Vector currentPosition = (*iter)->getPosition();
     142      const Vector oldGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep-2 >= 0 ? CurrentTimeStep - 2 : 0);
     143      const Vector currentGradient = (*iter)->getAtomicForce();
     144      LOG(4, "DEBUG: oldPosition for atom " << **iter << " is " << oldPosition);
     145      LOG(4, "DEBUG: currentPosition for atom " << **iter << " is " << currentPosition);
     146      LOG(4, "DEBUG: oldGradient for atom " << **iter << " is " << oldGradient);
     147      LOG(4, "DEBUG: currentGradient for atom " << **iter << " is " << currentGradient);
     148//      LOG(4, "DEBUG: Force for atom " << **iter << " is " << currentGradient);
     149
     150      // we use Barzilai-Borwein update with position reversed to get descent
     151      const Vector PositionDifference = currentPosition - oldPosition;
     152      const Vector GradientDifference = (currentGradient - oldGradient);
     153      double stepwidth = 0.;
     154      if (GradientDifference.Norm() > MYEPSILON)
     155        stepwidth = fabs(PositionDifference.ScalarProduct(GradientDifference))/
     156            GradientDifference.NormSquared();
     157      if (fabs(stepwidth) < 1e-10) {
     158        // dont' warn in first step, deltat usage normal
     159        if (currentStep != 1)
     160          ELOG(1, "INFO: Barzilai-Borwein stepwidth is zero, using deltat " << currentDeltat << " instead.");
     161        stepwidth = currentDeltat;
     162      }
     163      Vector PositionUpdate = stepwidth * currentGradient;
     164      LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate);
     165
     166      // extract largest components for showing progress of annealing
     167      for(size_t i=0;i<NDIM;++i)
     168        if (currentGradient[i] > maxComponents[i])
     169          maxComponents[i] = currentGradient[i];
     170
     171      // are we in initial step? Then don't check against velocity
     172      if ((currentStep > 1) && (!(*iter)->getAtomicVelocity().IsZero()))
     173        // update with currentDelta tells us how the current gradient relates to
     174        // the last one: If it has become larger, reduce currentDelta
     175        if ((PositionUpdate.ScalarProduct((*iter)->getAtomicVelocity()) < 0)
     176            && (currentDeltat > MinimumDeltat)) {
     177          currentDeltat = .5*currentDeltat;
     178          LOG(2, "DEBUG: Upgrade in other direction: " << PositionUpdate.NormSquared()
     179              << " > " << (*iter)->getAtomicVelocity().NormSquared()
     180              << ", decreasing deltat: " << currentDeltat);
     181          PositionUpdate = currentDeltat * currentGradient;
     182      }
     183      // finally set new values
     184      (*iter)->setPosition(currentPosition + PositionUpdate);
     185      (*iter)->setAtomicVelocity(PositionUpdate);
     186      //std::cout << "Id of atom is " << (*iter)->getId() << std::endl;
     187//        (*iter)->VelocityVerletUpdateU((*iter)->getId(), CurrentTimeStep-1, Deltat, IsAngstroem);
     188
     189      // reset force vector for next step except on final one
     190      if (currentStep != maxSteps)
     191        (*iter)->setAtomicForce(zeroVec);
     192    }
     193
     194    LOG(1, "STATUS: Largest remaining force components at step #"
     195        << currentStep << " are " << maxComponents);
     196
     197    // are we in final step? Remember to reset static entities
     198    if (currentStep == maxSteps) {
     199      LOG(2, "DEBUG: Final step, resetting values");
     200      reset();
     201    }
     202  }
     203
     204  /** Performs Gradient optimization on the bonds.
     205   *
     206   * We assume that forces have just been calculated. These forces are projected
     207   * onto the bonds and these are annealed subsequently by moving atoms in the
     208   * bond neighborhood on either side conjunctively.
     209   *
     210   *
     211   * \param CurrentTimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)
     212   * \param offset offset in matrix file to the first force component
     213   * \param maxComponents to be filled with maximum force component over all atoms
     214   */
     215  void annealWithBondGraph(
     216      const int CurrentTimeStep,
     217      const size_t offset,
     218      Vector &maxComponents)
     219  {
    101220    // get nodes on either side of selected bond via BFS discovery
    102221//    std::vector<atomId_t> atomids;
     
    116235
    117236    std::map<atomId_t, Vector> GatheredUpdates; //!< gathers all updates which are applied at the end
    118     Vector maxComponents(zeroVec);
    119237    for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
    120238        iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
    121239      // atom's force vector gives steepest descent direction
    122       const Vector oldPosition = (*iter)->getPositionAtStep(NextStep-2 >= 0 ? NextStep - 2 : 0);
     240      const Vector oldPosition = (*iter)->getPositionAtStep(CurrentTimeStep-2 >= 0 ? CurrentTimeStep - 2 : 0);
    123241      const Vector currentPosition = (*iter)->getPosition();
    124       const Vector oldGradient = (*iter)->getAtomicForceAtStep(NextStep-2 >= 0 ? NextStep - 2 : 0);
     242      const Vector oldGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep-2 >= 0 ? CurrentTimeStep - 2 : 0);
    125243      const Vector currentGradient = (*iter)->getAtomicForce();
    126244      LOG(4, "DEBUG: Force for atom " << **iter << " is " << currentGradient);
     
    225343      LOG(3, "DEBUG: Applying update " << update << " to atom " << *walker);
    226344    }
    227 
    228     LOG(1, "STATUS: Largest remaining force components at step #"
    229         << currentStep << " are " << maxComponents);
    230 
    231     // are we in final step? Remember to reset static entities
    232     if (currentStep == maxSteps) {
    233       LOG(2, "DEBUG: Final step, resetting values");
    234       reset();
    235     }
    236345  }
    237346
Note: See TracChangeset for help on using the changeset viewer.