Index: src/Dynamics/ForceAnnealing.hpp
===================================================================
--- src/Dynamics/ForceAnnealing.hpp	(revision d07be94506dc2c161a01ebc5c8a95f4d42d89885)
+++ src/Dynamics/ForceAnnealing.hpp	(revision 9190e6af861e577a6a8b46a31c96a36c116a9d6e)
@@ -22,4 +22,7 @@
 #include "Dynamics/AtomicForceManipulator.hpp"
 #include "Fragmentation/ForceMatrix.hpp"
+#include "Graph/BoostGraphCreator.hpp"
+#include "Graph/BoostGraphHelpers.hpp"
+#include "Graph/BreadthFirstSearchGatherer.hpp"
 #include "Helpers/helpers.hpp"
 #include "Helpers/defs.hpp"
@@ -29,9 +32,9 @@
 #include "World.hpp"
 
-/** This class is the essential build block for performing structual optimization.
+/** This class is the essential build block for performing structural optimization.
  *
  * Sadly, we have to use some static instances as so far values cannot be passed
  * between actions. Hence, we need to store the current step and the adaptive-
- * step width (we cannot perform a linesearch, as we have no control over the
+ * step width (we cannot perform a line search, as we have no control over the
  * calculation of the forces).
  */
@@ -86,4 +89,21 @@
     }
 
+    // get nodes on either side of selected bond via BFS discovery
+//    std::vector<atomId_t> atomids;
+//    for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
+//        iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
+//      atomids.push_back((*iter)->getId());
+//    }
+//    ASSERT( atomids.size() == AtomicForceManipulator<T>::atoms.size(),
+//        "ForceAnnealing() - could not gather all atomic ids?");
+    BoostGraphCreator BGcreator;
+    BGcreator.createFromRange(
+        AtomicForceManipulator<T>::atoms.begin(),
+        AtomicForceManipulator<T>::atoms.end(),
+        AtomicForceManipulator<T>::atoms.size(),
+        BreadthFirstSearchGatherer::AlwaysTruePredicate);
+    BreadthFirstSearchGatherer NodeGatherer(BGcreator);
+
+    std::map<atomId_t, Vector> GatheredUpdates; //!< gathers all updates which are applied at the end
     Vector maxComponents(zeroVec);
     for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
@@ -110,4 +130,68 @@
       LOG(3, "DEBUG: Update would be " << PositionUpdate);
 
+      // add update to central atom
+      const atomId_t atomid = (*iter)->getId();
+      if (GatheredUpdates.count(atomid)) {
+        GatheredUpdates[atomid] += PositionUpdate;
+      } else
+        GatheredUpdates.insert( std::make_pair(atomid, PositionUpdate) );
+
+      // We assume that a force is local, i.e. a bond is too short yet and hence
+      // the atom needs to be moved. However, all the adjacent (bound) atoms might
+      // already be at the perfect distance. If we just move the atom alone, we ruin
+      // all the other bonds. Hence, it would be sensible to move every atom found
+      // through the bond graph in the direction of the force as well by the same
+      // PositionUpdate. This is just what we are going to do.
+
+      /// get all nodes from bonds in the direction of the current force
+      const size_t max_distance = 4;
+      const double damping_factor = 0.9;
+
+      // remove edges facing in the wrong direction
+      std::vector<bond::ptr> removed_bonds;
+      const BondList& ListOfBonds = (*iter)->getListOfBonds();
+      for(BondList::const_iterator bonditer = ListOfBonds.begin();
+          bonditer != ListOfBonds.end(); ++bonditer) {
+        const bond &current_bond = *(*bonditer);
+        LOG(2, "DEBUG: Looking at bond " << current_bond);
+        Vector BondVector = (*iter)->getPosition();
+        BondVector -= ((*iter)->getId() == current_bond.rightatom->getId())
+            ? current_bond.rightatom->getPosition() : current_bond.leftatom->getPosition();
+        BondVector.Normalize();
+        if (BondVector.ScalarProduct(currentGradient) < 0) {
+          removed_bonds.push_back(*bonditer);
+#ifndef NDEBUG
+          const bool status =
+#endif
+              BGcreator.removeEdge(current_bond.leftatom->getId(), current_bond.rightatom->getId());
+          ASSERT( status, "ForceAnnealing() - edge to found bond is not present?");
+        }
+      }
+      BoostGraphHelpers::Nodeset_t bondside_set = NodeGatherer((*iter)->getId(), max_distance);
+      const BreadthFirstSearchGatherer::distance_map_t &distance_map = NodeGatherer.getDistances();
+      std::sort(bondside_set.begin(), bondside_set.end());
+      // re-add those edges
+      for (std::vector<bond::ptr>::const_iterator bonditer = removed_bonds.begin();
+          bonditer != removed_bonds.end(); ++bonditer)
+        BGcreator.addEdge((*bonditer)->leftatom->getId(), (*bonditer)->rightatom->getId());
+
+      // apply PositionUpdate to all nodes in the bondside_set
+      for (BoostGraphHelpers::Nodeset_t::const_iterator setiter = bondside_set.begin();
+          setiter != bondside_set.end(); ++setiter) {
+        const BreadthFirstSearchGatherer::distance_map_t::const_iterator diter
+          = distance_map.find(*setiter);
+        ASSERT( diter != distance_map.end(),
+            "ForceAnnealing() - could not find distance to an atom.");
+        const double factor = pow(damping_factor, diter->second);
+        if (GatheredUpdates.count((*setiter))) {
+          GatheredUpdates[(*setiter)] += factor*PositionUpdate;
+        } else {
+          GatheredUpdates.insert(
+              std::make_pair(
+                  (*setiter),
+                  factor*PositionUpdate) );
+        }
+      }
+
       // extract largest components for showing progress of annealing
       for(size_t i=0;i<NDIM;++i)
