Changeset 0682c2


Ignore:
Timestamp:
Jun 20, 2018, 8:21:41 AM (7 years ago)
Author:
Frederik Heber <frederik.heber@…>
Branches:
Candidate_v1.6.1, ChemicalSpaceEvaluator, Exclude_Hydrogens_annealWithBondGraph
Children:
3183f5
Parents:
bd19c1
git-author:
Frederik Heber <frederik.heber@…> (06/16/18 00:03:03)
git-committer:
Frederik Heber <frederik.heber@…> (06/20/18 08:21:41)
Message:

Excluded hydrogens due to their small mass from spreading updates.

  • hydrogens will rather adapt to position changes of other atoms than the other way round.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Dynamics/ForceAnnealing.hpp

    rbd19c1 r0682c2  
    322322  }
    323323
     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        }
     355
    324356  /** Performs Gradient optimization on the bonds with BarzilaiBorwein stepwdith.
    325357   *
     
    445477      LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate);
    446478
    447       /** for each atom, we imagine a plane at the position of the atom with
    448        * its atomic gradient as the normal vector. We go through all its bonds
    449        * and check on which side of the plane the bond is. This defines whether
    450        * the bond is contracting (+) or expanding (-) with respect to this atom.
    451        *
    452        * A bond has two atoms, however. Hence, we do this for either atom and
    453        * look at the combination: Is it in sum contracting or expanding given
    454        * both projected_forces?
    455        */
    456 
    457       /** go through all bonds and check projected_forces and side of plane
    458        * the idea is that if all bonds on one side are contracting ones or expanding,
    459        * respectively, then we may shift not only the atom with respect to its
    460        * gradient but also its neighbors (towards contraction or towards
    461        * expansion depending on direction of gradient).
    462        * if they are mixed on both sides of the plane, then we simply shift
    463        * only the atom itself.
    464        * if they are not mixed on either side, then we also only shift the
    465        * atom, namely away from expanding and towards contracting bonds.
    466        *
    467        * We may get this information right away by looking at the projected_forces.
    468        * They give the atomic gradient of either atom projected onto the BondVector
    469        * with an additional weight in [0,1].
    470        */
    471 
    472       // sign encodes side of plane and also encodes contracting(-) or expanding(+)
    473       typedef std::vector<int> sides_t;
    474       typedef std::vector<int> types_t;
    475       sides_t sides;
    476       types_t types;
    477       const BondList& ListOfBonds = walker.getListOfBonds();
    478       for(BondList::const_iterator bonditer = ListOfBonds.begin();
    479           bonditer != ListOfBonds.end(); ++bonditer) {
    480         const bond::ptr &current_bond = *bonditer;
    481 
    482         // BondVector goes from bond::rightatom to bond::leftatom
    483         const size_t index = bv.getIndexForBond(current_bond);
    484         std::vector<double> &forcelist = (&walker == current_bond->leftatom) ?
    485             projected_forces[BondVectors::leftside] : projected_forces[BondVectors::rightside];
    486         // note that projected_forces has sign such as to indicate whether
    487         // atomic gradient wants bond to contract (-) or expand (+).
    488         // This goes into sides: Minus side points away from gradient, plus side point
    489         // towards gradient.
    490         //
    491         // the sum of both bond sides goes into types, depending on which is
    492         // stronger if either wants a different thing
    493         const double &temp = forcelist[index];
    494         if (fabs(temp) < MYEPSILON)
    495           sides.push_back(1);
    496         else
    497           sides.push_back( -1.*temp/fabs(temp) ); // BondVectors has exactly opposite sign for sides decision
    498         ASSERT( (sides.back() == 1) || (sides.back() == -1),
    499             "ForceAnnealing() - sides is not in {-1,1}.");
    500         const double sum =
    501             projected_forces[BondVectors::leftside][index]+projected_forces[BondVectors::rightside][index];
    502         types.push_back( sum/fabs(sum) );
    503         LOG(4, "DEBUG: Bond " << *current_bond << " is on side " << sides.back()
    504             << " and has type " << types.back());
    505       }
    506 //      /// check whether both conditions are compatible:
    507 //      // i.e. either we have ++/-- for all entries in sides and types
    508 //      // or we have +-/-+ for all entries
    509 //      // hence, multiplying and taking the sum and its absolute value
    510 //      // should be equal to the maximum number of entries
    511 //      sides_t results;
    512 //      std::transform(
    513 //          sides.begin(), sides.end(),
    514 //          types.begin(),
    515 //          std::back_inserter(results),
    516 //          std::multiplies<int>);
    517 //      int result = abs(std::accumulate(results.begin(), results.end(), 0, std::plus<int>));
    518 
    519       std::vector<size_t> first_per_side(2, (size_t)-1); //!< mark down one representative from either side
    520       std::vector< std::vector<int> > types_per_side(2); //!< gather all types on each side
    521       types_t::const_iterator typesiter = types.begin();
    522       for (sides_t::const_iterator sidesiter = sides.begin();
    523           sidesiter != sides.end(); ++sidesiter, ++typesiter) {
    524         const size_t index = (*sidesiter+1)/2;
    525         types_per_side[index].push_back(*typesiter);
    526         if (first_per_side[index] == (size_t)-1)
    527           first_per_side[index] = std::distance(const_cast<const sides_t &>(sides).begin(), sidesiter);
    528       }
    529       LOG(4, "DEBUG: First on side minus is " << first_per_side[0] << ", and first on side plus is "
    530           << first_per_side[1]);
    531       //!> enumerate types per side with a little witching with the numbers to allow easy setting from types
    532       enum whichtypes_t {
    533         contracting=0,
    534         unset=1,
    535         expanding=2,
    536         mixed
    537       };
    538       std::vector<int> typeside(2, unset);
    539       for(size_t i=0;i<2;++i) {
    540         for (std::vector<int>::const_iterator tpsiter = types_per_side[i].begin();
    541             tpsiter != types_per_side[i].end(); ++tpsiter) {
    542           if (typeside[i] == unset) {
    543             typeside[i] = *tpsiter+1; //contracting(0) or expanding(2)
    544           } else {
    545             if (typeside[i] != (*tpsiter+1)) // no longer he same type
    546               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            }
    547581          }
    548582        }
    549       }
    550       LOG(4, "DEBUG: Minus side is " << typeside[0] << " and plus side is " << typeside[1]);
    551 
    552       typedef std::vector< std::pair<atomId_t, atomId_t> > RemovedEdges_t;
    553       if ((typeside[0] != mixed) || (typeside[1] != mixed)) {
    554         const size_t sideno = ((typeside[0] != mixed) && (typeside[0] != unset)) ? 0 : 1;
    555         LOG(4, "DEBUG: Chosen side is " << sideno << " with type " << typeside[sideno]);
    556         ASSERT( (typeside[sideno] == contracting) || (typeside[sideno] == expanding),
    557             "annealWithBondGraph_BB() - chosen side is neither expanding nor contracting.");
    558         // one side is not mixed, all bonds on one side are of same type
    559         // hence, find out which bonds to exclude
    560         const BondList& ListOfBonds = walker.getListOfBonds();
    561 
    562         // sideno is away (0) or in direction (1) of gradient
    563         // tpyes[first_per_side[sideno]] is either contracting (-1) or expanding (+1)
    564         // : side (i), where (i) means which bonds we keep for the BFS, bonds
    565         // on side (-i) are removed
    566         // If all bonds on side away (0) want expansion (+1), move towards side with atom: side 1
    567         // if all bonds side towards (1) want contraction (-1), move away side with atom : side -1
    568 
    569         // unsure whether this or do nothing in the remaining cases:
    570         // If all bonds on side toward (1) want expansion (+1), move away side with atom : side -1
    571         //    (the reasoning is that the bond's other atom must have a stronger
    572         //     gradient in the same direction and they push along atoms in
    573         //     gradient direction: we don't want to interface with those.
    574         //     Hence, move atoms along on away side
    575         // if all bonds side away (0) want contraction (-1), move towards side with atom: side 1
    576         //    (the reasoning is the same, don't interfere with update from
    577         //     stronger gradient)
    578         // hence, the decision is only based on sides once we have picked a side
    579         // depending on all bonds associated with have same good type.
    580 
    581         // away from gradient (minus) and contracting
    582         // or towards gradient (plus) and expanding
    583         // gather all on same side and remove
    584         const double sign =
    585             (sides[first_per_side[sideno]] == types[first_per_side[sideno]])
    586             ? sides[first_per_side[sideno]] : -1.*sides[first_per_side[sideno]];
    587 
    588         LOG(4, "DEBUG: Removing edges from side with sign " << sign);
    589         BondList::const_iterator bonditer = ListOfBonds.begin();
    590         RemovedEdges_t RemovedEdges;
    591         for (sides_t::const_iterator sidesiter = sides.begin();
    592             sidesiter != sides.end(); ++sidesiter, ++bonditer) {
    593           if (*sidesiter == sign) {
    594             // remove the edge
    595             const bond::ptr &current_bond = *bonditer;
    596             LOG(5, "DEBUG: Removing edge " << *current_bond);
    597             RemovedEdges.push_back( std::make_pair(
    598                 current_bond->leftatom->getId(),
    599                 current_bond->rightatom->getId())
    600             );
    601 #ifndef NDEBUG
    602             const bool status =
    603 #endif
    604                 BGcreator.removeEdge(RemovedEdges.back());
    605             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            }
    606640          }
    607         }
    608         // perform limited-horizon BFS
    609         BoostGraphHelpers::Nodeset_t bondside_set;
    610         BreadthFirstSearchGatherer::distance_map_t distance_map;
    611         bondside_set = NodeGatherer(walker.getId(), max_distance);
    612         distance_map = NodeGatherer.getDistances();
    613         std::sort(bondside_set.begin(), bondside_set.end());
    614 
    615         // re-add edge
    616         for (RemovedEdges_t::const_iterator edgeiter = RemovedEdges.begin();
    617             edgeiter != RemovedEdges.end(); ++edgeiter)
    618           BGcreator.addEdge(edgeiter->first, edgeiter->second);
    619 
    620         // update position with dampening factor on the discovered bonds
    621         for (BoostGraphHelpers::Nodeset_t::const_iterator setiter = bondside_set.begin();
    622             setiter != bondside_set.end(); ++setiter) {
    623           const BreadthFirstSearchGatherer::distance_map_t::const_iterator diter
    624             = distance_map.find(*setiter);
    625           ASSERT( diter != distance_map.end(),
    626               "ForceAnnealing() - could not find distance to an atom.");
    627           const double factor = pow(damping_factor, diter->second+1);
    628           LOG(3, "DEBUG: Update for atom #" << *setiter << " will be "
    629               << factor << "*" << PositionUpdate);
    630           if (GatheredUpdates.count((*setiter))) {
    631             GatheredUpdates[(*setiter)] += factor*PositionUpdate;
    632             LargestUpdate_per_Atom[(*setiter)] =
    633                 std::max(LargestUpdate_per_Atom[(*setiter)], factor*PositionUpdate.Norm());
    634           } else {
    635             GatheredUpdates.insert(
    636                 std::make_pair(
    637                     (*setiter),
    638                     factor*PositionUpdate) );
    639             LargestUpdate_per_Atom.insert(
    640                 std::make_pair(
    641                     (*setiter),
    642                     factor*PositionUpdate.Norm()) );
     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);
    643664          }
     665        } else {
     666          // simple atomic annealing, i.e. damping factor of 1
     667          updateInserter(GatheredUpdates, LargestUpdate_per_Atom, walker.getId(), PositionUpdate);
    644668        }
    645669      } else {
    646         // simple atomic annealing, i.e. damping factor of 1
    647         LOG(3, "DEBUG: Update for atom #" << walker.getId() << " will be " << PositionUpdate);
    648         GatheredUpdates.insert(
    649             std::make_pair(
    650                 walker.getId(),
    651                 PositionUpdate) );
    652         LargestUpdate_per_Atom.insert(
    653             std::make_pair(
    654                 walker.getId(),
    655                 PositionUpdate.Norm()) );
     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);
    656673      }
    657674    }
Note: See TracChangeset for help on using the changeset viewer.