Changeset 8754b1 for src/Dynamics/ForceAnnealing.hpp
- Timestamp:
- Jul 5, 2017, 7:46:00 PM (8 years ago)
- 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)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Dynamics/ForceAnnealing.hpp
rbd0159 r8754b1 20 20 #include "CodePatterns/Log.hpp" 21 21 #include "CodePatterns/Verbose.hpp" 22 #include "Descriptors/AtomIdDescriptor.hpp" 22 23 #include "Dynamics/AtomicForceManipulator.hpp" 23 24 #include "Fragmentation/ForceMatrix.hpp" 25 #include "Graph/BoostGraphCreator.hpp" 26 #include "Graph/BoostGraphHelpers.hpp" 27 #include "Graph/BreadthFirstSearchGatherer.hpp" 24 28 #include "Helpers/helpers.hpp" 25 29 #include "Helpers/defs.hpp" … … 29 33 #include "World.hpp" 30 34 31 /** This class is the essential build block for performing structu al optimization.35 /** This class is the essential build block for performing structural optimization. 32 36 * 33 37 * Sadly, we have to use some static instances as so far values cannot be passed 34 38 * between actions. Hence, we need to store the current step and the adaptive- 35 * step width (we cannot perform a line search, as we have no control over the39 * step width (we cannot perform a line search, as we have no control over the 36 40 * 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. 37 45 */ 38 46 template <class T> … … 48 56 * \param _IsAngstroem whether length units are in angstroem or bohr radii 49 57 * \param _maxSteps number of optimization steps to perform 58 * \param _max_distance up to this bond order is bond graph taken into account. 50 59 */ 51 60 ForceAnnealing( 52 61 AtomSetMixin<T> &_atoms, 53 62 bool _IsAngstroem, 54 const size_t _maxSteps) : 63 const size_t _maxSteps, 64 const int _max_distance) : 55 65 AtomicForceManipulator<T>(_atoms, 1., _IsAngstroem), 56 maxSteps(_maxSteps) 66 maxSteps(_maxSteps), 67 max_distance(_max_distance), 68 damping_factor(0.5) 57 69 {} 58 70 /** Destructor of class ForceAnnealing. … … 86 98 } 87 99 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 88 117 Vector maxComponents(zeroVec); 89 118 for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin(); … … 110 139 LOG(3, "DEBUG: Update would be " << PositionUpdate); 111 140 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 ¤t_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 112 205 // extract largest components for showing progress of annealing 113 206 for(size_t i=0;i<NDIM;++i) … … 115 208 maxComponents[i] = currentGradient[i]; 116 209 117 // are we in initial step? Then don't check against velocity118 if ((currentStep > 1) && (!(*iter)->getAtomicVelocity().IsZero()))119 // update with currentDelta tells us how the current gradient relates to120 // the last one: If it has become larger, reduce currentDelta121 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 values131 (*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 136 210 // reset force vector for next step except on final one 137 211 if (currentStep != maxSteps) 138 212 (*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); 139 225 } 140 226 … … 171 257 //!> minimum deltat for internal while loop (adaptive step width) 172 258 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; 173 263 }; 174 264
Note:
See TracChangeset
for help on using the changeset viewer.