Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Dynamics/ForceAnnealing.hpp

    r4b2adf r0682c2  
    1717#include <functional>
    1818#include <iterator>
     19#include <math.h>
    1920
    2021#include <boost/bind.hpp>
     
    167168  {
    168169    double stepwidth = 0.;
    169     if (_GradientDifference.NormSquared() > MYEPSILON)
     170    if (_GradientDifference.Norm() > MYEPSILON)
    170171      stepwidth = fabs(_PositionDifference.ScalarProduct(_GradientDifference))/
    171172          _GradientDifference.NormSquared();
     
    176177      stepwidth = currentDeltat;
    177178    }
    178     return stepwidth;
     179    return std::min(1., stepwidth);
    179180  }
    180181
     
    200201        iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
    201202      // 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 &currentPosition = (*iter)->getPositionAtStep(CurrentTimeStep);
     204      const Vector &currentGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep);
    204205      LOG(4, "DEBUG: currentPosition for atom #" << (*iter)->getId() << " is " << currentPosition);
    205206      LOG(4, "DEBUG: currentGradient for atom #" << (*iter)->getId() << " is " << currentGradient);
     
    248249  }
    249250
     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 &currentPosition = _atom->getPositionAtStep(CurrentTimeStep);
     268    const Vector &oldGradient = _atom->getAtomicForceAtStep(OldTimeStep);
     269    const Vector &currentGradient = _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
    250287  /** Performs Gradient optimization on the atoms using BarzilaiBorwein step width.
    251288   *
    252289   * \note this can only be called when there are at least two optimization
    253    * time steps present, i.e. this must be preceeded by a simple anneal().
     290   * time steps present, i.e. this must be preceded by a simple anneal().
    254291   *
    255292   * We assume that forces have just been calculated.
     
    271308
    272309    Vector maxComponents;
    273     bool deltat_decreased = false;
    274310    for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
    275311        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 &currentPosition = (*iter)->getPositionAtStep(CurrentTimeStep);
    279       const Vector &oldGradient = (*iter)->getAtomicForceAtStep(OldTimeStep);
     312
     313      annealAtom_BarzilaiBorwein(*iter, OldTimeStep, CurrentTimeStep, _TimeStep);
     314
     315      // extract largest components for showing progress of annealing
    280316      const Vector &currentGradient = (*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 descent
    288       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 annealing
    295317      for(size_t i=0;i<NDIM;++i)
    296318        maxComponents[i] = std::max(maxComponents[i], fabs(currentGradient[i]));
    297 
    298 //      // steps may go back and forth again (updates are of same magnitude but
    299 //      // have different sign: Check whether this is the case and one step with
    300 //      // deltat to interrupt this sequence
    301 //      if (!PositionDifference.IsZero())
    302 //        if ((PositionUpdate.ScalarProduct(PositionDifference) < 0)
    303 //            && (fabs(PositionUpdate.NormSquared()-PositionDifference.NormSquared()) < 1e-3)) {
    304 //          // for convergence we want a null sequence here, too
    305 //          if (!deltat_decreased) {
    306 //            deltat_decreased = true;
    307 //            currentDeltat = .5*currentDeltat;
    308 //          }
    309 //          LOG(2, "DEBUG: Upgrade in other direction: " << PositionUpdate
    310 //              << " > " << PositionDifference
    311 //              << ", using deltat: " << currentDeltat);
    312 //          PositionUpdate = currentDeltat * currentGradient;
    313 //      }
    314 
    315       // finally set new values
    316       (*iter)->setPositionAtStep(_TimeStep, currentPosition + PositionUpdate);
    317319    }
    318320
    319321    return maxComponents;
    320322  }
     323
     324        /** Helper function to insert \a PositionUpdate into a map for every atom.
     325         *
     326         * \param _GatheredUpdates map of updates per atom
     327         * \param _LargestUpdate_per_Atom map with the largest update per atom for checking
     328         * \param _atomno key for map
     329         * \param _PositionUpdate update to add
     330         * \param _factor optional dampening factor
     331         */
     332        void updateInserter(
     333            std::map<atomId_t, Vector> &_GatheredUpdates,
     334            std::map<atomId_t, double> &_LargestUpdate_per_Atom,
     335            const atomId_t _atomno,
     336            const Vector &_PositionUpdate,
     337            const double _factor = 1.
     338            )
     339        {
     340          if (_GatheredUpdates.count(_atomno)) {
     341            _GatheredUpdates[_atomno] += _factor*_PositionUpdate;
     342            _LargestUpdate_per_Atom[_atomno] =
     343                std::max(_LargestUpdate_per_Atom[_atomno], _factor*_PositionUpdate.Norm());
     344          } else {
     345            _GatheredUpdates.insert(
     346                std::make_pair(
     347                    _atomno,
     348                    _factor*_PositionUpdate) );
     349            _LargestUpdate_per_Atom.insert(
     350                std::make_pair(
     351                    _atomno,
     352                    _PositionUpdate.Norm()) );
     353          }
     354        }
    321355
    322356  /** Performs Gradient optimization on the bonds with BarzilaiBorwein stepwdith.
     
    416450
    417451    std::map<atomId_t, Vector> GatheredUpdates; //!< gathers all updates which are applied at the end
     452    std::map<atomId_t, double> LargestUpdate_per_Atom; //!< check whether updates cancelled each other
    418453    for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
    419454        iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
     
    434469      const Vector PositionDifference = currentPosition - oldPosition;
    435470      const Vector GradientDifference = (currentGradient - oldGradient);
    436       double stepwidth = 0.;
    437       if (GradientDifference.Norm() > MYEPSILON)
    438         stepwidth = fabs(PositionDifference.ScalarProduct(GradientDifference))/
    439             GradientDifference.NormSquared();
    440       if (fabs(stepwidth) < 1e-10) {
    441         // dont' warn in first step, deltat usage normal
    442         if (currentStep != 1)
    443           ELOG(1, "INFO: Barzilai-Borwein stepwidth is zero, using deltat " << currentDeltat << " instead.");
    444         stepwidth = currentDeltat;
    445       }
     471      double stepwidth = getBarzilaiBorweinStepwidth(PositionDifference, GradientDifference);
    446472      Vector PositionUpdate = stepwidth * currentGradient;
     473      // cap updates (if non-zero) at 0.2 angstroem. BB tends to overshoot.
     474      for (size_t i=0;i<NDIM;++i)
     475        if (fabs(PositionUpdate[i]) > MYEPSILON)
     476          PositionUpdate[i] = std::min(0.2, fabs(PositionUpdate[i]))*PositionUpdate[i]/fabs(PositionUpdate[i]);
    447477      LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate);
    448478
    449       /** for each atom, we imagine a plane at the position of the atom with
    450        * its atomic gradient as the normal vector. We go through all its bonds
    451        * and check on which side of the plane the bond is. This defines whether
    452        * the bond is contracting (+) or expanding (-) with respect to this atom.
    453        *
    454        * A bond has two atoms, however. Hence, we do this for either atom and
    455        * look at the combination: Is it in sum contracting or expanding given
    456        * both projected_forces?
    457        */
    458 
    459       /** go through all bonds and check projected_forces and side of plane
    460        * the idea is that if all bonds on one side are contracting ones or expanding,
    461        * respectively, then we may shift not only the atom with respect to its
    462        * gradient but also its neighbors (towards contraction or towards
    463        * expansion depending on direction of gradient).
    464        * if they are mixed on both sides of the plane, then we simply shift
    465        * only the atom itself.
    466        * if they are not mixed on either side, then we also only shift the
    467        * atom, namely away from expanding and towards contracting bonds.
    468        *
    469        * We may get this information right away by looking at the projected_forces.
    470        * They give the atomic gradient of either atom projected onto the BondVector
    471        * with an additional weight in [0,1].
    472        */
    473 
    474       // sign encodes side of plane and also encodes contracting(-) or expanding(+)
    475       typedef std::vector<int> sides_t;
    476       typedef std::vector<int> types_t;
    477       sides_t sides;
    478       types_t types;
    479       const BondList& ListOfBonds = walker.getListOfBonds();
    480       for(BondList::const_iterator bonditer = ListOfBonds.begin();
    481           bonditer != ListOfBonds.end(); ++bonditer) {
    482         const bond::ptr &current_bond = *bonditer;
    483 
    484         // BondVector goes from bond::rightatom to bond::leftatom
    485         const size_t index = bv.getIndexForBond(current_bond);
    486         std::vector<double> &forcelist = (&walker == current_bond->leftatom) ?
    487             projected_forces[BondVectors::leftside] : projected_forces[BondVectors::rightside];
    488         // note that projected_forces has sign such as to indicate whether
    489         // atomic gradient wants bond to contract (-) or expand (+).
    490         // This goes into sides: Minus side points away from gradient, plus side point
    491         // towards gradient.
    492         //
    493         // the sum of both bond sides goes into types, depending on which is
    494         // stronger if either wants a different thing
    495         const double &temp = forcelist[index];
    496         sides.push_back( -1.*temp/fabs(temp) ); // BondVectors has exactly opposite sign for sides decision
    497         const double sum =
    498             projected_forces[BondVectors::leftside][index]+projected_forces[BondVectors::rightside][index];
    499         types.push_back( sum/fabs(sum) );
    500         LOG(4, "DEBUG: Bond " << *current_bond << " is on side " << sides.back()
    501             << " and has type " << types.back());
    502       }
    503 //      /// check whether both conditions are compatible:
    504 //      // i.e. either we have ++/-- for all entries in sides and types
    505 //      // or we have +-/-+ for all entries
    506 //      // hence, multiplying and taking the sum and its absolute value
    507 //      // should be equal to the maximum number of entries
    508 //      sides_t results;
    509 //      std::transform(
    510 //          sides.begin(), sides.end(),
    511 //          types.begin(),
    512 //          std::back_inserter(results),
    513 //          std::multiplies<int>);
    514 //      int result = abs(std::accumulate(results.begin(), results.end(), 0, std::plus<int>));
    515 
    516       std::vector<size_t> first_per_side(2, (size_t)-1); //!< mark down one representative from either side
    517       std::vector< std::vector<int> > types_per_side(2); //!< gather all types on each side
    518       types_t::const_iterator typesiter = types.begin();
    519       for (sides_t::const_iterator sidesiter = sides.begin();
    520           sidesiter != sides.end(); ++sidesiter, ++typesiter) {
    521         const size_t index = (*sidesiter+1)/2;
    522         types_per_side[index].push_back(*typesiter);
    523         if (first_per_side[index] == (size_t)-1)
    524           first_per_side[index] = std::distance(const_cast<const sides_t &>(sides).begin(), sidesiter);
    525       }
    526       LOG(4, "DEBUG: First on side minus is " << first_per_side[0] << ", and first on side plus is "
    527           << first_per_side[1]);
    528       //!> enumerate types per side with a little witching with the numbers to allow easy setting from types
    529       enum whichtypes_t {
    530         contracting=0,
    531         unset=1,
    532         expanding=2,
    533         mixed
    534       };
    535       std::vector<int> typeside(2, unset);
    536       for(size_t i=0;i<2;++i) {
    537         for (std::vector<int>::const_iterator tpsiter = types_per_side[i].begin();
    538             tpsiter != types_per_side[i].end(); ++tpsiter) {
    539           if (typeside[i] == unset) {
    540             typeside[i] = *tpsiter+1; //contracting(0) or expanding(2)
    541           } else {
    542             if (typeside[i] != (*tpsiter+1)) // no longer he same type
    543               typeside[i] = mixed;
     479      if (walker.getElementNo() != 1) {
     480        /** for each atom, we imagine a plane at the position of the atom with
     481         * its atomic gradient as the normal vector. We go through all its bonds
     482         * and check on which side of the plane the bond is. This defines whether
     483         * the bond is contracting (+) or expanding (-) with respect to this atom.
     484         *
     485         * A bond has two atoms, however. Hence, we do this for either atom and
     486         * look at the combination: Is it in sum contracting or expanding given
     487         * both projected_forces?
     488         */
     489
     490        /** go through all bonds and check projected_forces and side of plane
     491         * the idea is that if all bonds on one side are contracting ones or expanding,
     492         * respectively, then we may shift not only the atom with respect to its
     493         * gradient but also its neighbors (towards contraction or towards
     494         * expansion depending on direction of gradient).
     495         * if they are mixed on both sides of the plane, then we simply shift
     496         * only the atom itself.
     497         * if they are not mixed on either side, then we also only shift the
     498         * atom, namely away from expanding and towards contracting bonds.
     499         *
     500         * We may get this information right away by looking at the projected_forces.
     501         * They give the atomic gradient of either atom projected onto the BondVector
     502         * with an additional weight in [0,1].
     503         */
     504
     505        // sign encodes side of plane and also encodes contracting(-) or expanding(+)
     506        typedef std::vector<int> sides_t;
     507        typedef std::vector<int> types_t;
     508        sides_t sides;
     509        types_t types;
     510        const BondList& ListOfBonds = walker.getListOfBonds();
     511        for(BondList::const_iterator bonditer = ListOfBonds.begin();
     512            bonditer != ListOfBonds.end(); ++bonditer) {
     513          const bond::ptr &current_bond = *bonditer;
     514
     515          // BondVector goes from bond::rightatom to bond::leftatom
     516          const size_t index = bv.getIndexForBond(current_bond);
     517          std::vector<double> &forcelist = (&walker == current_bond->leftatom) ?
     518              projected_forces[BondVectors::leftside] : projected_forces[BondVectors::rightside];
     519          // note that projected_forces has sign such as to indicate whether
     520          // atomic gradient wants bond to contract (-) or expand (+).
     521          // This goes into sides: Minus side points away from gradient, plus side point
     522          // towards gradient.
     523          //
     524          // the sum of both bond sides goes into types, depending on which is
     525          // stronger if either wants a different thing
     526          const double &temp = forcelist[index];
     527          if (fabs(temp) < MYEPSILON)
     528            sides.push_back(1);
     529          else
     530            sides.push_back( -1.*temp/fabs(temp) ); // BondVectors has exactly opposite sign for sides decision
     531          ASSERT( (sides.back() == 1) || (sides.back() == -1),
     532              "ForceAnnealing() - sides is not in {-1,1}.");
     533          const double sum =
     534              projected_forces[BondVectors::leftside][index]+projected_forces[BondVectors::rightside][index];
     535          types.push_back( sum/fabs(sum) );
     536          LOG(4, "DEBUG: Bond " << *current_bond << " is on side " << sides.back()
     537              << " and has type " << types.back());
     538        }
     539  //      /// check whether both conditions are compatible:
     540  //      // i.e. either we have ++/-- for all entries in sides and types
     541  //      // or we have +-/-+ for all entries
     542  //      // hence, multiplying and taking the sum and its absolute value
     543  //      // should be equal to the maximum number of entries
     544  //      sides_t results;
     545  //      std::transform(
     546  //          sides.begin(), sides.end(),
     547  //          types.begin(),
     548  //          std::back_inserter(results),
     549  //          std::multiplies<int>);
     550  //      int result = abs(std::accumulate(results.begin(), results.end(), 0, std::plus<int>));
     551
     552        std::vector<size_t> first_per_side(2, (size_t)-1); //!< mark down one representative from either side
     553        std::vector< std::vector<int> > types_per_side(2); //!< gather all types on each side
     554        types_t::const_iterator typesiter = types.begin();
     555        for (sides_t::const_iterator sidesiter = sides.begin();
     556            sidesiter != sides.end(); ++sidesiter, ++typesiter) {
     557          const size_t index = (*sidesiter+1)/2;
     558          types_per_side[index].push_back(*typesiter);
     559          if (first_per_side[index] == (size_t)-1)
     560            first_per_side[index] = std::distance(const_cast<const sides_t &>(sides).begin(), sidesiter);
     561        }
     562        LOG(4, "DEBUG: First on side minus is " << first_per_side[0] << ", and first on side plus is "
     563            << first_per_side[1]);
     564        //!> enumerate types per side with a little witching with the numbers to allow easy setting from types
     565        enum whichtypes_t {
     566          contracting=0,
     567          unset=1,
     568          expanding=2,
     569          mixed
     570        };
     571        std::vector<int> typeside(2, unset);
     572        for(size_t i=0;i<2;++i) {
     573          for (std::vector<int>::const_iterator tpsiter = types_per_side[i].begin();
     574              tpsiter != types_per_side[i].end(); ++tpsiter) {
     575            if (typeside[i] == unset) {
     576              typeside[i] = *tpsiter+1; //contracting(0) or expanding(2)
     577            } else {
     578              if (typeside[i] != (*tpsiter+1)) // no longer he same type
     579                typeside[i] = mixed;
     580            }
    544581          }
    545582        }
    546       }
    547       LOG(4, "DEBUG: Minus side is " << typeside[0] << " and plus side is " << typeside[1]);
    548 
    549       typedef std::vector< std::pair<atomId_t, atomId_t> > RemovedEdges_t;
    550       if ((typeside[0] != mixed) || (typeside[1] != mixed)) {
    551         const size_t sideno = ((typeside[0] != mixed) && (typeside[0] != unset)) ? 0 : 1;
    552         LOG(4, "DEBUG: Chosen side is " << sideno << " with type " << typeside[sideno]);
    553         ASSERT( (typeside[sideno] == contracting) || (typeside[sideno] == expanding),
    554             "annealWithBondGraph_BB() - chosen side is neither expanding nor contracting.");
    555         // one side is not mixed, all bonds on one side are of same type
    556         // hence, find out which bonds to exclude
    557         const BondList& ListOfBonds = walker.getListOfBonds();
    558 
    559         // sideno is away (0) or in direction (1) of gradient
    560         // tpyes[first_per_side[sideno]] is either contracting (-1) or expanding (+1)
    561         // : side (i), where (i) means which bonds we keep for the BFS, bonds
    562         // on side (-i) are removed
    563         // If all bonds on side away (0) want expansion (+1), move towards side with atom: side 1
    564         // if all bonds side towards (1) want contraction (-1), move away side with atom : side -1
    565 
    566         // unsure whether this or do nothing in the remaining cases:
    567         // If all bonds on side toward (1) want expansion (+1), move away side with atom : side -1
    568         //    (the reasoning is that the bond's other atom must have a stronger
    569         //     gradient in the same direction and they push along atoms in
    570         //     gradient direction: we don't want to interface with those.
    571         //     Hence, move atoms along on away side
    572         // if all bonds side away (0) want contraction (-1), move towards side with atom: side 1
    573         //    (the reasoning is the same, don't interfere with update from
    574         //     stronger gradient)
    575         // hence, the decision is only based on sides once we have picked a side
    576         // depending on all bonds associated with have same good type.
    577         const double sign = sides[first_per_side[sideno]];
    578         LOG(4, "DEBUG: Removing edges from side with sign " << sign);
    579         BondList::const_iterator bonditer = ListOfBonds.begin();
    580         RemovedEdges_t RemovedEdges;
    581         for (sides_t::const_iterator sidesiter = sides.begin();
    582             sidesiter != sides.end(); ++sidesiter, ++bonditer) {
    583           if (*sidesiter == sign) {
    584             // remove the edge
    585             const bond::ptr &current_bond = *bonditer;
    586             LOG(5, "DEBUG: Removing edge " << *current_bond);
    587             RemovedEdges.push_back( std::make_pair(
    588                 current_bond->leftatom->getId(),
    589                 current_bond->rightatom->getId())
    590             );
    591 #ifndef NDEBUG
    592             const bool status =
    593 #endif
    594                 BGcreator.removeEdge(RemovedEdges.back());
    595             ASSERT( status, "ForceAnnealing() - edge to found bond is not present?");
     583        LOG(4, "DEBUG: Minus side is " << typeside[0] << " and plus side is " << typeside[1]);
     584
     585        typedef std::vector< std::pair<atomId_t, atomId_t> > RemovedEdges_t;
     586        if ((typeside[0] != mixed) || (typeside[1] != mixed)) {
     587          const size_t sideno = ((typeside[0] != mixed) && (typeside[0] != unset)) ? 0 : 1;
     588          LOG(4, "DEBUG: Chosen side is " << sideno << " with type " << typeside[sideno]);
     589          ASSERT( (typeside[sideno] == contracting) || (typeside[sideno] == expanding),
     590              "annealWithBondGraph_BB() - chosen side is neither expanding nor contracting.");
     591          // one side is not mixed, all bonds on one side are of same type
     592          // hence, find out which bonds to exclude
     593          const BondList& ListOfBonds = walker.getListOfBonds();
     594
     595          // sideno is away (0) or in direction (1) of gradient
     596          // tpyes[first_per_side[sideno]] is either contracting (-1) or expanding (+1)
     597          // : side (i), where (i) means which bonds we keep for the BFS, bonds
     598          // on side (-i) are removed
     599          // If all bonds on side away (0) want expansion (+1), move towards side with atom: side 1
     600          // if all bonds side towards (1) want contraction (-1), move away side with atom : side -1
     601
     602          // unsure whether this or do nothing in the remaining cases:
     603          // If all bonds on side toward (1) want expansion (+1), move away side with atom : side -1
     604          //    (the reasoning is that the bond's other atom must have a stronger
     605          //     gradient in the same direction and they push along atoms in
     606          //     gradient direction: we don't want to interface with those.
     607          //     Hence, move atoms along on away side
     608          // if all bonds side away (0) want contraction (-1), move towards side with atom: side 1
     609          //    (the reasoning is the same, don't interfere with update from
     610          //     stronger gradient)
     611          // hence, the decision is only based on sides once we have picked a side
     612          // depending on all bonds associated with have same good type.
     613
     614          // away from gradient (minus) and contracting
     615          // or towards gradient (plus) and expanding
     616          // gather all on same side and remove
     617          const double sign =
     618              (sides[first_per_side[sideno]] == types[first_per_side[sideno]])
     619              ? sides[first_per_side[sideno]] : -1.*sides[first_per_side[sideno]];
     620
     621          LOG(4, "DEBUG: Removing edges from side with sign " << sign);
     622          BondList::const_iterator bonditer = ListOfBonds.begin();
     623          RemovedEdges_t RemovedEdges;
     624          for (sides_t::const_iterator sidesiter = sides.begin();
     625              sidesiter != sides.end(); ++sidesiter, ++bonditer) {
     626            if (*sidesiter == sign) {
     627              // remove the edge
     628              const bond::ptr &current_bond = *bonditer;
     629              LOG(5, "DEBUG: Removing edge " << *current_bond);
     630              RemovedEdges.push_back( std::make_pair(
     631                  current_bond->leftatom->getId(),
     632                  current_bond->rightatom->getId())
     633              );
     634  #ifndef NDEBUG
     635              const bool status =
     636  #endif
     637                  BGcreator.removeEdge(RemovedEdges.back());
     638              ASSERT( status, "ForceAnnealing() - edge to found bond is not present?");
     639            }
    596640          }
    597         }
    598         // perform limited-horizon BFS
    599         BoostGraphHelpers::Nodeset_t bondside_set;
    600         BreadthFirstSearchGatherer::distance_map_t distance_map;
    601         bondside_set = NodeGatherer(walker.getId(), max_distance);
    602         distance_map = NodeGatherer.getDistances();
    603         std::sort(bondside_set.begin(), bondside_set.end());
    604 
    605         // re-add edge
    606         for (RemovedEdges_t::const_iterator edgeiter = RemovedEdges.begin();
    607             edgeiter != RemovedEdges.end(); ++edgeiter)
    608           BGcreator.addEdge(edgeiter->first, edgeiter->second);
    609 
    610         // update position with dampening factor on the discovered bonds
    611         for (BoostGraphHelpers::Nodeset_t::const_iterator setiter = bondside_set.begin();
    612             setiter != bondside_set.end(); ++setiter) {
    613           const BreadthFirstSearchGatherer::distance_map_t::const_iterator diter
    614             = distance_map.find(*setiter);
    615           ASSERT( diter != distance_map.end(),
    616               "ForceAnnealing() - could not find distance to an atom.");
    617           const double factor = pow(damping_factor, diter->second+1);
    618           LOG(3, "DEBUG: Update for atom #" << *setiter << " will be "
    619               << factor << "*" << PositionUpdate);
    620           if (GatheredUpdates.count((*setiter))) {
    621             GatheredUpdates[(*setiter)] += factor*PositionUpdate;
    622           } else {
    623             GatheredUpdates.insert(
    624                 std::make_pair(
    625                     (*setiter),
    626                     factor*PositionUpdate) );
     641          // perform limited-horizon BFS
     642          BoostGraphHelpers::Nodeset_t bondside_set;
     643          BreadthFirstSearchGatherer::distance_map_t distance_map;
     644          bondside_set = NodeGatherer(walker.getId(), max_distance);
     645          distance_map = NodeGatherer.getDistances();
     646          std::sort(bondside_set.begin(), bondside_set.end());
     647
     648          // re-add edge
     649          for (RemovedEdges_t::const_iterator edgeiter = RemovedEdges.begin();
     650              edgeiter != RemovedEdges.end(); ++edgeiter)
     651            BGcreator.addEdge(edgeiter->first, edgeiter->second);
     652
     653          // update position with dampening factor on the discovered bonds
     654          for (BoostGraphHelpers::Nodeset_t::const_iterator setiter = bondside_set.begin();
     655              setiter != bondside_set.end(); ++setiter) {
     656            const BreadthFirstSearchGatherer::distance_map_t::const_iterator diter
     657              = distance_map.find(*setiter);
     658            ASSERT( diter != distance_map.end(),
     659                "ForceAnnealing() - could not find distance to an atom.");
     660            const double factor = pow(damping_factor, diter->second+1);
     661            LOG(3, "DEBUG: Update for atom #" << *setiter << " will be "
     662                << factor << "*" << PositionUpdate);
     663            updateInserter(GatheredUpdates, LargestUpdate_per_Atom, *setiter, PositionUpdate, factor);
    627664          }
     665        } else {
     666          // simple atomic annealing, i.e. damping factor of 1
     667          updateInserter(GatheredUpdates, LargestUpdate_per_Atom, walker.getId(), PositionUpdate);
    628668        }
    629669      } else {
    630         // simple atomic annealing, i.e. damping factor of 1
    631         LOG(3, "DEBUG: Update for atom #" << walker.getId() << " will be " << PositionUpdate);
    632         GatheredUpdates.insert(
    633             std::make_pair(
    634                 walker.getId(),
    635                 PositionUpdate) );
     670        // hydrogens (are light-weighted and therefore) are always updated normally
     671        LOG(3, "DEBUG: Update for hydrogen #" << walker.getId() << " will be " << PositionUpdate);
     672        updateInserter(GatheredUpdates, LargestUpdate_per_Atom, walker.getId(), PositionUpdate);
    636673      }
    637674    }
     
    641678      atom &walker = *(*iter);
    642679      // extract largest components for showing progress of annealing
    643       const Vector currentGradient = walker.getAtomicForceAtStep(CurrentTimeStep);
     680      const Vector &currentGradient = walker.getAtomicForceAtStep(CurrentTimeStep);
    644681      for(size_t i=0;i<NDIM;++i)
    645682        maxComponents[i] = std::max(maxComponents[i], fabs(currentGradient[i]));
     
    670707      for (size_t i=0;i<NDIM;++i)
    671708        LargestUpdate[i] = std::max(LargestUpdate[i], fabs(update[i]));
    672       walker->setPositionAtStep(_TimeStep,
    673           walker->getPositionAtStep(CurrentTimeStep) + update); // - CommonTranslation);
     709
     710      std::map<atomId_t, double>::const_iterator largestiter = LargestUpdate_per_Atom.find(atomid);
     711      ASSERT( largestiter != LargestUpdate_per_Atom.end(),
     712          "ForceAnnealing() - walker with id "+toString(atomid)+" not in LargestUpdates.");
     713      // if we had large updates but their sum is very small
     714      if (update.Norm()/largestiter->second > MYEPSILON) {
     715        walker->setPositionAtStep(_TimeStep,
     716            walker->getPositionAtStep(CurrentTimeStep) + update); // - CommonTranslation);
     717      } else {
     718        // then recalc update with simple anneal
     719        LOG(2, "WARNING: Updates on atom " << *iter << " cancel themselves, performing simple anneal step.");
     720        annealAtom_BarzilaiBorwein(walker, OldTimeStep, CurrentTimeStep, _TimeStep);
     721      }
    674722    }
    675723    LOG(1, "STATUS: Largest absolute update components are " << LargestUpdate);
Note: See TracChangeset for help on using the changeset viewer.