Changeset 8754b1


Ignore:
Timestamp:
Jul 5, 2017, 7:46:00 PM (8 years ago)
Author:
Frederik Heber <frederik.heber@…>
Branches:
ForceAnnealing_oldresults
Parents:
bd0159
git-author:
Frederik Heber <frederik.heber@…> (05/19/17 14:29:40)
git-committer:
Frederik Heber <frederik.heber@…> (07/05/17 19:46:00)
Message:

ForceAnnealing now shifts atoms in the bond graph to anneal forces, too.

Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/Actions/MoleculeAction/ForceAnnealingAction.cpp

    rbd0159 r8754b1  
    9393      set,
    9494      true,
    95       params.steps.get());
     95      params.steps.get(),
     96      params.MaxDistance.get());
    9697  // parse forces into next step
    9798  if (!params.forcesfile.get().string().empty()) {
  • src/Actions/MoleculeAction/ForceAnnealingAction.def

    rbd0159 r8754b1  
    1616// ValueStorage by the token "Z" -> first column: int, Z, "Z"
    1717// "undefine" if no parameters are required, use (NOPARAM_DEFAULT) for each (undefined) default value
    18 #define paramtypes (boost::filesystem::path)(unsigned int)(bool)
    19 #define paramtokens ("forces-file")("steps")("output-every-step")
    20 #define paramdescriptions ("file containing")("fixed number of optimization steps to be performed")("whether WorldTime should be increased and output written after every step, useful if optimization might hang")
    21 #define paramdefaults (PARAM_DEFAULT(""))(NOPARAM_DEFAULT)(PARAM_DEFAULT("0"))
    22 #define paramreferences (forcesfile)(steps)(DoOutput)
     18#define paramtypes (boost::filesystem::path)(unsigned int)(bool)(int)
     19#define paramtokens ("forces-file")("steps")("output-every-step")("max-distance")
     20#define paramdescriptions ("file containing")("fixed number of optimization steps to be performed")("whether WorldTime should be increased and output written after every step, useful if optimization might hang")("maximum distance to which bond graph is taken into account")
     21#define paramdefaults (PARAM_DEFAULT(""))(NOPARAM_DEFAULT)(PARAM_DEFAULT("0"))(PARAM_DEFAULT(0))
     22#define paramreferences (forcesfile)(steps)(DoOutput)(MaxDistance)
    2323#define paramvalids \
    2424(DummyValidator< boost::filesystem::path >()) \
    2525(NotZeroValidator< unsigned int >()) \
    26 (DummyValidator<bool>())
     26(DummyValidator<bool>()) \
     27(DummyValidator< int >())
    2728
    2829#define statetypes (std::vector<AtomicInfo>)(std::vector<AtomicInfo>)
  • src/Dynamics/ForceAnnealing.hpp

    rbd0159 r8754b1  
    2020#include "CodePatterns/Log.hpp"
    2121#include "CodePatterns/Verbose.hpp"
     22#include "Descriptors/AtomIdDescriptor.hpp"
    2223#include "Dynamics/AtomicForceManipulator.hpp"
    2324#include "Fragmentation/ForceMatrix.hpp"
     25#include "Graph/BoostGraphCreator.hpp"
     26#include "Graph/BoostGraphHelpers.hpp"
     27#include "Graph/BreadthFirstSearchGatherer.hpp"
    2428#include "Helpers/helpers.hpp"
    2529#include "Helpers/defs.hpp"
     
    2933#include "World.hpp"
    3034
    31 /** This class is the essential build block for performing structual optimization.
     35/** This class is the essential build block for performing structural optimization.
    3236 *
    3337 * Sadly, we have to use some static instances as so far values cannot be passed
    3438 * between actions. Hence, we need to store the current step and the adaptive-
    35  * step width (we cannot perform a linesearch, as we have no control over the
     39 * step width (we cannot perform a line search, as we have no control over the
    3640 * calculation of the forces).
     41 *
     42 * However, we do use the bond graph, i.e. if a single atom needs to be shifted
     43 * to the left, then the whole molecule left of it is shifted, too. This is
     44 * controlled by the \a max_distance parameter.
    3745 */
    3846template <class T>
     
    4856   * \param _IsAngstroem whether length units are in angstroem or bohr radii
    4957   * \param _maxSteps number of optimization steps to perform
     58   * \param _max_distance up to this bond order is bond graph taken into account.
    5059   */
    5160  ForceAnnealing(
    5261      AtomSetMixin<T> &_atoms,
    5362      bool _IsAngstroem,
    54       const size_t _maxSteps) :
     63      const size_t _maxSteps,
     64      const int _max_distance) :
    5565    AtomicForceManipulator<T>(_atoms, 1., _IsAngstroem),
    56     maxSteps(_maxSteps)
     66    maxSteps(_maxSteps),
     67    max_distance(_max_distance),
     68    damping_factor(0.5)
    5769  {}
    5870  /** Destructor of class ForceAnnealing.
     
    8698    }
    8799
     100    // get nodes on either side of selected bond via BFS discovery
     101//    std::vector<atomId_t> atomids;
     102//    for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
     103//        iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
     104//      atomids.push_back((*iter)->getId());
     105//    }
     106//    ASSERT( atomids.size() == AtomicForceManipulator<T>::atoms.size(),
     107//        "ForceAnnealing() - could not gather all atomic ids?");
     108    BoostGraphCreator BGcreator;
     109    BGcreator.createFromRange(
     110        AtomicForceManipulator<T>::atoms.begin(),
     111        AtomicForceManipulator<T>::atoms.end(),
     112        AtomicForceManipulator<T>::atoms.size(),
     113        BreadthFirstSearchGatherer::AlwaysTruePredicate);
     114    BreadthFirstSearchGatherer NodeGatherer(BGcreator);
     115
     116    std::map<atomId_t, Vector> GatheredUpdates; //!< gathers all updates which are applied at the end
    88117    Vector maxComponents(zeroVec);
    89118    for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
     
    110139      LOG(3, "DEBUG: Update would be " << PositionUpdate);
    111140
     141//      // add update to central atom
     142//      const atomId_t atomid = (*iter)->getId();
     143//      if (GatheredUpdates.count(atomid)) {
     144//        GatheredUpdates[atomid] += PositionUpdate;
     145//      } else
     146//        GatheredUpdates.insert( std::make_pair(atomid, PositionUpdate) );
     147
     148      // We assume that a force is local, i.e. a bond is too short yet and hence
     149      // the atom needs to be moved. However, all the adjacent (bound) atoms might
     150      // already be at the perfect distance. If we just move the atom alone, we ruin
     151      // all the other bonds. Hence, it would be sensible to move every atom found
     152      // through the bond graph in the direction of the force as well by the same
     153      // PositionUpdate. This is just what we are going to do.
     154
     155      /// get all nodes from bonds in the direction of the current force
     156
     157      // remove edges facing in the wrong direction
     158      std::vector<bond::ptr> removed_bonds;
     159      const BondList& ListOfBonds = (*iter)->getListOfBonds();
     160      for(BondList::const_iterator bonditer = ListOfBonds.begin();
     161          bonditer != ListOfBonds.end(); ++bonditer) {
     162        const bond &current_bond = *(*bonditer);
     163        LOG(2, "DEBUG: Looking at bond " << current_bond);
     164        Vector BondVector = (*iter)->getPosition();
     165        BondVector -= ((*iter)->getId() == current_bond.rightatom->getId())
     166            ? current_bond.rightatom->getPosition() : current_bond.leftatom->getPosition();
     167        BondVector.Normalize();
     168        if (BondVector.ScalarProduct(currentGradient) < 0) {
     169          removed_bonds.push_back(*bonditer);
     170#ifndef NDEBUG
     171          const bool status =
     172#endif
     173              BGcreator.removeEdge(current_bond.leftatom->getId(), current_bond.rightatom->getId());
     174          ASSERT( status, "ForceAnnealing() - edge to found bond is not present?");
     175        }
     176      }
     177      BoostGraphHelpers::Nodeset_t bondside_set = NodeGatherer((*iter)->getId(), max_distance);
     178      const BreadthFirstSearchGatherer::distance_map_t &distance_map = NodeGatherer.getDistances();
     179      std::sort(bondside_set.begin(), bondside_set.end());
     180      // re-add those edges
     181      for (std::vector<bond::ptr>::const_iterator bonditer = removed_bonds.begin();
     182          bonditer != removed_bonds.end(); ++bonditer)
     183        BGcreator.addEdge((*bonditer)->leftatom->getId(), (*bonditer)->rightatom->getId());
     184
     185      // apply PositionUpdate to all nodes in the bondside_set
     186      for (BoostGraphHelpers::Nodeset_t::const_iterator setiter = bondside_set.begin();
     187          setiter != bondside_set.end(); ++setiter) {
     188        const BreadthFirstSearchGatherer::distance_map_t::const_iterator diter
     189          = distance_map.find(*setiter);
     190        ASSERT( diter != distance_map.end(),
     191            "ForceAnnealing() - could not find distance to an atom.");
     192        const double factor = pow(damping_factor, diter->second);
     193        LOG(3, "DEBUG: Update for atom #" << *setiter << " will be "
     194            << factor << "*" << PositionUpdate);
     195        if (GatheredUpdates.count((*setiter))) {
     196          GatheredUpdates[(*setiter)] += factor*PositionUpdate;
     197        } else {
     198          GatheredUpdates.insert(
     199              std::make_pair(
     200                  (*setiter),
     201                  factor*PositionUpdate) );
     202        }
     203      }
     204
    112205      // extract largest components for showing progress of annealing
    113206      for(size_t i=0;i<NDIM;++i)
     
    115208          maxComponents[i] = currentGradient[i];
    116209
    117       // are we in initial step? Then don't check against velocity
    118       if ((currentStep > 1) && (!(*iter)->getAtomicVelocity().IsZero()))
    119         // update with currentDelta tells us how the current gradient relates to
    120         // the last one: If it has become larger, reduce currentDelta
    121         if ((PositionUpdate.ScalarProduct((*iter)->getAtomicVelocity()) < 0)
    122             && (currentDeltat > MinimumDeltat)) {
    123           currentDeltat = .5*currentDeltat;
    124           LOG(2, "DEBUG: Upgrade in other direction: " << PositionUpdate.NormSquared()
    125               << " > " << (*iter)->getAtomicVelocity().NormSquared()
    126               << ", decreasing deltat: " << currentDeltat);
    127           PositionUpdate = currentDeltat * currentGradient;
    128         }
    129 
    130       // finally set new values
    131       (*iter)->setPosition(currentPosition + PositionUpdate);
    132       (*iter)->setAtomicVelocity(PositionUpdate);
    133       //std::cout << "Id of atom is " << (*iter)->getId() << std::endl;
    134 //        (*iter)->VelocityVerletUpdateU((*iter)->getId(), NextStep-1, Deltat, IsAngstroem);
    135 
    136210      // reset force vector for next step except on final one
    137211      if (currentStep != maxSteps)
    138212        (*iter)->setAtomicForce(zeroVec);
     213    }
     214    // apply the gathered updates
     215    for (std::map<atomId_t, Vector>::const_iterator iter = GatheredUpdates.begin();
     216        iter != GatheredUpdates.end(); ++iter) {
     217      const atomId_t &atomid = iter->first;
     218      const Vector &update = iter->second;
     219      atom* const walker = World::getInstance().getAtom(AtomById(atomid));
     220      ASSERT( walker != NULL,
     221          "ForceAnnealing() - walker with id "+toString(atomid)+" has suddenly disappeared.");
     222      walker->setPosition( walker->getPosition() + update );
     223      walker->setAtomicVelocity(update);
     224      LOG(3, "DEBUG: Applying update " << update << " to atom " << *walker);
    139225    }
    140226
     
    171257  //!> minimum deltat for internal while loop (adaptive step width)
    172258  static double MinimumDeltat;
     259  //!> contains the maximum bond graph distance up to which shifts of a single atom are spread
     260  const int max_distance;
     261  //!> the shifted is dampened by this factor with the power of the bond graph distance to the shift causing atom
     262  const double damping_factor;
    173263};
    174264
  • tests/Python/AllActions/options.dat

    rbd0159 r8754b1  
    104104load-session    "test.py"
    105105MaxDistance     "-1"
     106max-distance    "0"
    106107max-meshwidth   "0.3"
    107108mesh-offset     "0.5,0.5,0.5"
Note: See TracChangeset for help on using the changeset viewer.