Changeset bccbe9 for src/Actions


Ignore:
Timestamp:
Jul 12, 2017, 7:10:31 PM (7 years ago)
Author:
Frederik Heber <frederik.heber@…>
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)
Message:

Extracted extraction (subset of) nodes from BoostGraph into BreadthFirstSearchGatherer.

  • also added helper namespace BoostGraphHelpers.
  • we now treat the vertex indices and vertex names properly. Before that they had to coincide. Now, the name is the atomic id associated with the node and the index is the boost::graph internal index.
Location:
src/Actions/MoleculeAction
Files:
2 edited

Legend:

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

    rd24ef58 rbccbe9  
    3333#endif
    3434
    35 #include <boost/graph/adjacency_list.hpp>
    36 #include <boost/graph/breadth_first_search.hpp>
    37 
    3835//#include "CodePatterns/MemDebug.hpp"
    3936
     
    5249#include "Descriptors/AtomIdDescriptor.hpp"
    5350#include "Graph/BoostGraphCreator.hpp"
     51#include "Graph/BoostGraphHelpers.hpp"
     52#include "Graph/BreadthFirstSearchGatherer.hpp"
    5453#include "molecule.hpp"
    5554#include "World.hpp"
     
    6160#include "Action_impl_pre.hpp"
    6261
    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_visitor
    72 {
    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 }
    9162
    9263static bool addEdgePredicate(
     
    11081    return Action::failure;
    11182  }
     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
    11296  std::vector<atomId_t> atomids(2);
    11397  atomids[0] = atoms[0]->getId();
     
    11599  std::sort(atomids.begin(), atomids.end());
    116100  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();
    127108
    128109  // Assume the selected bond splits the molecule into two parts, each one on
     
    133114  // leaving the other positions untouched.
    134115
    135   // convert BondGraph into boost::graph
     116  // get nodes on either side of selected bond via BFS discovery
    136117  BoostGraphCreator BGcreator;
    137118  BGcreator.createFromMolecule(*mol,
    138119      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."
    166133          << " Shifting only bond partners.");
    167134      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] );
    169137        const Vector &position = atoms[j]->getPosition();
    170138        atoms[j]->setPosition( domain.enforceBoundaryConditions(position+Shift[j]) );
    171139      }
    172       break;
    173     }
     140      isCyclic = true;
     141    }
     142  }
    174143
    175144  // 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) {
    178146    for (molecule::iterator iter = mol->begin(); iter != mol->end(); ++iter) {
    179147      const Vector &position = (*iter)->getPosition();
    180148      // 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 {
    191155        ELOG(1, "Atom " << *iter << " is not contained on either side of bond? Undoing done shifts");
    192156        // 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();
    195159              iter != bondside_sets[i].end(); ++iter) {
    196160            atom &walker = *World::getInstance().getAtom(AtomById(*iter));
     
    214178  Box &domain = World::getInstance().getDomain();
    215179  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();
    217181        iter != state->bondside_sets[i].end(); ++iter) {
    218182      atom &walker = *World::getInstance().getAtom(AtomById(*iter));
     
    230194  Box &domain = World::getInstance().getDomain();
    231195  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();
    233197        iter != state->bondside_sets[i].end(); ++iter) {
    234198      atom &walker = *World::getInstance().getAtom(AtomById(*iter));
  • src/Actions/MoleculeAction/StretchBondAction.def

    rd24ef58 rbccbe9  
    2121(RangeValidator< double >(0., 10.))
    2222
    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 *)
    2424#define statereferences (Shift)(bondside_sets)(mol)
    2525
Note: See TracChangeset for help on using the changeset viewer.