Changeset 3b74fa 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:
- d24ef58
- Parents:
- 0716eac
- git-author:
- Frederik Heber <frederik.heber@…> (05/14/17 21:08:41)
- 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
r0716eac r3b74fa 33 33 #endif 34 34 35 #include <boost/graph/adjacency_list.hpp> 36 #include <boost/graph/breadth_first_search.hpp> 37 #include <boost/graph/subgraph.hpp> 38 35 39 //#include "CodePatterns/MemDebug.hpp" 36 40 … … 44 48 #include "Atom/atom.hpp" 45 49 #include "Bond/bond.hpp" 50 #include "Descriptors/AtomIdDescriptor.hpp" 46 51 #include "molecule.hpp" 47 52 #include "World.hpp" … … 52 57 #include "StretchBondAction.def" 53 58 #include "Action_impl_pre.hpp" 59 60 61 /** 62 * I have no idea why this is so complicated with BGL ... 63 * 64 * This is taken from the book "The Boost Graph Library: User Guide and Reference Manual, Portable Documents", 65 * chapter "Basic Graph Algorithms", example on calculating the bacon number. 66 */ 67 template <typename DistanceMap> 68 class distance_recorder : public boost::default_bfs_visitor 69 { 70 public: 71 distance_recorder(DistanceMap dist) : d(dist) {} 72 73 template <typename Edge, typename Graph> 74 void tree_edge(Edge e, const Graph &g) const { 75 typename boost::graph_traits<Graph>::vertex_descriptor u = source(e,g), v = target(e,g); 76 d[v] = d[u] + 1; 77 } 78 79 private: 80 DistanceMap d; 81 }; 82 83 template <typename DistanceMap> 84 distance_recorder<DistanceMap> record_distance(DistanceMap d) 85 { 86 return distance_recorder<DistanceMap>(d); 87 } 88 54 89 /** =========== define the function ====================== */ 55 90 ActionState::ptr MoleculeStretchBondAction::performCall() … … 61 96 return Action::failure; 62 97 } 98 std::vector<atomId_t> atomids(2); 99 atomids[0] = atoms[0]->getId(); 100 atomids[1] = atoms[1]->getId(); 101 std::sort(atomids.begin(), atomids.end()); 102 LOG(1, "DEBUG: Selected nodes are " << atomids); 63 103 molecule *mol = World::getInstance(). 64 104 getMolecule(MoleculeById(atoms[0]->getMolecule()->getId())); … … 72 112 LOG(1, "INFO: Old bond distance is " << olddistance << ", stretching to " << newdistance << "."); 73 113 74 // create the bond plane and mid-distance 114 // Assume the selected bond splits the molecule into two parts, each one on 115 // either side of the bond. We need to perform a BFS from each bond partner 116 // not using the selected bond. Therefrom, we obtain two sets of atoms/nodes. 117 // If both are disjoint, the bond is not contained in a cycle and we simply 118 // shift either set as desired. If not, then we simply shift each atom, 119 // leaving the other positions untouched. 120 typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS, 121 boost::no_property, boost::no_property > UndirectedGraph; 122 123 // convert BondGraph into boost::graph 124 UndirectedGraph molgraph(mol->getAtomCount()); 125 size_t no_edges = 0; 126 for(molecule::const_iterator iter = const_cast<const molecule * const>(mol)->begin(); 127 iter != const_cast<const molecule * const>(mol)->end(); ++iter) { 128 LOG(2, "DEBUG: Looking at node " << (*iter)->getId()); 129 const BondList& ListOfBonds = (*iter)->getListOfBonds(); 130 for(BondList::const_iterator bonditer = ListOfBonds.begin(); 131 bonditer != ListOfBonds.end(); ++bonditer) { 132 const unsigned int &leftid = (*bonditer)->leftatom->getId(); 133 const unsigned int &rightid = (*bonditer)->rightatom->getId(); 134 // only add each edge once and do not add selected edge 135 if ((leftid == (*iter)->getId()) 136 && ((leftid != atomids[0]) || (rightid != atomids[1]))) { 137 LOG(1, "DEBUG: ADDING edge " << leftid << " <-> " << rightid); 138 boost::add_edge(leftid, rightid, molgraph); 139 ++no_edges; 140 } else { 141 LOG(1, "DEBUG: Discarding edge " << leftid << " <-> " << rightid); 142 } 143 } 144 } 145 typedef boost::property_map < boost::adjacency_list <>, boost::vertex_index_t >::type index_map_t; 146 index_map_t index_map = boost::get(boost::vertex_index, molgraph); 147 const size_t num_vertices = boost::num_vertices(molgraph); 148 LOG(2, "DEBUG: We have " << num_vertices << " nodes and " << no_edges 149 << " edges in the molecule graph."); 150 151 std::vector< std::vector<size_t> > distances; 152 for (size_t i=0;i<2;++i) { 153 distances.push_back(std::vector<size_t>(num_vertices, num_vertices+1)); // set distance to num+1 154 distances[i][atomids[i]] = 0; 155 boost::breadth_first_search( 156 molgraph, 157 boost::vertex(atomids[i], molgraph), 158 boost::visitor(record_distance(&(distances[i][0])))); 159 LOG(3, "DEBUG: From atom #" << atomids[i] 160 << " BFS discovered the following distances " << distances[i]); 161 } 162 75 163 const Vector NormalVector = (atoms[0]->getPosition() - atoms[1]->getPosition())* (1./olddistance); 76 const Vector OffsetVector = 0.5*(atoms[0]->getPosition() + atoms[1]->getPosition());77 Plane bondplane(NormalVector, OffsetVector);78 // go through the molecule and stretch each atom relative two plane79 164 const double shift = 0.5*(newdistance - olddistance); 80 const Vector PositiveShift = shift * NormalVector; 81 const Vector NegativeShift = -shift * NormalVector; 165 std::vector<Vector> Shift(2); 166 Shift[0] = shift * NormalVector; 167 Shift[1] = -shift * NormalVector; 82 168 Box &domain = World::getInstance().getDomain(); 83 for (molecule::iterator iter = mol->begin(); iter != mol->end(); ++iter) { 84 const Vector &position = (*iter)->getPosition(); 85 // for each atom determine on which side of plane it is and shift accordingly 86 if (bondplane.SignedDistance(position) > 0) { 87 (*iter)->setPosition( domain.enforceBoundaryConditions(position+PositiveShift) ); 88 } else { 89 (*iter)->setPosition( domain.enforceBoundaryConditions(position+NegativeShift) ); 90 } 91 } 92 93 MoleculeStretchBondState *UndoState = new MoleculeStretchBondState(shift, bondplane, mol, params); 169 std::vector< std::vector<size_t> > bondside_sets(2); 170 171 // Check whether there are common nodes in each set of distances 172 for (size_t i=0;i<num_vertices;++i) 173 if ((distances[0][i] != (num_vertices+1)) && (distances[1][i] != (num_vertices+1))) { 174 ELOG(2, "Node #" << i << " is reachable from either side of bond, hence must by cyclic." 175 << " Shifting only bond partners."); 176 for(size_t j=0;j<2;++j) { 177 bondside_sets[j].push_back(atoms[j]->getId()); 178 const Vector &position = atoms[j]->getPosition(); 179 atoms[j]->setPosition( domain.enforceBoundaryConditions(position+Shift[j]) ); 180 } 181 break; 182 } 183 184 // go through the molecule and stretch each atom in either set of nodes 185 if (bondside_sets[0].empty()) { 186 for (molecule::iterator iter = mol->begin(); iter != mol->end(); ++iter) { 187 const Vector &position = (*iter)->getPosition(); 188 // for each atom determine in which set of nodes it is and shift accordingly 189 size_t i=0; 190 const size_t nodeindex = boost::get(index_map, boost::vertex((*iter)->getId(), molgraph)); 191 for (;i<2;++i) { 192 if (distances[i][nodeindex] != (num_vertices+1)) { 193 (*iter)->setPosition( domain.enforceBoundaryConditions(position+Shift[i]) ); 194 bondside_sets[i].push_back((*iter)->getId()); 195 break; 196 } 197 } 198 if (i==2) { 199 ELOG(1, "Atom " << *iter << " is not contained on either side of bond? Undoing done shifts"); 200 // Have to undo shifts 201 for (i=0;i<2;++i) { 202 for (std::vector<size_t>::const_iterator iter = bondside_sets[i].begin(); 203 iter != bondside_sets[i].end(); ++iter) { 204 atom &walker = *World::getInstance().getAtom(AtomById(*iter)); 205 const Vector &position = walker.getPosition(); 206 walker.setPosition( domain.enforceBoundaryConditions(position-Shift[i]) ); 207 } 208 } 209 return Action::failure; 210 } 211 } 212 } 213 214 MoleculeStretchBondState *UndoState = new MoleculeStretchBondState(Shift, bondside_sets, mol, params); 94 215 return ActionState::ptr(UndoState); 95 216 } … … 99 220 100 221 // use given plane to undo 101 const Vector PositiveShift = state->shift * state->bondplane.getNormal();102 const Vector NegativeShift = -state->shift * state->bondplane.getNormal();103 222 Box &domain = World::getInstance().getDomain(); 104 molecule *mol = World::getInstance(). 105 getMolecule(MoleculeById(state->mol->getId())); 106 for (molecule::iterator iter = mol->begin(); 107 iter != mol->end(); ++iter) { 108 const Vector &position = (*iter)->getPosition(); 109 // for each atom determine on which side of plane it is and shift accordingly 110 if (state->bondplane.SignedDistance(position) < 0) { 111 (*iter)->setPosition( domain.enforceBoundaryConditions(position+PositiveShift) ); 112 } else { 113 (*iter)->setPosition( domain.enforceBoundaryConditions(position+NegativeShift) ); 223 for (size_t i=0;i<2;++i) { 224 for (std::vector<size_t>::const_iterator iter = state->bondside_sets[i].begin(); 225 iter != state->bondside_sets[i].end(); ++iter) { 226 atom &walker = *World::getInstance().getAtom(AtomById(*iter)); 227 const Vector &position = walker.getPosition(); 228 walker.setPosition( domain.enforceBoundaryConditions(position-state->Shift[i]) ); 114 229 } 115 230 } … … 121 236 MoleculeStretchBondState *state = assert_cast<MoleculeStretchBondState*>(_state.get()); 122 237 123 // use given plane to undo124 const Vector PositiveShift = state->shift * state->bondplane.getNormal();125 const Vector NegativeShift = -state->shift * state->bondplane.getNormal();126 238 Box &domain = World::getInstance().getDomain(); 127 molecule *mol = World::getInstance(). 128 getMolecule(MoleculeById(state->mol->getId())); 129 for (molecule::iterator iter = mol->begin(); 130 iter != mol->end(); ++iter) { 131 const Vector &position = (*iter)->getPosition(); 132 // for each atom determine on which side of plane it is and shift accordingly 133 if (state->bondplane.SignedDistance(position) > 0) { 134 (*iter)->setPosition( domain.enforceBoundaryConditions(position+PositiveShift) ); 135 } else { 136 (*iter)->setPosition( domain.enforceBoundaryConditions(position+NegativeShift) ); 137 } 138 } 239 for (size_t i=0;i<2;++i) { 240 for (std::vector<size_t>::const_iterator iter = state->bondside_sets[i].begin(); 241 iter != state->bondside_sets[i].end(); ++iter) { 242 atom &walker = *World::getInstance().getAtom(AtomById(*iter)); 243 const Vector &position = walker.getPosition(); 244 walker.setPosition( domain.enforceBoundaryConditions(position+state->Shift[i]) ); 245 } 246 } 247 139 248 return ActionState::ptr(_state); 140 249 } -
src/Actions/MoleculeAction/StretchBondAction.def
r0716eac r3b74fa 21 21 (RangeValidator< double >(0., 10.)) 22 22 23 #define statetypes ( const double)(const Plane)(const molecule *)24 #define statereferences ( shift)(bondplane)(mol)23 #define statetypes (std::vector<Vector>)(std::vector< std::vector<size_t> >)(const molecule *) 24 #define statereferences (Shift)(bondside_sets)(mol) 25 25 26 26 // some defines for all the names, you may use ACTION, STATE and PARAMS
Note:
See TracChangeset
for help on using the changeset viewer.