Ignore:
Timestamp:
Aug 3, 2017, 10:44:57 AM (8 years ago)
Author:
Frederik Heber <frederik.heber@…>
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)
Message:

ForceAnnealing functions now have better readable time step variables.

  • _TimeStep is the parameter, Old.. and CurrentTimeStep designate the two reference time steps for calculating step width.
  • Split functions into simple step width and using BB step width.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Dynamics/ForceAnnealing.hpp

    r93fd2a6 rfcc860  
    9292   *
    9393   *
    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)
    9595   * \param offset offset in matrix file to the first force component
    9696   * \todo This is not yet checked if it is correctly working with DoConstrainedMD set >0.
    9797   */
    9898  void operator()(
    99       const int _CurrentTimeStep,
     99      const int _TimeStep,
    100100      const size_t _offset,
    101101      const bool _UseBondgraph)
    102102  {
     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
    103107    // make sum of forces equal zero
    104108    AtomicForceManipulator<T>::correctForceMatrixForFixedCenterOfMass(
    105109        _offset,
    106         _CurrentTimeStep-1>=0 ? _CurrentTimeStep - 1 : 0);
     110        CurrentTimeStep);
    107111
    108112    // are we in initial step? Then set static entities
     
    114118
    115119      // always use atomic annealing on first step
    116       maxComponents = anneal(_CurrentTimeStep);
     120      maxComponents = anneal(_TimeStep);
    117121    } else {
    118122      ++currentStep;
     
    121125      // bond graph annealing is always followed by a normal annealing
    122126      if (_UseBondgraph)
    123         maxComponents = annealWithBondGraph(_CurrentTimeStep);
     127        maxComponents = annealWithBondGraph_BarzilaiBorwein(_TimeStep);
    124128      // cannot store RemnantGradient in Atom's Force as it ruins BB stepwidth calculation
    125129      else
    126         maxComponents = anneal(_CurrentTimeStep);
     130        maxComponents = anneal_BarzilaiBorwein(_TimeStep);
    127131    }
    128132
     
    141145   * We assume that forces have just been calculated.
    142146   *
    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)
    144148   * \return to be filled with maximum force component over all atoms
    145149   */
    146150  Vector anneal(
    147       const int CurrentTimeStep)
     151      const int _TimeStep)
    148152  {
     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
    149159    Vector maxComponents;
    150160    bool deltat_decreased = false;
     
    152162                    iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
    153163                        // 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);
    162168//                      LOG(4, "DEBUG: Force for atom " << **iter << " is " << currentGradient);
    163169
    164170      // 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;
    177172      Vector PositionUpdate = stepwidth * currentGradient;
    178173                        LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate);
     
    186181                        // have different sign: Check whether this is the case and one step with
    187182                        // 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);
    189192                                if ((PositionUpdate.ScalarProduct(PositionDifference) < 0)
    190193                                    && (fabs(PositionUpdate.NormSquared()-PositionDifference.NormSquared()) < 1e-3)) {
     
    198201                                      << ", using deltat: " << currentDeltat);
    199202                                  PositionUpdate = currentDeltat * currentGradient;
     203                                }
    200204                        }
    201205
    202206                        // finally set new values
    203                         (*iter)->setPosition(currentPosition + PositionUpdate);
     207                        (*iter)->setPositionAtStep(_TimeStep, currentPosition + PositionUpdate);
    204208                }
     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    }
    205291
    206292    return maxComponents;
     
    244330  }
    245331
    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().
    247336   *
    248337   * We assume that forces have just been calculated. These forces are projected
     
    251340   *
    252341   *
    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)
    254343   * \param maxComponents to be filled with maximum force component over all atoms
    255344   */
    256   Vector annealWithBondGraph(
    257       const int CurrentTimeStep)
     345  Vector annealWithBondGraph_BarzilaiBorwein(
     346      const int _TimeStep)
    258347  {
     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
    259357    Vector maxComponents;
    260358
     
    297395        AtomicForceManipulator<T>::atoms.begin(),
    298396        AtomicForceManipulator<T>::atoms.end(),
    299         CurrentTimeStep);
     397        _TimeStep);
    300398    const BondVectors::container_t &sorted_bonds = bv.getSorted();
    301399
     
    316414    RemnantGradient_per_atom_t RemnantGradient_per_atom;
    317415    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 " << CurrentTimeStep
     416      const size_t ReferenceTimeStep = _TimeStep-timestep-1;
     417      LOG(2, "DEBUG: given time step is " << _TimeStep
    320418          << ", timestep is " << timestep
    321           << ", and CurrentStep is " << CurrentStep);
     419          << ", and ReferenceTimeStep is " << ReferenceTimeStep);
    322420
    323421      for(typename AtomSetMixin<T>::const_iterator iter = AtomicForceManipulator<T>::atoms.begin();
    324422          iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
    325423        const atom &walker = *(*iter);
    326         const Vector &walkerGradient = walker.getAtomicForceAtStep(CurrentStep);
     424        const Vector &walkerGradient = walker.getAtomicForceAtStep(ReferenceTimeStep);
    327425        LOG(3, "DEBUG: Gradient of atom #" << walker.getId() << ", namely "
    328426            << walker << " is " << walkerGradient);
     
    333431          // gather subset of BondVectors for the current atom
    334432          const std::vector<Vector> BondVectors =
    335               bv.getAtomsBondVectorsAtStep(walker, CurrentStep);
     433              bv.getAtomsBondVectorsAtStep(walker, ReferenceTimeStep);
    336434
    337435          // go through all its bonds and calculate what magnitude is represented
     
    340438              weights_per_atom[timestep].insert(
    341439                  std::make_pair(walker.getId(),
    342                   bv.getWeightsForAtomAtStep(walker, BondVectors, CurrentStep)) );
     440                  bv.getWeightsForAtomAtStep(walker, BondVectors, ReferenceTimeStep)) );
    343441          ASSERT( inserter.second,
    344442              "ForceAnnealing::operator() - weight map for atom "+toString(walker)
     
    428526        LOG(4, "DEBUG: current projected gradient for "
    429527            << (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 &currentPosition = bondatom[side]->getPositionAtStep(CurrentTimeStep-1>=0 ? CurrentTimeStep - 1 : 0);
     528        const Vector &oldPosition = bondatom[side]->getPositionAtStep(OldTimeStep);
     529        const Vector &currentPosition = bondatom[side]->getPositionAtStep(CurrentTimeStep);
    432530        const Vector PositionDifference = currentPosition - oldPosition;
    433531        LOG(4, "DEBUG: old position is " << oldPosition);
     
    478576      atom &walker = *(*iter);
    479577      // 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);
    481579      for(size_t i=0;i<NDIM;++i)
    482580        if (currentGradient[i] > maxComponents[i])
     
    505603      LOG(3, "DEBUG: Applying update " << update << " to atom #" << atomid
    506604          << ", 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);
    510607//      walker->setAtomicForce( RemnantGradient_per_atom[walker->getId()] );
    511608    }
Note: See TracChangeset for help on using the changeset viewer.