Changeset 9f55b9


Ignore:
Timestamp:
Apr 23, 2021, 8:34:22 PM (5 years ago)
Author:
Frederik Heber <frederik.heber@…>
Branches:
Candidate_v1.7.0, stable
Children:
4de4f6
Parents:
f3eb6a
git-author:
Frederik Heber <frederik.heber@…> (10/04/20 20:13:46)
git-committer:
Frederik Heber <frederik.heber@…> (04/23/21 20:34:22)
Message:

Extracted functor StretchBondUtil from StretchBondAction.

Location:
src
Files:
2 added
3 edited

Legend:

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

    rf3eb6a r9f55b9  
    3939#include <boost/bind.hpp>
    4040
    41 #include "CodePatterns/Assert.hpp"
    4241#include "CodePatterns/Log.hpp"
    4342#include "CodePatterns/Verbose.hpp"
     
    4746#include "Atom/atom.hpp"
    4847#include "Bond/bond.hpp"
    49 #include "Descriptors/AtomIdDescriptor.hpp"
    50 #include "Graph/BoostGraphCreator.hpp"
     48#include "Bond/StretchBond.hpp"
    5149#include "Graph/BoostGraphHelpers.hpp"
    52 #include "Graph/BreadthFirstSearchGatherer.hpp"
    53 #include "molecule.hpp"
    5450#include "World.hpp"
    5551
     
    6157
    6258
    63 static bool addEdgePredicate(
    64     const bond &_bond,
    65     const std::vector<atomId_t> &_atomids)
    66 {
    67   ASSERT(_atomids.size() == (size_t)2,
    68       "addEdgePredicate() - atomids must contain exactly two ids.");
    69   // do not add selected edge
    70   return ((_bond.leftatom->getId() != _atomids[0])
    71       || (_bond.rightatom->getId() != _atomids[1]));
    72 }
    73 
    7459/** =========== define the function ====================== */
    7560ActionState::ptr MoleculeStretchBondAction::performCall()
    7661{
    77   // check preconditions
    7862  const std::vector< atom *> atoms = World::getInstance().getSelectedAtoms();
    79   if (atoms.size() != 2) {
    80     STATUS("Exactly two atoms must be selected.");
     63  StretchBondUtil stretcher(atoms);
     64  bool status = stretcher(params.bonddistance.get());
     65
     66  if (status) {
     67    MoleculeStretchBondState *UndoState =
     68        new MoleculeStretchBondState(
     69            stretcher.getShift(),
     70            stretcher.getBondSides(),
     71            &stretcher.getMolecule(),
     72            params);
     73    return ActionState::ptr(UndoState);
     74  } else {
     75    STATUS("Failed, exactly two atoms must be selected.");
    8176    return Action::failure;
    8277  }
    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
    96   std::vector<atomId_t> atomids(2);
    97   atomids[0] = atoms[0]->getId();
    98   atomids[1] = atoms[1]->getId();
    99   std::sort(atomids.begin(), atomids.end());
    100   LOG(1, "DEBUG: Selected nodes are " << atomids);
    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();
    108 
    109   // Assume the selected bond splits the molecule into two parts, each one on
    110   // either side of the bond. We need to perform a BFS from each bond partner
    111   // not using the selected bond. Therefrom, we obtain two sets of atoms/nodes.
    112   // If both are disjoint, the bond is not contained in a cycle and we simply
    113   // shift either set as desired. If not, then we simply shift each atom,
    114   // leaving the other positions untouched.
    115 
    116   // get nodes on either side of selected bond via BFS discovery
    117   BoostGraphCreator BGcreator;
    118   BGcreator.createFromMolecule(*mol,
    119       boost::bind(addEdgePredicate, _1, boost::ref(atomids)));
    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."
    133           << " Shifting only bond partners.");
    134       for(size_t j=0;j<2;++j) {
    135         bondside_sets[j].clear();
    136         bondside_sets[j].push_back( atomids[j] );
    137         const Vector &position = atoms[j]->getPosition();
    138         atoms[j]->setPosition( domain.enforceBoundaryConditions(position+Shift[j]) );
    139       }
    140       isCyclic = true;
    141     }
    142   }
    143 
    144   // go through the molecule and stretch each atom in either set of nodes
    145   if (!isCyclic) {
    146     for (molecule::iterator iter = mol->begin(); iter != mol->end(); ++iter) {
    147       const Vector &position = (*iter)->getPosition();
    148       // for each atom determine in which set of nodes it is and shift accordingly
    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 {
    155         ELOG(1, "Atom " << *iter << " is not contained on either side of bond? Undoing done shifts");
    156         // Have to undo shifts
    157         for (size_t i=0;i<2;++i) {
    158           for (BoostGraphHelpers::Nodeset_t::const_iterator iter = bondside_sets[i].begin();
    159               iter != bondside_sets[i].end(); ++iter) {
    160             atom &walker = *World::getInstance().getAtom(AtomById(*iter));
    161             const Vector &position = walker.getPosition();
    162             walker.setPosition( domain.enforceBoundaryConditions(position-Shift[i]) );
    163           }
    164         }
    165         return Action::failure;
    166       }
    167     }
    168   }
    169 
    170   MoleculeStretchBondState *UndoState = new MoleculeStretchBondState(Shift, bondside_sets, mol, params);
    171   return ActionState::ptr(UndoState);
    17278}
    17379
  • src/Graph/BoostGraphHelpers.hpp

    rf3eb6a r9f55b9  
    1616
    1717#include <vector>
     18
     19#include "types.hpp"
    1820
    1921namespace BoostGraphHelpers {
  • src/Makefile.am

    rf3eb6a r9f55b9  
    3333        Bond/bond_observable.cpp \
    3434        Bond/BondInfo.cpp \
    35         Bond/GraphEdge.cpp
     35        Bond/GraphEdge.cpp \
     36        Bond/StretchBond.cpp
    3637
    3738BONDHEADER = \
     
    3940        Bond/bond_observable.hpp \
    4041        Bond/BondInfo.hpp \
    41         Bond/GraphEdge.hpp
     42        Bond/GraphEdge.hpp \
     43        Bond/StretchBond.hpp
    4244
    4345DESCRIPTORSOURCE = \
Note: See TracChangeset for help on using the changeset viewer.