Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Dynamics/ForceAnnealing.hpp

    r0682c2 r4b2adf  
    1717#include <functional>
    1818#include <iterator>
    19 #include <math.h>
    2019
    2120#include <boost/bind.hpp>
     
    168167  {
    169168    double stepwidth = 0.;
    170     if (_GradientDifference.Norm() > MYEPSILON)
     169    if (_GradientDifference.NormSquared() > MYEPSILON)
    171170      stepwidth = fabs(_PositionDifference.ScalarProduct(_GradientDifference))/
    172171          _GradientDifference.NormSquared();
     
    177176      stepwidth = currentDeltat;
    178177    }
    179     return std::min(1., stepwidth);
     178    return stepwidth;
    180179  }
    181180
     
    201200        iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
    202201      // atom's force vector gives steepest descent direction
    203       const Vector &currentPosition = (*iter)->getPositionAtStep(CurrentTimeStep);
    204       const Vector &currentGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep);
     202      const Vector currentPosition = (*iter)->getPositionAtStep(CurrentTimeStep);
     203      const Vector currentGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep);
    205204      LOG(4, "DEBUG: currentPosition for atom #" << (*iter)->getId() << " is " << currentPosition);
    206205      LOG(4, "DEBUG: currentGradient for atom #" << (*iter)->getId() << " is " << currentGradient);
     
    249248  }
    250249
    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 
    287250  /** Performs Gradient optimization on the atoms using BarzilaiBorwein step width.
    288251   *
    289252   * \note this can only be called when there are at least two optimization
    290    * time steps present, i.e. this must be preceded by a simple anneal().
     253   * time steps present, i.e. this must be preceeded by a simple anneal().
    291254   *
    292255   * We assume that forces have just been calculated.
     
    308271
    309272    Vector maxComponents;
     273    bool deltat_decreased = false;
    310274    for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
    311275        iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
    312 
    313       annealAtom_BarzilaiBorwein(*iter, OldTimeStep, CurrentTimeStep, _TimeStep);
     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);
     280      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);
    314293
    315294      // extract largest components for showing progress of annealing
    316       const Vector &currentGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep);
    317295      for(size_t i=0;i<NDIM;++i)
    318296        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);
    319317    }
    320318
    321319    return maxComponents;
    322320  }
    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         }
    355321
    356322  /** Performs Gradient optimization on the bonds with BarzilaiBorwein stepwdith.
     
    450416
    451417    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
    453418    for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
    454419        iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
     
    469434      const Vector PositionDifference = currentPosition - oldPosition;
    470435      const Vector GradientDifference = (currentGradient - oldGradient);
    471       double stepwidth = getBarzilaiBorweinStepwidth(PositionDifference, GradientDifference);
     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      }
    472446      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]);
    477447      LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate);
    478448
    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             }
     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;
    581544          }
    582545        }
    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             }
     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?");
    640596          }
    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);
     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) );
    664627          }
    665         } else {
    666           // simple atomic annealing, i.e. damping factor of 1
    667           updateInserter(GatheredUpdates, LargestUpdate_per_Atom, walker.getId(), PositionUpdate);
    668628        }
    669629      } else {
    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);
     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) );
    673636      }
    674637    }
     
    678641      atom &walker = *(*iter);
    679642      // extract largest components for showing progress of annealing
    680       const Vector &currentGradient = walker.getAtomicForceAtStep(CurrentTimeStep);
     643      const Vector currentGradient = walker.getAtomicForceAtStep(CurrentTimeStep);
    681644      for(size_t i=0;i<NDIM;++i)
    682645        maxComponents[i] = std::max(maxComponents[i], fabs(currentGradient[i]));
     
    707670      for (size_t i=0;i<NDIM;++i)
    708671        LargestUpdate[i] = std::max(LargestUpdate[i], fabs(update[i]));
    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       }
     672      walker->setPositionAtStep(_TimeStep,
     673          walker->getPositionAtStep(CurrentTimeStep) + update); // - CommonTranslation);
    722674    }
    723675    LOG(1, "STATUS: Largest absolute update components are " << LargestUpdate);
Note: See TracChangeset for help on using the changeset viewer.