Changeset bccbe9 for src/Actions
- Timestamp:
- Jul 12, 2017, 7:10:31 PM (7 years ago)
- Branches:
- Action_Thermostats, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_StructOpt_integration_tests, AutomationFragmentation_failures, Candidate_v1.6.1, ChemicalSpaceEvaluator, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Exclude_Hydrogens_annealWithBondGraph, Fix_Verbose_Codepatterns, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, Gui_displays_atomic_force_velocity, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, PythonUI_with_named_parameters, Recreated_GuiChecks, StoppableMakroAction, TremoloParser_IncreasedPrecision
- Children:
- 6e5b8d
- Parents:
- d24ef58
- git-author:
- Frederik Heber <frederik.heber@…> (05/18/17 17:45:47)
- git-committer:
- Frederik Heber <frederik.heber@…> (07/12/17 19:10:31)
- Location:
- src/Actions/MoleculeAction
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Actions/MoleculeAction/StretchBondAction.cpp
rd24ef58 rbccbe9 33 33 #endif 34 34 35 #include <boost/graph/adjacency_list.hpp>36 #include <boost/graph/breadth_first_search.hpp>37 38 35 //#include "CodePatterns/MemDebug.hpp" 39 36 … … 52 49 #include "Descriptors/AtomIdDescriptor.hpp" 53 50 #include "Graph/BoostGraphCreator.hpp" 51 #include "Graph/BoostGraphHelpers.hpp" 52 #include "Graph/BreadthFirstSearchGatherer.hpp" 54 53 #include "molecule.hpp" 55 54 #include "World.hpp" … … 61 60 #include "Action_impl_pre.hpp" 62 61 63 64 /**65 * I have no idea why this is so complicated with BGL ...66 *67 * This is taken from the book "The Boost Graph Library: User Guide and Reference Manual, Portable Documents",68 * chapter "Basic Graph Algorithms", example on calculating the bacon number.69 */70 template <typename DistanceMap>71 class distance_recorder : public boost::default_bfs_visitor72 {73 public:74 distance_recorder(DistanceMap dist) : d(dist) {}75 76 template <typename Edge, typename Graph>77 void tree_edge(Edge e, const Graph &g) const {78 typename boost::graph_traits<Graph>::vertex_descriptor u = source(e,g), v = target(e,g);79 d[v] = d[u] + 1;80 }81 82 private:83 DistanceMap d;84 };85 86 template <typename DistanceMap>87 distance_recorder<DistanceMap> record_distance(DistanceMap d)88 {89 return distance_recorder<DistanceMap>(d);90 }91 62 92 63 static bool addEdgePredicate( … … 110 81 return Action::failure; 111 82 } 83 molecule *mol = World::getInstance(). 84 getMolecule(MoleculeById(atoms[0]->getMolecule()->getId())); 85 if (mol != atoms[1]->getMolecule()) { 86 STATUS("The two selected atoms must belong to the same molecule."); 87 return Action::failure; 88 } 89 90 // gather undo information 91 const double olddistance = atoms[0]->getPosition().distance(atoms[1]->getPosition()); 92 const double newdistance = params.bonddistance.get(); 93 LOG(1, "INFO: Old bond distance is " << olddistance << ", stretching to " << newdistance << "."); 94 95 // gather sorted ids 112 96 std::vector<atomId_t> atomids(2); 113 97 atomids[0] = atoms[0]->getId(); … … 115 99 std::sort(atomids.begin(), atomids.end()); 116 100 LOG(1, "DEBUG: Selected nodes are " << atomids); 117 molecule *mol = World::getInstance(). 118 getMolecule(MoleculeById(atoms[0]->getMolecule()->getId())); 119 if (mol != atoms[1]->getMolecule()) { 120 STATUS("The two selected atoms must belong to the same molecule."); 121 return Action::failure; 122 } 123 // gather undo information 124 const double olddistance = atoms[0]->getPosition().distance(atoms[1]->getPosition()); 125 const double newdistance = params.bonddistance.get(); 126 LOG(1, "INFO: Old bond distance is " << olddistance << ", stretching to " << newdistance << "."); 101 102 const Vector NormalVector = (atoms[0]->getPosition() - atoms[1]->getPosition())* (1./olddistance); 103 const double shift = 0.5*(newdistance - olddistance); 104 std::vector<Vector> Shift(2); 105 Shift[0] = shift * NormalVector; 106 Shift[1] = -shift * NormalVector; 107 Box &domain = World::getInstance().getDomain(); 127 108 128 109 // Assume the selected bond splits the molecule into two parts, each one on … … 133 114 // leaving the other positions untouched. 134 115 135 // convert BondGraph into boost::graph116 // get nodes on either side of selected bond via BFS discovery 136 117 BoostGraphCreator BGcreator; 137 118 BGcreator.createFromMolecule(*mol, 138 119 boost::bind(addEdgePredicate, _1, boost::ref(atomids))); 139 const BoostGraphCreator::UndirectedGraph &molgraph = BGcreator.get(); 140 141 const size_t num_vertices = BGcreator.getNumVertices(); 142 std::vector< std::vector<size_t> > distances; 143 for (size_t i=0;i<2;++i) { 144 distances.push_back(std::vector<size_t>(num_vertices, num_vertices+1)); // set distance to num+1 145 distances[i][atomids[i]] = 0; 146 boost::breadth_first_search( 147 molgraph, 148 boost::vertex(atomids[i], molgraph), 149 boost::visitor(record_distance(&(distances[i][0])))); 150 LOG(3, "DEBUG: From atom #" << atomids[i] 151 << " BFS discovered the following distances " << distances[i]); 152 } 153 154 const Vector NormalVector = (atoms[0]->getPosition() - atoms[1]->getPosition())* (1./olddistance); 155 const double shift = 0.5*(newdistance - olddistance); 156 std::vector<Vector> Shift(2); 157 Shift[0] = shift * NormalVector; 158 Shift[1] = -shift * NormalVector; 159 Box &domain = World::getInstance().getDomain(); 160 std::vector< std::vector<size_t> > bondside_sets(2); 161 162 // Check whether there are common nodes in each set of distances 163 for (size_t i=0;i<num_vertices;++i) 164 if ((distances[0][i] != (num_vertices+1)) && (distances[1][i] != (num_vertices+1))) { 165 ELOG(2, "Node #" << i << " is reachable from either side of bond, hence must by cyclic." 120 BreadthFirstSearchGatherer NodeGatherer(BGcreator); 121 std::vector< BoostGraphHelpers::Nodeset_t > bondside_sets(2); 122 for(size_t j=0;j<2;++j) { 123 bondside_sets[j] = NodeGatherer(atoms[j]->getId()); 124 std::sort(bondside_sets[j].begin(), bondside_sets[j].end()); 125 } 126 127 // simple test whether bond has split the system in two disjoint sets or not 128 bool isCyclic = false; 129 if ((bondside_sets[0].size() + bondside_sets[1].size()) > BGcreator.getNumVertices()) { 130 // Check whether there are common nodes in each set of distances 131 if (BoostGraphHelpers::isCommonNodeInVector(bondside_sets[0], bondside_sets[1])) { 132 ELOG(2, "Sets contain common node, hence bond must have been by cyclic." 166 133 << " Shifting only bond partners."); 167 134 for(size_t j=0;j<2;++j) { 168 bondside_sets[j].push_back(atoms[j]->getId()); 135 bondside_sets[j].clear(); 136 bondside_sets[j].push_back( atomids[j] ); 169 137 const Vector &position = atoms[j]->getPosition(); 170 138 atoms[j]->setPosition( domain.enforceBoundaryConditions(position+Shift[j]) ); 171 139 } 172 break; 173 } 140 isCyclic = true; 141 } 142 } 174 143 175 144 // go through the molecule and stretch each atom in either set of nodes 176 if (bondside_sets[0].empty()) { 177 const BoostGraphCreator::index_map_t index_map = BGcreator.getIndexMap(); 145 if (!isCyclic) { 178 146 for (molecule::iterator iter = mol->begin(); iter != mol->end(); ++iter) { 179 147 const Vector &position = (*iter)->getPosition(); 180 148 // for each atom determine in which set of nodes it is and shift accordingly 181 size_t i=0; 182 const size_t nodeindex = boost::get(index_map, boost::vertex((*iter)->getId(), molgraph)); 183 for (;i<2;++i) { 184 if (distances[i][nodeindex] != (num_vertices+1)) { 185 (*iter)->setPosition( domain.enforceBoundaryConditions(position+Shift[i]) ); 186 bondside_sets[i].push_back((*iter)->getId()); 187 break; 188 } 189 } 190 if (i==2) { 149 const atomId_t &atomid = (*iter)->getId(); 150 if (std::binary_search(bondside_sets[0].begin(), bondside_sets[0].end(), atomid)) { 151 (*iter)->setPosition( domain.enforceBoundaryConditions(position+Shift[0]) ); 152 } else if (std::binary_search(bondside_sets[1].begin(), bondside_sets[1].end(), atomid)) { 153 (*iter)->setPosition( domain.enforceBoundaryConditions(position+Shift[1]) ); 154 } else { 191 155 ELOG(1, "Atom " << *iter << " is not contained on either side of bond? Undoing done shifts"); 192 156 // Have to undo shifts 193 for ( i=0;i<2;++i) {194 for ( std::vector<size_t>::const_iterator iter = bondside_sets[i].begin();157 for (size_t i=0;i<2;++i) { 158 for (BoostGraphHelpers::Nodeset_t::const_iterator iter = bondside_sets[i].begin(); 195 159 iter != bondside_sets[i].end(); ++iter) { 196 160 atom &walker = *World::getInstance().getAtom(AtomById(*iter)); … … 214 178 Box &domain = World::getInstance().getDomain(); 215 179 for (size_t i=0;i<2;++i) { 216 for ( std::vector<size_t>::const_iterator iter = state->bondside_sets[i].begin();180 for (BoostGraphHelpers::Nodeset_t::const_iterator iter = state->bondside_sets[i].begin(); 217 181 iter != state->bondside_sets[i].end(); ++iter) { 218 182 atom &walker = *World::getInstance().getAtom(AtomById(*iter)); … … 230 194 Box &domain = World::getInstance().getDomain(); 231 195 for (size_t i=0;i<2;++i) { 232 for ( std::vector<size_t>::const_iterator iter = state->bondside_sets[i].begin();196 for (BoostGraphHelpers::Nodeset_t::const_iterator iter = state->bondside_sets[i].begin(); 233 197 iter != state->bondside_sets[i].end(); ++iter) { 234 198 atom &walker = *World::getInstance().getAtom(AtomById(*iter)); -
src/Actions/MoleculeAction/StretchBondAction.def
rd24ef58 rbccbe9 21 21 (RangeValidator< double >(0., 10.)) 22 22 23 #define statetypes (std::vector<Vector>)(std::vector< std::vector<size_t>>)(const molecule *)23 #define statetypes (std::vector<Vector>)(std::vector< BoostGraphHelpers::Nodeset_t >)(const molecule *) 24 24 #define statereferences (Shift)(bondside_sets)(mol) 25 25
Note:
See TracChangeset
for help on using the changeset viewer.