TEST(RingPerceiverTest, ethanol)
{
  Molecule molecule;
  molecule.addAtom(6);
  molecule.addAtom(6);
  molecule.addAtom(8);
  molecule.addBond(molecule.atom(0), molecule.atom(1), 1);
  molecule.addBond(molecule.atom(1), molecule.atom(2), 1);

  RingPerceiver perceiver(&molecule);
  std::vector<std::vector<size_t>> rings = perceiver.rings();
  EXPECT_EQ(rings.size(), static_cast<size_t>(0));
}
Example #2
0
TEST(CjsonTest, crystal)
{
  CjsonFormat cjson;
  Molecule molecule;
  bool success = cjson.readFile(std::string(AVOGADRO_DATA) +
                                "/data/rutile.cjson", molecule);
  EXPECT_TRUE(success);
  EXPECT_EQ(cjson.error(), "");
  EXPECT_EQ(molecule.data("name").toString(), "TiO2 rutile");
  EXPECT_EQ(molecule.atomCount(), static_cast<size_t>(6));
  EXPECT_EQ(molecule.bondCount(), static_cast<size_t>(0));

  const UnitCell *unitCell = molecule.unitCell();
  ASSERT_NE(unitCell, (UnitCell*)NULL);
  EXPECT_TRUE(std::fabs((float)unitCell->a() - 2.95812f) < 1e-5f);
  EXPECT_TRUE(std::fabs((float)unitCell->b() - 4.59373f) < 1e-5f);
  EXPECT_TRUE(std::fabs((float)unitCell->c() - 4.59373f) < 1e-5f);
  EXPECT_TRUE(std::fabs((float)unitCell->alpha() - (.5f * PI_F)) < 1e-5f);
  EXPECT_TRUE(std::fabs((float)unitCell->beta()  - (.5f * PI_F)) < 1e-5f);
  EXPECT_TRUE(std::fabs((float)unitCell->gamma() - (.5f * PI_F)) < 1e-5f);

  Atom atom = molecule.atom(5);
  EXPECT_EQ(atom.atomicNumber(), 8);
  EXPECT_TRUE(std::fabs((float)atom.position3d().x() - 1.479060f) < 1e-5f);
  EXPECT_TRUE(std::fabs((float)atom.position3d().y() - 3.699331f) < 1e-5f);
  EXPECT_TRUE(std::fabs((float)atom.position3d().z() - 0.894399f) < 1e-5f);

  std::string cjsonStr;
  cjson.writeString(cjsonStr, molecule);
  Molecule otherMolecule;
  cjson.readString(cjsonStr, otherMolecule);

  const UnitCell *otherUnitCell = otherMolecule.unitCell();
  ASSERT_NE(otherUnitCell, (UnitCell*)NULL);
  EXPECT_FLOAT_EQ((float)otherUnitCell->a(),     (float)unitCell->a());
  EXPECT_FLOAT_EQ((float)otherUnitCell->b(),     (float)unitCell->b());
  EXPECT_FLOAT_EQ((float)otherUnitCell->c(),     (float)unitCell->c());
  EXPECT_FLOAT_EQ((float)otherUnitCell->alpha(), (float)unitCell->alpha());
  EXPECT_FLOAT_EQ((float)otherUnitCell->beta(),  (float)unitCell->beta());
  EXPECT_FLOAT_EQ((float)otherUnitCell->gamma(), (float)unitCell->gamma());

  Atom otherAtom = otherMolecule.atom(5);
  EXPECT_EQ(otherAtom.atomicNumber(), atom.atomicNumber());
  EXPECT_FLOAT_EQ((float)otherAtom.position3d().x(),
                  (float)atom.position3d().x());
  EXPECT_FLOAT_EQ((float)otherAtom.position3d().y(),
                  (float)atom.position3d().y());
  EXPECT_FLOAT_EQ((float)otherAtom.position3d().z(),
                  (float)atom.position3d().z());
}
Example #3
0
   /*
   * Allocate arrays.
   */
   void G1MSD::setup() 
   {
 
      // Get number of molecules of this species in the System. 
      nMolecule_ = system().nMolecule(speciesId_);
      
      int nratoms;
      nratoms =  nMolecule_*nAtom_;
      // Allocate arrays of position Vectors and shifts
      truePositions_.allocate(nratoms); 
      oldPositions_.allocate(nratoms); 
      shifts_.allocate(nratoms); 

      // Initialize the AutoCorrArray object
      accumulator_.setParam(nratoms, capacity_);

      // Store initial positions, and set initial shift vectors.
      Vector     r;
      IntVector  zero(0);
      Molecule*  moleculePtr;
      int        iatom = 0;
      for (int i = 0; i < nMolecule_; ++i) {
	 moleculePtr = &system().molecule(speciesId_, i);
	 for (int j = 0 ; j < nAtom_; j++) {
            r = moleculePtr->atom(j).position();
            system().boundary().shift(r);
            oldPositions_[iatom] = r;
            shifts_[iatom] = zero;
	    iatom++;
	 }
      }

   }
Example #4
0
   /*
   * Initialize all Angle objects for Molecules of one Species.
   *
   * This functions assigns pointers to Atoms and angle types ids within a
   * contiguous block of Angle objects, and sets a pointer in each Molecule
   * to the first Angle in the associated block.
   */
   void Simulation::initializeSpeciesAngles(int iSpecies)
   {

      if (nAngleType_ <= 0) {
         UTIL_THROW("nAngleType must be positive");
      }

      Species*  speciesPtr = 0;
      Molecule *moleculePtr = 0;
      Angle    *anglePtr = 0;
      Atom     *firstAtomPtr, *atom0Ptr, *atom1Ptr, *atom2Ptr;
      int       iMol, iAngle, atom0Id, atom1Id, atom2Id, type;
      int       capacity, nAngle;

      speciesPtr = &species(iSpecies);
      capacity   = speciesPtr->capacity();
      nAngle     = speciesPtr->nAngle();

      // Initialize pointers before loop
      moleculePtr = &molecules_[firstMoleculeIds_[iSpecies]];
      anglePtr = &angles_[firstAngleIds_[iSpecies]];

      // Loop over molecules in Species
      for (iMol = 0; iMol < capacity; ++iMol) {

         firstAtomPtr = &(moleculePtr->atom(0));
         moleculePtr->setFirstAngle(*anglePtr);
         moleculePtr->setNAngle(nAngle);

         if (nAngle > 0) {

            // Create angles for a molecule
            for (iAngle = 0; iAngle < nAngle; ++iAngle) {

               // Get pointers to atoms spanning the angle and angle type
               atom0Id  = speciesPtr->speciesAngle(iAngle).atomId(0);
               atom1Id  = speciesPtr->speciesAngle(iAngle).atomId(1);
               atom2Id  = speciesPtr->speciesAngle(iAngle).atomId(2);
               type     = speciesPtr->speciesAngle(iAngle).typeId();
               atom0Ptr = firstAtomPtr + atom0Id;
               atom1Ptr = firstAtomPtr + atom1Id;
               atom2Ptr = firstAtomPtr + atom2Id;

               // Set fields of the Angle object
               anglePtr->setAtom(0, *atom0Ptr);
               anglePtr->setAtom(1, *atom1Ptr);
               anglePtr->setAtom(2, *atom2Ptr);
               anglePtr->setTypeId(type);

               ++anglePtr;

            }

         }

         ++moleculePtr;
      }

   }
void BallAndStick::process(const Molecule &molecule,
                           Rendering::GroupNode &node)
{
  // Add a sphere node to contain all of the spheres.
  GeometryNode *geometry = new GeometryNode;
  node.addChild(geometry);
  SphereGeometry *spheres = new SphereGeometry;
  spheres->identifier().molecule = &molecule;
  spheres->identifier().type = Rendering::AtomType;
  geometry->addDrawable(spheres);

  for (Index i = 0; i < molecule.atomCount(); ++i) {
    Core::Atom atom = molecule.atom(i);
    unsigned char atomicNumber = atom.atomicNumber();
    const unsigned char *c = Elements::color(atomicNumber);
    Vector3ub color(c[0], c[1], c[2]);
    spheres->addSphere(atom.position3d().cast<float>(), color,
                       static_cast<float>(Elements::radiusVDW(atomicNumber))
                       * 0.3f);
  }

  float bondRadius = 0.1f;
  CylinderGeometry *cylinders = new CylinderGeometry;
  cylinders->identifier().molecule = &molecule;
  cylinders->identifier().type = Rendering::BondType;
  geometry->addDrawable(cylinders);
  for (Index i = 0; i < molecule.bondCount(); ++i) {
    Core::Bond bond = molecule.bond(i);
    Vector3f pos1 = bond.atom1().position3d().cast<float>();
    Vector3f pos2 = bond.atom2().position3d().cast<float>();
    Vector3ub color1(Elements::color(bond.atom1().atomicNumber()));
    Vector3ub color2(Elements::color(bond.atom2().atomicNumber()));
    Vector3f bondVector = pos2 - pos1;
    float bondLength = bondVector.norm();
    bondVector /= bondLength;
    switch (bond.order()) {
    case 3: {
      Vector3f delta = bondVector.unitOrthogonal() * (2.0f * bondRadius);
      cylinders->addCylinder(pos1 + delta, bondVector, bondLength, bondRadius,
                             color1, color2, i);
      cylinders->addCylinder(pos1 - delta, bondVector, bondLength, bondRadius,
                             color1, color2, i);
    }
    default:
    case 1:
      cylinders->addCylinder(pos1, bondVector, bondLength, bondRadius,
                             color1, color2, i);
      break;
    case 2: {
      Vector3f delta = bondVector.unitOrthogonal() * bondRadius;
      cylinders->addCylinder(pos1 + delta, bondVector, bondLength, bondRadius,
                             color1, color2, i);
      cylinders->addCylinder(pos1 - delta, bondVector, bondLength, bondRadius,
                             color1, color2, i);
    }
    }
  }
}
static PyObject *setbonds(PyObject *self, PyObject *args) {
  int molid;
  PyObject *atomlist, *bondlist; 

  if (!PyArg_ParseTuple(args, (char *)"iO!O!:setbonds", &molid, 
                        &PyTuple_Type, &atomlist, &PyList_Type, &bondlist)) 
    return NULL;  // bad args
 
  Molecule *mol = get_vmdapp()->moleculeList->mol_from_id(molid);
  if (!mol) {
    PyErr_SetString(PyExc_ValueError, "molecule no longer exists");
    return NULL;
  }
  int num_atoms = mol->nAtoms;
  int num_selected = PyTuple_Size(atomlist);
  if (PyList_Size(bondlist) != num_selected) {
    PyErr_SetString(PyExc_ValueError, 
      (char *)"setbonds: atomlist and bondlist must have the same size");
    return NULL;
  }
  mol->force_recalc(DrawMolItem::MOL_REGEN); // many reps ignore bonds
  for (int i=0; i<num_selected; i++) {
    int id = PyInt_AsLong(PyTuple_GET_ITEM(atomlist, i));
    if (PyErr_Occurred()) {
      return NULL;
    }
    if (id < 0 || id >= num_atoms) {
      PyErr_SetString(PyExc_ValueError, (char *)"invalid atom id found");
      return NULL;
    }
    MolAtom *atom = mol->atom(id);
   
    PyObject *atomids = PyList_GET_ITEM(bondlist, i);
    if (!PyList_Check(atomids)) {
      PyErr_SetString(PyExc_TypeError, 
        (char *)"bondlist must contain lists");
      return NULL;
    }
    int numbonds = PyList_Size(atomids);
    int k=0;
    for (int j=0; j<numbonds; j++) {
      int bond = PyInt_AsLong(PyList_GET_ITEM(atomids, j));
      if (PyErr_Occurred())
        return NULL;
      if (bond >= 0 && bond < mol->nAtoms) {
        atom->bondTo[k++] = bond;
      } else {
        char buf[40];
        sprintf(buf, "Invalid atom id in bondlist: %d", bond);
        PyErr_SetString(PyExc_ValueError, buf);
        return NULL;
      }
    }
    atom->bonds = k;
  }
  Py_INCREF(Py_None);
  return Py_None;
}
Example #7
0
   /*
   * Initialize all Dihedral objects for Molecules of one Species.
   *
   * This functions assigns pointers to Atoms and Dihedral types ids within
   * a contiguous block of Dihedral objects, and sets a pointer in each 
   * Molecule to the first Dihedral in the associated block.
   */
   void Simulation::initializeSpeciesDihedrals(int iSpecies)
   {

      Species*  speciesPtr = 0;
      Molecule *moleculePtr = 0;
      Dihedral  *dihedralPtr = 0;
      Atom     *firstAtomPtr, *atom0Ptr, *atom1Ptr, *atom2Ptr, *atom3Ptr;
      int       iMol, iDihedral, atom0Id, atom1Id, atom2Id, atom3Id, type;
      int       capacity, nDihedral;

      speciesPtr = &species(iSpecies);
      capacity   = speciesPtr->capacity();
      nDihedral  = speciesPtr->nDihedral();

      // Initialize pointers before loop
      moleculePtr = &molecules_[firstMoleculeIds_[iSpecies]];
      dihedralPtr = &dihedrals_[firstDihedralIds_[iSpecies]];

      // Loop over molecules in Species
      for (iMol = 0; iMol < capacity; ++iMol) {

         firstAtomPtr = &(moleculePtr->atom(0));
         moleculePtr->setFirstDihedral(*dihedralPtr);
         moleculePtr->setNDihedral(nDihedral);

         if (nDihedral > 0) {

            // Create dihedrals for a molecule
            for (iDihedral = 0; iDihedral < nDihedral; ++iDihedral) {

               // Get local indices for atoms and dihedral type
               atom0Id  = speciesPtr->speciesDihedral(iDihedral).atomId(0);
               atom1Id  = speciesPtr->speciesDihedral(iDihedral).atomId(1);
               atom2Id  = speciesPtr->speciesDihedral(iDihedral).atomId(2);
               atom3Id  = speciesPtr->speciesDihedral(iDihedral).atomId(3);
               type     = speciesPtr->speciesDihedral(iDihedral).typeId();

               // Calculate atom pointers
               atom0Ptr = firstAtomPtr + atom0Id;
               atom1Ptr = firstAtomPtr + atom1Id;
               atom2Ptr = firstAtomPtr + atom2Id;
               atom3Ptr = firstAtomPtr + atom3Id;

               // Set fields of the Dihedral object
               dihedralPtr->setAtom(0, *atom0Ptr);
               dihedralPtr->setAtom(1, *atom1Ptr);
               dihedralPtr->setAtom(2, *atom2Ptr);
               dihedralPtr->setAtom(3, *atom3Ptr);
               dihedralPtr->setTypeId(type);

               ++dihedralPtr;
            }
         }
         ++moleculePtr;
      }

   }
Example #8
0
   /// Evaluate end-to-end vectors of all chains.
   void EndtoEndXYZ::sample(long iStep) 
   { 
      if (isAtInterval(iStep))  {

         Molecule* moleculePtr;
         Vector    r1, r2, dR;
         double    dxSq, dySq, dzSq;
         int       i, j, nMolecule;

         dxSq = 0.0;
         dySq = 0.0; 
         dzSq = 0.0; 
         nMolecule = system().nMolecule(speciesId_);
         for (i = 0; i < system().nMolecule(speciesId_); i++) {
            moleculePtr = &system().molecule(speciesId_, i);

            // Construct map of molecule with no periodic boundary conditions
            positions_[0] = moleculePtr->atom(0).position();
            for (j = 1 ; j < nAtom_; j++) {
               r1 = moleculePtr->atom(j-1).position();
               r2 = moleculePtr->atom(j).position();
               system().boundary().distanceSq(r1, r2, dR);
               positions_[j]  = positions_[j-1];
               positions_[j] += dR;
            }

            dR.subtract(positions_[0], positions_[nAtom_-1]);
            dxSq += dR[0]*dR[0];
            dySq += dR[1]*dR[1];
            dzSq += dR[2]*dR[2];    
            
     
         }
         dxSq /= double(nMolecule);
         dySq /= double(nMolecule);
         dzSq /= double(nMolecule); 
      
         accumulatorX_.sample(dxSq, outputFileX_);
         accumulatorY_.sample(dySq, outputFileY_); 
         accumulatorZ_.sample(dzSq, outputFileZ_); 

      } // if isAtInterval

   }
static PyObject *contacts(PyObject *self, PyObject *args) {
  
  int mol1, frame1, mol2, frame2;
  PyObject *selected1, *selected2;
  float cutoff;
  if (!PyArg_ParseTuple(args, (char *)"iiO!iiO!f:atomselection.contacts",
        &mol1, &frame1, &PyTuple_Type, &selected1,
        &mol2, &frame2, &PyTuple_Type, &selected2,
        &cutoff))
    return NULL;
  VMDApp *app = get_vmdapp();
  AtomSel *sel1 = sel_from_py(mol1, frame1, selected1, app);
  AtomSel *sel2 = sel_from_py(mol2, frame2, selected2, app);
  if (!sel1 || !sel2) {
    delete sel1;
    delete sel2;
    return NULL;
  }
  const float *ts1 = sel1->coordinates(app->moleculeList);
  const float *ts2 = sel2->coordinates(app->moleculeList);
  if (!ts1 || !ts2) {
    PyErr_SetString(PyExc_ValueError, "No coordinates in selection");
    delete sel1;
    delete sel2;
    return NULL;
  }
  Molecule *mol = app->moleculeList->mol_from_id(mol1);

  GridSearchPair *pairlist = vmd_gridsearch3(
      ts1, sel1->num_atoms, sel1->on,
      ts2, sel2->num_atoms, sel2->on,
      cutoff, -1, (sel1->num_atoms + sel2->num_atoms) * 27);

  delete sel1;
  delete sel2;
  GridSearchPair *p, *tmp;
  PyObject *list1 = PyList_New(0);
  PyObject *list2 = PyList_New(0);
  for (p=pairlist; p != NULL; p=tmp) {
    // throw out pairs that are already bonded
    MolAtom *a1 = mol->atom(p->ind1);
    if (mol1 != mol2 || !a1->bonded(p->ind2)) {
      PyList_Append(list1, PyInt_FromLong(p->ind1));
      PyList_Append(list2, PyInt_FromLong(p->ind2));
    }
    tmp = p->next;
    free(p);
  }
  PyObject *result = PyList_New(2);
  PyList_SET_ITEM(result, 0, list1);
  PyList_SET_ITEM(result, 1, list2);
  return result;
}
   /*
   * Evaluate Rosenbluth weight, and add to accumulator.
   */
   void McChemicalPotential::sample(long iStep)
   {
      if (isAtInterval(iStep))  {

         Species* speciesPtr;
         Molecule* molPtr;
         Molecule::BondIterator bondIter;
         Atom* endPtr;
         double w;
         double rosenbluth = 1;
         double de;
         double e = 0;

         speciesPtr = &(simulation().species(speciesId_));

         // Pop a new molecule off the species reservoir
         molPtr = &(speciesPtr->reservoir().pop());
         system().addMolecule(*molPtr);

         // Loop over molecule growth trials
         for (int i = 0; i < nMoleculeTrial_; i++) {

            // Pick a random position for the first atom
            endPtr = &molPtr->atom(0);
            boundary().randomPosition(random(), endPtr->position());

            e = system().pairPotential().atomEnergy(*endPtr);
            rosenbluth = boltzmann(e);
            system().pairPotential().addAtom(*endPtr);

            for (molPtr->begin(bondIter); bondIter.notEnd(); ++bondIter) {
                addEndAtom(&(bondIter->atom(1)), &(bondIter->atom(0)), bondIter->typeId(), w, de);
                e += de;
                rosenbluth *= w;
                system().pairPotential().addAtom(bondIter->atom(1));
            }

            rosenbluth = rosenbluth / pow(nTrial_,molPtr->nAtom()-1);
            accumulator_.sample(rosenbluth, outputFile_);

            system().pairPotential().deleteAtom(*endPtr);
            for (molPtr->begin(bondIter); bondIter.notEnd(); ++bondIter) {
                system().pairPotential().deleteAtom(bondIter->atom(1));
            }
         }

         // Return additional molecule to reservoir
         system().removeMolecule(*molPtr);
         speciesPtr->reservoir().push(*molPtr);
      }

   }
void HydrogenTools::adjustHydrogens(Molecule &molecule, Adjustment adjustment)
{
  // This vector stores indices of hydrogens that need to be removed. Additions
  // are made first, followed by removals to keep indexing sane.
  std::vector<size_t> badHIndices;

  // Temporary container for calls to generateNewHydrogenPositions.
  std::vector<Vector3> newHPos;

  // Convert the adjustment option to a couple of booleans
  bool doAdd(adjustment == Add || adjustment == AddAndRemove);
  bool doRemove(adjustment == Remove || adjustment == AddAndRemove);

  // Limit to only the original atoms:
  const size_t numAtoms = molecule.atomCount();

  // Iterate through all atoms in the molecule, adding hydrogens as needed
  // and building up a list of hydrogens that should be removed.
  for (size_t atomIndex = 0; atomIndex < numAtoms; ++atomIndex) {
    const Atom atom(molecule.atom(atomIndex));
    int hDiff = valencyAdjustment(atom);
    // Add hydrogens:
    if (doAdd && hDiff > 0) {
      newHPos.clear();
      generateNewHydrogenPositions(atom, hDiff, newHPos);
      for (std::vector<Vector3>::const_iterator it = newHPos.begin(),
           itEnd = newHPos.end(); it != itEnd; ++it) {
        Atom newH(molecule.addAtom(1));
        newH.setPosition3d(*it);
        molecule.addBond(atom, newH, 1);
      }
    }
    // Add bad hydrogens to our list of hydrogens to remove:
    else if (doRemove && hDiff < 0) {
      extraHydrogenIndices(atom, -hDiff, badHIndices);
    }
  }

  // Remove dead hydrogens now. Remove them in reverse-index order to keep
  // indexing sane.
  if (doRemove && !badHIndices.empty()) {
    std::sort(badHIndices.begin(), badHIndices.end());
    std::vector<size_t>::iterator newEnd(std::unique(badHIndices.begin(),
                                                     badHIndices.end()));
    badHIndices.resize(std::distance(badHIndices.begin(), newEnd));
    for (std::vector<size_t>::const_reverse_iterator it = badHIndices.rbegin(),
         itEnd = badHIndices.rend(); it != itEnd; ++it) {
      molecule.removeAtom(*it);
    }
  }
}
   /*
   * Evaluate end-to-end vectors of all chains, add to ensemble.
   */
   void RingRouseAutoCorr::sample(long iStep) 
   { 
      if (isAtInterval(iStep))  {

         Molecule* moleculePtr;
         Vector    r1, r2, dR, atomPos;
         int       i, j;

         // Confirm that nMolecule has remained constant
         if (nMolecule_ != system().nMolecule(speciesId_)) {
            UTIL_THROW("Number of molecules has changed.");
         }

         // Loop over molecules
         for (i=0; i < nMolecule_; i++) {
            moleculePtr = &(system().molecule(speciesId_, i));

            // Retrace non-periodic shape and calculate coefficients
            atomPos = moleculePtr->atom(0).position();
            dR.multiply(atomPos, projector_[0]);
            data_[i] = dR;
            for (j = 1; j < nAtom_; j++) {
               r1 = moleculePtr->atom(j-1).position();
               r2 = moleculePtr->atom(j).position();
               system().boundary().distanceSq(r2, r1, dR);
               atomPos += dR;
               dR.multiply(atomPos, projector_[j]);
               data_[i] += dR;
            }
         }
      
         accumulator_.sample(data_);

      } // if isAtInterval

   }
Example #13
0
TEST(CjsonTest, atoms)
{
  CjsonFormat cjson;
  Molecule molecule;
  bool success = cjson.readFile(std::string(AVOGADRO_DATA) +
                                "/data/ethane.cjson", molecule);
  EXPECT_TRUE(success);
  EXPECT_EQ(cjson.error(), "");
  EXPECT_EQ(molecule.data("name").toString(), "Ethane");
  EXPECT_EQ(molecule.atomCount(), static_cast<size_t>(8));
  Atom atom = molecule.atom(0);
  EXPECT_EQ(atom.atomicNumber(), static_cast<unsigned char>(1));
  atom = molecule.atom(1);
  EXPECT_EQ(atom.atomicNumber(), static_cast<unsigned char>(6));
  EXPECT_EQ(atom.position3d().x(),  0.751621);
  EXPECT_EQ(atom.position3d().y(), -0.022441);
  EXPECT_EQ(atom.position3d().z(), -0.020839);

  atom = molecule.atom(7);
  EXPECT_EQ(atom.atomicNumber(), static_cast<unsigned char>(1));
  EXPECT_EQ(atom.position3d().x(), -1.184988);
  EXPECT_EQ(atom.position3d().y(),  0.004424);
  EXPECT_EQ(atom.position3d().z(), -0.987522);
}
Example #14
0
TEST(RWMoleculeTest, MoleculeToRWMolecule)
{
  Molecule mol;
  typedef Molecule::AtomType Atom;
  typedef Molecule::BondType Bond;
  Atom a0 = mol.addAtom(1);
  Atom a1 = mol.addAtom(6);
  Atom a2 = mol.addAtom(9);
  Bond b0 = mol.addBond(a0, a2);
  a1.setPosition3d(Vector3(0, 6, 9));
  b0.setOrder(3);

  RWMolecule rwmol(mol, 0);
  EXPECT_EQ(rwmol.atomCount(), mol.atomCount());
  EXPECT_EQ(rwmol.bondCount(), mol.bondCount());
  EXPECT_EQ(rwmol.atom(2).atomicNumber(), mol.atom(2).atomicNumber());
  EXPECT_EQ(rwmol.bond(0).order(), mol.bond(0).order());
}
Example #15
0
   /*
   * Evaluate end-to-end vectors of all chains, add to ensemble.
   */
   void G1MSD::sample(long iStep) 
   { 
      if (!isAtInterval(iStep)) return;

      // Confirm that nMolecule has remained constant, and nMolecule > 0.
      if (nMolecule_ <= 0) {
         UTIL_THROW("nMolecule <= 0");
      }
      if (nMolecule_ != system().nMolecule(speciesId_)) {
         UTIL_THROW("Number of molecules has changed.");
      }

      Vector     r;
      IntVector  shift;
      Molecule*  moleculePtr;
      Vector     lengths = system().boundary().lengths();
      int        i, j, k;
      int        iatom = 0;
      for (i = 0; i < nMolecule_; ++i) {
	 moleculePtr = &system().molecule(speciesId_, i);
	 for (j = 0 ; j < nAtom_; j++) {	 
            r = moleculePtr->atom(j).position();
            system().boundary().shift(r);

            // Compare current r to previous position, oldPositions_[iatom]
            system().boundary().distanceSq(r, oldPositions_[iatom], shift);

            // If this atom crossed a boundary, increment its shift vector
            shifts_[iatom] += shift;

            // Reconstruct true position
            for (k = 0; k < Dimension; ++k) {
               truePositions_[iatom][k] = r[k] + shifts_[iatom][k]*lengths[k];
            }

            // Store current position in box for comparison to next one
            oldPositions_[iatom] = r;
	    
	    iatom++;
	 }
      }
      accumulator_.sample(truePositions_);

   }
static PyObject *getbonds(PyObject *self, PyObject *args) {
  int molid;
  PyObject *atomlist;
   
  if (!PyArg_ParseTuple(args, (char *)"iO!:getbonds", &molid, 
                        &PyTuple_Type, &atomlist)) 
    return NULL;  // bad args
 
  Molecule *mol = get_vmdapp()->moleculeList->mol_from_id(molid);
  if (!mol) {
    PyErr_SetString(PyExc_ValueError, "molecule no longer exists");
    return NULL;
  }
  int num_atoms = mol->nAtoms;
  int num_selected = PyTuple_Size(atomlist);
  PyObject *newlist = PyList_New(num_selected);
  for (int i=0; i< num_selected; i++) {
    int id = PyInt_AsLong(PyTuple_GET_ITEM(atomlist, i));
    if (PyErr_Occurred()) {
      Py_DECREF(newlist);
      return NULL;
    }
    if (id < 0 || id >= num_atoms) {
      PyErr_SetString(PyExc_ValueError, (char *)"invalid atom id found");
      Py_DECREF(newlist);
      return NULL;
    }
    const MolAtom *atom = mol->atom(id);
    PyObject *bondlist = PyList_New(atom->bonds);
    for (int j=0; j<atom->bonds; j++) {
      PyList_SET_ITEM(bondlist, j, PyInt_FromLong(atom->bondTo[j]));
    }
    PyList_SET_ITEM(newlist, i, bondlist);
  }
  return newlist;
}
TEST(RingPerceiverTest, benzene)
{
  Molecule molecule;
  molecule.addAtom(6);
  molecule.addAtom(6);
  molecule.addAtom(6);
  molecule.addAtom(6);
  molecule.addAtom(6);
  molecule.addAtom(6);
  molecule.addBond(molecule.atom(0), molecule.atom(1), 1);
  molecule.addBond(molecule.atom(1), molecule.atom(2), 2);
  molecule.addBond(molecule.atom(2), molecule.atom(3), 1);
  molecule.addBond(molecule.atom(3), molecule.atom(4), 2);
  molecule.addBond(molecule.atom(4), molecule.atom(5), 1);
  molecule.addBond(molecule.atom(5), molecule.atom(0), 2);

  RingPerceiver perceiver(&molecule);
  std::vector<std::vector<size_t>> rings = perceiver.rings();
  EXPECT_EQ(rings.size(), static_cast<size_t>(1));
  EXPECT_EQ(rings[0].size(), static_cast<size_t>(6));
}
   /* 
   * Generate, attempt and accept or reject a Monte Carlo move.
   *
   * A complete move involve the following stepts:
   *
   *    1) choose a molecule-i randomly;
   *    2) find molecule-j of the same type as i, and monomer pairs satisfying
   *       the distance criterion exist;
   *    3) Delete the two rebridging monomers; first molecule-i, then -j.
   *    4) Rebuild molecule-j, then -i. (in the JCP paper, the order is chosen
   *       at random.)
   *
   */
   bool CfbDoubleRebridgeMove::move() 
   {
      bool      found, accept;
      int       iMol, jMol, sign, beginId, nEnd, i;
      Molecule *iPtr;     // pointer to i-th molecule
      Molecule *jPtr;     // pointer to j-th molecule
      int      *bonds;    // bond types of a consequtive blocks of atoms
      Atom     *thisPtr;  // pointer to the current end atom
      Atom     *tempPtr;  // pointer used for swap atom positions
      double    rosenbluth, rosen_r,  rosen_f;
      double    energy, energy_r, energy_f;
      double    po2n, pn2o;
      Vector    swapPos;

      incrementNAttempt();

      // Choose a random direction
      if (random().uniform(0.0, 1.0) > 0.5)
         sign = +1;
      else
         sign = -1;

      // Search for a pair of candidate sites and calculate probability 
      found = forwardScan(sign, iMol, jMol, beginId, po2n);
      if (!found) return found;

      iPtr = &(system().molecule(speciesId_, iMol));
      jPtr = &(system().molecule(speciesId_, jMol));

      // Save positions for atoms to be regrown
      thisPtr = &(iPtr->atom(beginId));
      tempPtr = &(jPtr->atom(beginId));
      for (i = 0; i < nRegrow_; ++i) {
         iOldPos_[i] = thisPtr->position();
         jOldPos_[i] = tempPtr->position();

         thisPtr += sign;
         tempPtr += sign;
      }

      // Prepare for the rebridge move
      accept = false;

      bonds = new int[nRegrow_ + 1];
      if (sign == +1) {
         for (i = 0; i < nRegrow_ + 1; ++i)
            bonds[i] = iPtr->bond(beginId - 1 + nRegrow_ - i).typeId();
      } else {
         for (i = 0; i < nRegrow_ + 1; ++i)
            bonds[i] = iPtr->bond(beginId - nRegrow_ + i).typeId();
      }

      // Deleting atoms: first i-th molecule, then j-th
      rosen_r = 1.0;
      energy_r = 0.0;

      thisPtr = &(iPtr->atom(beginId + (nRegrow_-1)*sign));
      deleteSequence(nRegrow_, sign, thisPtr, bonds, rosenbluth, energy);
      rosen_r *= rosenbluth;
      energy_r += energy;

      thisPtr = &(jPtr->atom(beginId + (nRegrow_-1)*sign));
      deleteSequence(nRegrow_, sign, thisPtr, bonds, rosenbluth, energy);
      rosen_r *= rosenbluth;
      energy_r += energy;

      // Swap the atom positions of the dangling end
      if (sign == +1)
         nEnd = iPtr->nAtom() - beginId - nRegrow_;
      else
         nEnd = beginId + 1 - nRegrow_;

      thisPtr = &(iPtr->atom(beginId + nRegrow_*sign));
      tempPtr = &(jPtr->atom(beginId + nRegrow_*sign));
      for (i = 0; i < nEnd; ++i) {
         swapPos = thisPtr->position();
         //system().moveAtom(*thisPtr, tempPtr->position());
         thisPtr->position() = tempPtr->position();
         #ifndef INTER_NOPAIR
         system().pairPotential().updateAtomCell(*thisPtr);
         #endif
         //system().moveAtom(*tempPtr, swapPos);
         tempPtr->position() = swapPos;
         #ifndef INTER_NOPAIR
         system().pairPotential().updateAtomCell(*tempPtr);
         #endif

         thisPtr += sign;
         tempPtr += sign;
      }

      // Regrow atoms: first j-th molecule, then i-th
      rosen_f = 1.0;
      energy_f = 0.0;

      thisPtr = &(jPtr->atom(beginId));
      addSequence(nRegrow_, sign, thisPtr, bonds, rosenbluth, energy);
      rosen_f *= rosenbluth;
      energy_f += energy;

      thisPtr = &(iPtr->atom(beginId));
      addSequence(nRegrow_, sign, thisPtr, bonds, rosenbluth, energy);
      rosen_f *= rosenbluth;
      energy_f += energy;

      // Reverse scan
      found = reverseScan(sign, iMol, jMol, beginId - sign, pn2o);

      // Decide whether to accept or reject
      if (found)
         accept = random().metropolis(rosen_f * pn2o / rosen_r / po2n);
      else
         accept = false;

      if (accept) {

         // Increment counter for accepted moves of this class.
         incrementNAccept();

      } else {

         // If the move is rejected, restore nRegrow_ positions
         thisPtr = &(iPtr->atom(beginId));
         tempPtr = &(jPtr->atom(beginId));
         for (i = 0; i < nRegrow_; ++i) {
            //system().moveAtom(*thisPtr, iOldPos_[i]);
            thisPtr->position() = iOldPos_[i];
            #ifndef INTER_NOPAIR
            system().pairPotential().updateAtomCell(*thisPtr);
            #endif
            //system().moveAtom(*tempPtr, jOldPos_[i]);
            tempPtr->position() = jOldPos_[i];
            #ifndef INTER_NOPAIR
            system().pairPotential().updateAtomCell(*tempPtr);
            #endif

            thisPtr += sign;
            tempPtr += sign;
         }

         // Restore atom positions at the dangling end
         thisPtr = &(iPtr->atom(beginId + nRegrow_*sign));
         tempPtr = &(jPtr->atom(beginId + nRegrow_*sign));
         for (i = 0; i < nEnd; ++i) {
            swapPos = thisPtr->position();
            //system().moveAtom(*thisPtr, tempPtr->position());
            thisPtr->position() = tempPtr->position();
            #ifndef INTER_NOPAIR
            system().pairPotential().updateAtomCell(*thisPtr);
            #endif
            //system().moveAtom(*tempPtr, swapPos);
            tempPtr->position() = swapPos;
            #ifndef INTER_NOPAIR
            system().pairPotential().updateAtomCell(*tempPtr);
            #endif

            thisPtr += sign;
            tempPtr += sign;
         }

      }

      // Release memory
      delete [] bonds;

      return accept;
   }
   /* 
   * Generate, attempt and accept or reject a Monte Carlo move.
   */
   bool EndSwapMove::move() 
   {
      double newEnergy, oldEnergy;
      Molecule* molPtr;
      Atom* atomPtr;
      int i, nAtom;

      incrementNAttempt();

      molPtr = &(system().randomMolecule(speciesId_));
      nAtom  = molPtr->nAtom();

      // Calculate old molecule energy = pair + external 
      oldEnergy = 0.0;
      #ifndef INTER_NOPAIR 
      oldEnergy += system().pairPotential().moleculeEnergy(*molPtr);
      #endif
      #ifdef INTER_EXTERNAL
      for (i = 0; i < nAtom; ++i) {
         atomPtr = &molPtr->atom(i);
         oldEnergy += system().externalPotential().atomEnergy(*atomPtr);
      }
      #endif

      // Reverse sequence of atom types
      for (i = 0; i < nAtom; ++i) {
         assert(molPtr->atom(i).typeId() == atomTypeIds_[i]);
         molPtr->atom(i).setTypeId(atomTypeIds_[nAtom - 1 - i]);   
      }

      // Calculate new energy (with reversed sequence of atom types).
      newEnergy = 0.0;
      #ifndef INTER_NOPAIR 
      newEnergy += system().pairPotential().moleculeEnergy(*molPtr);
      #endif
      #ifdef INTER_EXTERNAL
      for (i = 0; i < nAtom; ++i) {
         molPtr->atom(i).setTypeId(atomTypeIds_[nAtom - 1 - i]);   
         atomPtr = &molPtr->atom(i);
         newEnergy += system().externalPotential().atomEnergy(*atomPtr);
      }
      #endif

      // Restore original sequence of atom type Ids
      for (i = 0; i < nAtom; ++i) {
         molPtr->atom(i).setTypeId(atomTypeIds_[i]);   
      }
   
      // Decide whether to accept or reject
      bool accept = random().metropolis(boltzmann(newEnergy-oldEnergy));
 
      if (accept) {

         // Store all atomic positions
         for (i = 0; i < nAtom; ++i) {
            positions_[i] = molPtr->atom(i).position();
         }

         // Reverse sequence of atomic positions 
         for (i = 0; i < nAtom; ++i) {
            atomPtr = &molPtr->atom(i);
            atomPtr->position() = positions_[nAtom - 1 - i];
            #ifndef INTER_NOPAIR
            system().pairPotential().updateAtomCell(*atomPtr);
            #endif
         }

         incrementNAccept();

      }

      return accept;
   }
Example #20
0
   /* 
   * Generate, attempt and accept or reject a Monte Carlo move.
   *
   * Convention for index
   *       head of molecule                tail of molecule
   *          |                                   |
   *          0   1   2   3 ...                length-1
   *          o---o---o---o---o---o---o---o---o---o
   *              |_______________|___________|
   *                valid beginId    nRegrow
   *
   */
   bool CfbRebridgeMove::move() 
   {
      Molecule *molPtr;   // pointer to randomly chosen molecule
      Atom     *thisPtr;  // pointer to the current end atom
      int       length, sign, beginId, endId, i;
      int       *bonds;
      double    rosen_r,  rosen_f;
      double    energy_r, energy_f;
      bool      accept;

      incrementNAttempt();

      // Choose a molecule at random
      molPtr = &(system().randomMolecule(speciesId_));
      length = molPtr->nAtom();

      // Require that chain length - 2 >= nRegrow_
      if (nRegrow_ > length - 2) {
         UTIL_THROW("nRegrow_  >= chain length");
      }

      // Allocate bonds array
      bonds = new int[nRegrow_ + 1];

      // Choose the beginId of the growing interior bridge
      beginId = random().uniformInt(1, length - nRegrow_);

      // Choose direction: sign = +1 if beginId < endId
      if (random().uniform(0.0, 1.0) > 0.5) {
         sign = +1;
         endId = beginId + (nRegrow_ - 1);
      } else {
         sign = -1;
         endId   = beginId;
         beginId = endId + (nRegrow_ - 1);
      }

      // Store current atomic positions from segment to be regrown
      thisPtr = &(molPtr->atom(beginId));
      for (i = 0; i < nRegrow_; ++i) {
         oldPos_[i] = thisPtr->position();
         thisPtr += sign;
      }

      // Get bond types.
      if (sign == +1) {
         for (i = 0; i < nRegrow_ + 1; ++i)
            bonds[i] = molPtr->bond(endId - i).typeId();
      } else {
         for (i = 0; i < nRegrow_ + 1; ++i)
            bonds[i] = molPtr->bond(endId - 1 + i).typeId();
      }

      // Delete atoms: endId -> beginId
      thisPtr = &(molPtr->atom(endId));
      deleteSequence(nRegrow_, sign, thisPtr, bonds, rosen_r, energy_r);

      // Regrow atoms: endId -> beginId
      thisPtr = &(molPtr->atom(beginId));
      addSequence(nRegrow_, sign, thisPtr, bonds, rosen_f, energy_f);

      // Release bonds array
      delete [] bonds;

      // Decide whether to accept or reject
      accept = random().metropolis(rosen_f/rosen_r);
      if (accept) {

         // Increment counter for accepted moves of this class.
         incrementNAccept();

         // If the move is accepted, keep current positions.

      } else {

         // If the move is rejected, restore old positions
         thisPtr = &(molPtr->atom(beginId));
         for (i = 0; i < nRegrow_; ++i) {
            //system().moveAtom(*thisPtr, oldPos_[i]);
            thisPtr->position() = oldPos_[i];
            #ifndef INTER_NOPAIR
            system().pairPotential().updateAtomCell(*thisPtr);
            #endif
            thisPtr += sign;
         }
   
      }

      return accept;
   }
Example #21
0
   /**
   * Recursive function to try to place an atom.
   */
   bool Linear::tryPlaceAtom(Molecule& molecule, int atomId,
      DArray<double> exclusionRadius, System& system, CellList &cellList,
      BondPotential *bondPotentialPtr, const Boundary &boundary)
   {
      Atom& lastAtom = molecule.atom(atomId);
      Atom& thisAtom = molecule.atom(++atomId);
      Random& random = system.simulation().random();

      bool hasBeenPlaced = false;

      for (int iAttempt = 0; iAttempt < maxPlacementAttempts_; iAttempt++)
      {
         // draw a random bond vector
         int beta = 1;
         Vector v;
         random.unitVector(v);
         v *= bondPotentialPtr->randomBondLength(&random, beta,
            calculateBondTypeId(lastAtom.indexInMolecule()));

         Vector newPos;
         newPos = lastAtom.position();
         newPos += v;
         // shift into simulation cell
         boundary.shift(newPos);

         // check if the atom can be placed at the new position
         CellList::NeighborArray neighbors;
         cellList.getNeighbors(newPos, neighbors);
         int nNeighbor = neighbors.size();
         bool canBePlaced = true;
         for (int j = 0; j < nNeighbor; ++j) {
            Atom *jAtomPtr = neighbors[j];
         
            double r = sqrt(boundary.distanceSq(
               jAtomPtr->position(), newPos));
            if (r < (exclusionRadius[thisAtom.typeId()] +
               exclusionRadius[jAtomPtr->typeId()])) {
               canBePlaced = false;
               break;
            }
         } 
         if (canBePlaced) {
            // place the particle
            thisAtom.position() = newPos;

            // add to cell list
            cellList.addAtom(thisAtom);

            // are we add the end of the chain?
            if (atomId == molecule.nAtom()-1) 
              return true;
            
            // recursion step
            if (! tryPlaceAtom(molecule, atomId, exclusionRadius, system,
               cellList, bondPotentialPtr, boundary) ) {
               // If the next monomer cannot be inserted, delete this monomer
               // again
               cellList.deleteAtom(thisAtom);
            } else {
               hasBeenPlaced = true;
               break;
            }
         } 
      }

      return hasBeenPlaced;
   }
   /* 
   * Generate, attempt and accept or reject a Monte Carlo move.
   */
   bool CfbHomoReptationMove::move() 
   {
      Vector    oldPos, newPos;
      double    rosen_r,  rosen_f;
      double    energy_r, energy_f;
      Atom     *tailPtr; // pointer to the tail atom (to be removed)
      Atom     *atomPtr; // resetable atom pointer
      Molecule *molPtr;  // pointer to randomly chosen molecule
      int       length, sign, headId, tailId, bondType, i;
      bool      accept;
     
      incrementNAttempt();

      // Choose a molecule at random
      molPtr = &(system().randomMolecule(speciesId_));
      length = molPtr->nAtom();

      // Choose which chain end to regrow
      if (random().uniform(0.0, 1.0) > 0.5) {
         sign = +1;
         headId = length - 1;
         tailId = 0;
      } else {
         sign = -1;
         headId = 0;
         tailId = length - 1;
      }

      // Store current positions of tail
      oldPos = molPtr->atom(tailId).position();
   
      // Delete tail monomers
      tailPtr = &(molPtr->atom(tailId));
      atomPtr = tailPtr + sign;
      if (sign == 1) {
         bondType = molPtr->bond(0).typeId();
      } else {
         bondType = molPtr->bond(length-2).typeId();
      }
      deleteEndAtom(tailPtr, atomPtr, bondType, rosen_r, energy_r);

      #ifndef INTER_NOPAIR
      // Delete from McSystem cell list
      system().pairPotential().deleteAtom(*tailPtr);
      #endif
   
      // Regrow head, using tailPtr to store properties of the new head.
      atomPtr = &(molPtr->atom(headId));
      tailPtr->setTypeId(atomPtr->typeId());
      tailPtr->mask().clear();
      #ifndef MCMD_NOMASKBONDED
      tailPtr->mask().append(*atomPtr);
      #endif
      if (sign == 1) {
         bondType = molPtr->bond(length-2).typeId();
      } else {
         bondType = molPtr->bond(0).typeId();
      }
      addEndAtom(tailPtr, atomPtr, bondType, rosen_f, energy_f);

      // Restore original type and connectivity of tail Atom
      atomPtr = tailPtr + sign;
      tailPtr->setTypeId(atomPtr->typeId());
      tailPtr->mask().clear();
      #ifndef MCMD_NOMASKBONDED
      tailPtr->mask().append(*atomPtr);
      #endif

      // Decide whether to accept or reject
      accept = random().metropolis(rosen_f/rosen_r);
      if (accept) {

         // Increment nAccept, the number accepted moves.
         incrementNAccept();

         // Store new head position
         newPos = tailPtr->position();
   
         tailPtr->position() = atomPtr->position();

         #ifndef INTER_NOPAIR
         // Add back to system cell list
         system().pairPotential().addAtom(*tailPtr);
         #endif
   
         // Shift atom positions towards the head
         for (i=1; i < length - 1; ++i) {
            //system().moveAtom(*atomPtr, (atomPtr+sign)->position());
            atomPtr->position() = (atomPtr+sign)->position();
            #ifndef INTER_NOPAIR
            system().pairPotential().updateAtomCell(*atomPtr);
            #endif
            atomPtr += sign;
         }
   
         // Move head atom to new chosen position
         //system().moveAtom(*atomPtr, newPos);
         atomPtr->position() = newPos;
         #ifndef INTER_NOPAIR
         system().pairPotential().updateAtomCell(*atomPtr);
         #endif

      } else {

         // Restore old position of tail
         tailPtr->position() = oldPos;

         #ifndef INTER_NOPAIR
         // Add tail back to System cell list.
         system().pairPotential().addAtom(*tailPtr);
         #endif
   
      }

      return accept;
   
   }
Example #23
0
   /*
   * Initialize all Bond objects for Molecules of one Species. (private)
   *
   * This functions assigns pointers to Atoms and bond types ids within a
   * contiguous block of Bond objects, and sets a pointer in each Molecule
   * to the first Bond in the associated block.
   */
   void Simulation::initializeSpeciesBonds(int iSpecies)
   {
      if (nBondType_ <= 0) {
         UTIL_THROW("nBondType_ must be positive");
      }

      Species*  speciesPtr = 0;
      Molecule* moleculePtr = 0;
      Bond*     bondPtr = 0;
      Atom*     firstAtomPtr;
      Atom*     atom0Ptr;
      Atom*     atom1Ptr;
      int       iMol, iBond, atom0Id, atom1Id, type;
      int       capacity, nBond;

      speciesPtr = &species(iSpecies);
      nBond      = speciesPtr->nBond();
      capacity   = speciesPtr->capacity();

      // Initialize pointers before loop
      moleculePtr = &molecules_[firstMoleculeIds_[iSpecies]];
      bondPtr = &bonds_[firstBondIds_[iSpecies]];

      // Loop over molecules in Species
      for (iMol = 0; iMol < capacity; ++iMol) {

         firstAtomPtr = &(moleculePtr->atom(0));
         moleculePtr->setFirstBond(*bondPtr);
         moleculePtr->setNBond(nBond);

         if (nBond > 0) {

            // Create bonds for a molecule
            for (iBond = 0; iBond < nBond; ++iBond) {

               // Get pointers to bonded atoms and bond type
               atom0Id  = speciesPtr->speciesBond(iBond).atomId(0);
               atom1Id  = speciesPtr->speciesBond(iBond).atomId(1);
               type     = speciesPtr->speciesBond(iBond).typeId();
               atom0Ptr = firstAtomPtr + atom0Id;
               atom1Ptr = firstAtomPtr + atom1Id;

               // Set fields of the Bond object
               bondPtr->setAtom(0, *atom0Ptr);
               bondPtr->setAtom(1, *atom1Ptr);
               bondPtr->setTypeId(type);

               // If MaskBonded, add each bonded atom to its partners Mask
               if (maskedPairPolicy_ == MaskBonded) {
                  atom0Ptr->mask().append(*atom1Ptr);
                  atom1Ptr->mask().append(*atom0Ptr);
               }

               ++bondPtr;
            }

         }
         ++moleculePtr;
      }

   }
Example #24
0
// Calculate total intramolecular forces
void DUQ::intramolecularForces(ProcessPool& procPool, Configuration* cfg, double* fx, double* fy, double* fz)
{
	/*
	 * Calculate the total intramolecular forces within the system, arising from Bond, Angle, and Torsion
	 * terms in all molecules.
	 * 
	 * This is a parallel routine.
	 */

	double distance, angle, force, dp, magji, magjk;
	int index, start, stride;
	Atom* i, *j, *k;
	Vec3<double> vecji, vecjk, forcei, forcek;

	// Set start/skip for parallel loop
	start = procPool.interleavedLoopStart(ProcessPool::OverPoolProcesses);
	stride = procPool.interleavedLoopStride(ProcessPool::OverPoolProcesses);

	// Main loop over molecules
	for (Molecule* mol = cfg->molecules(); mol != NULL; mol = mol->next)
	{
		// Bonds
		for (SpeciesBond* b = mol->species()->bonds(); b != NULL; b = b->next)
		{
			// Grab pointers to atoms involved in bond
			i = mol->atom(b->indexI());
			j = mol->atom(b->indexJ());

			// Determine whether we need to apply minimum image to the vector calculation
			if (cfg->useMim(i->grain()->cell(), j->grain()->cell())) vecji = cfg->box()->minimumVector(i, j);
			else vecji = j->r() - i->r();
			
			// Get distance and normalise vector ready for force calculation
			distance = vecji.magAndNormalise();

			// Determine final forces
			vecji *= b->force(distance);

			// Calculate forces
			index = b->i()->index();
			fx[index] -= vecji.x;
			fy[index] -= vecji.y;
			fz[index] -= vecji.z;
			index = b->j()->index();
			fx[index] += vecji.x;
			fy[index] += vecji.y;
			fz[index] += vecji.z;
		}

		// Angles
		for (SpeciesAngle* a = mol->species()->angles(); a != NULL; a = a->next)
		{
			// Grab pointers to atoms involved in angle
			i = mol->atom(a->indexI());
			j = mol->atom(a->indexJ());
			k = mol->atom(a->indexK());

			// Determine whether we need to apply minimum image between 'j-i' and 'j-k'
			if (cfg->useMim(j->grain()->cell(), i->grain()->cell())) vecji = cfg->box()->minimumVector(j, i);
			else vecji = i->r() - j->r();
			if (cfg->useMim(j->grain()->cell(), k->grain()->cell())) vecjk = cfg->box()->minimumVector(j, k);
			else vecjk = k->r() - j->r();
			
			// Calculate angle
			magji = vecji.magAndNormalise();
			magjk = vecjk.magAndNormalise();
			angle = Box::angle(vecji, vecjk, dp);

			// Determine Angle force vectors for atoms
			force = a->force(angle);
			forcei = vecjk - vecji * dp;
			forcei *= force / magji;
			forcek = vecji - vecjk * dp;
			forcek *= force / magjk;
			
			// Store forces
			index = a->i()->index();
			fx[index] += forcei.x;
			fy[index] += forcei.y;
			fz[index] += forcei.z;
			index = a->j()->index();
			fx[index] -= forcei.x + forcek.x;
			fy[index] -= forcei.y + forcek.y;
			fz[index] -= forcei.z + forcek.z;
			index = a->k()->index();
			fx[index] += forcek.x;
			fy[index] += forcek.y;
			fz[index] += forcek.z;
		}

	}
}
Example #25
0
   // Create or destroy the slip-springs.
   bool SliplinkerAll::move() 
   {
     System::MoleculeIterator molIter;
     Molecule::AtomIterator   atomIter;
     Atom                    *atom0Ptr, *atom1Ptr;
     Atom*                    atomPtr;
     Molecule                *mol0Ptr, *mol1Ptr;
     Molecule*                molIPtr;
     double                   prob, dRSq, mindRSq=cutoff_*cutoff_, rnd, norm;
     int                      i, ntrials, j, nNeighbor, idLink, iAtom, id1, id0;
     int                      iAtom0, iAtom1, iMolecule0, iMolecule1, n0;
     Link*                    linkPtr;
     static const int         maxNeighbor = CellList::MaxNeighbor;
     double                   cdf[maxNeighbor], energy, sum;
     int                      idneighbors[maxNeighbor];

     
     ntrials = 2 * system().simulation().atomCapacity();
     for (i=0; i < ntrials; ++i){   
       
       //Choose to create or destroy a link with prob 0.5
       if (random().uniform(0.0, 1.0) > 0.5){         
	  // Try to create a link. 
	  incrementNAttempt();		
	  // Choose a molecule and atom at random
	  molIPtr  = &(system().randomMolecule(speciesId_));
	  iMolecule0 = system().moleculeId(*molIPtr);
	  iAtom   = random().uniformInt(0, molIPtr->nAtom());
	  atomPtr = &molIPtr->atom(iAtom);
	  id0 = atomPtr->id();
	  
	  // Get array of neighbors
	  system().pairPotential().cellList().getNeighbors(atomPtr->position(), neighbors_);
	  nNeighbor = neighbors_.size();
	    
	  n0 = 0;
	  sum = 0;
	  // Loop over neighboring atoms
	  for (j = 0; j < nNeighbor; ++j) {
	    atom1Ptr = neighbors_[j];
	    mol1Ptr = &atom1Ptr->molecule();
	    iMolecule1 = system().moleculeId(*mol1Ptr);	
	    id1 = atom1Ptr->id();
	    
            // Check if atoms are the same
            if (id0 != id1){	    	    
	      // Exclude masked pairs	    
	      if (!atomPtr->mask().isMasked(*atom1Ptr)) {
		// Identify possible partners and calculate the cumulative distribution function
		dRSq = system().boundary().distanceSq(atomPtr->position(), atom1Ptr->position());
		if (dRSq <= mindRSq) {
		  energy = system().linkPotential().energy(dRSq, 0);
		  //energy = 0.5*dRSq;
		  sum = sum + boltzmann(energy);
		  cdf[n0] = sum;
		  idneighbors[n0] = j;
		  n0++;
		}    
	      }
	    }
	  }   
	    
	  // If at least 1 candidate has been found.  
	  if (n0 > 0) {
	    // Choose a partner with probability cdf[j]/cdf[n0-1]
	    j = 0;
	    rnd = random().uniform(0.0, 1.0);
	    norm = 1.0/cdf[n0-1];
	    while (rnd > cdf[j]*norm ){
	      j = j + 1;
	    }     
	    atom1Ptr = neighbors_[idneighbors[j]];	  	  
	    // Create a slip-link between the selected atoms with probability = prob
	    prob = 2.0 * (system().linkMaster().nLink() + 1.0);
	    prob = system().simulation().atomCapacity() * boltzmann(-mu_) * cdf[n0-1]/ prob ;
	    //prob = 2.0 * system().nMolecule(speciesId_) * boltzmann(-mu_) * cdf[n0-1]/ prob ;	      
	    if (system().simulation().random().uniform(0.0, 1.0) < prob) {        
	      system().linkMaster().addLink(*atomPtr, *atom1Ptr, 0); 
	      incrementNAccept();	    
	    }      
	  }    
       }
       else {
	  // Try to destroy a link
	  incrementNAttempt();
	  // Choose a link at random
	  if (system().linkMaster().nLink() > 0){
	    idLink = random().uniformInt(0, system().linkMaster().nLink());
	    // Indentify the atoms for this link.
	    linkPtr = &(system().linkMaster().link(idLink));
	    atom0Ptr = &(linkPtr->atom0());
	    mol0Ptr = &atom0Ptr->molecule();
	    iMolecule0 = system().moleculeId(*mol0Ptr);
	    iAtom0 = atom0Ptr->indexInMolecule();	    
	    atom1Ptr = &(linkPtr->atom1());
	    mol1Ptr = &atom1Ptr->molecule();
	    iMolecule1 = system().moleculeId(*mol1Ptr);
	    iAtom1 = atom1Ptr->indexInMolecule();
	    // try to delete the slip-spring	
	    dRSq = system().boundary().distanceSq(atom0Ptr->position(), atom1Ptr->position());
	    // try to delete the link if the bond is smaller than the cutoff
	    if (dRSq <= mindRSq) {    
	      // Get array of neighbors
	      system().pairPotential().cellList().getNeighbors(atom0Ptr->position(), neighbors_);
	      nNeighbor = neighbors_.size();
	      id0 = atom0Ptr->id();
	      n0 = 0;
	      sum = 0;
	      // Loop over neighboring atoms
	      for (j = 0; j < nNeighbor; ++j) {
		atom1Ptr = neighbors_[j];
		mol1Ptr = &atom1Ptr->molecule();
		iMolecule1 = system().moleculeId(*mol1Ptr);
	        id1 = atom1Ptr->id();
	    
                // Check if atoms are the same
                if (id0 != id1){	    					
		  // Exclude masked pairs	    
		  if (!atom0Ptr->mask().isMasked(*atom1Ptr)) {
		    // Identify possible partners and calculate the cumulative distribution function
		    dRSq = system().boundary().distanceSq(atom0Ptr->position(), atom1Ptr->position());
		    if (dRSq <= mindRSq) {
		      energy = system().linkPotential().energy(dRSq, 0);
		      //energy = 0.5*dRSq;
		      sum = sum + boltzmann(energy);
		      cdf[n0] = sum;
		      idneighbors[n0] = j;
		      n0++;
		    }    
		  }
	        }
	      }    
	      // Destroy the slip-link between the selected atoms with probability = prob	  
	      //prob = 2.0 * system().nMolecule(speciesId_) * boltzmann(-mu_) * cdf[n0-1];	
	      prob = system().simulation().atomCapacity() * boltzmann(-mu_) * cdf[n0-1];	    
	      prob = 2.0 * system().linkMaster().nLink() / prob; 	            
	      if (system().simulation().random().uniform(0.0, 1.0) < prob) {        
		system().linkMaster().removeLink(idLink); 
		incrementNAccept();  
	      }  
	    }
          }
       }
     }
     return true;
   }
Example #26
0
static PyObject *contacts(PyObject *self, PyObject *args) {
  
  int mol1, frame1, mol2, frame2;
  PyObject *selected1, *selected2;
  float cutoff;
  if (!PyArg_ParseTuple(args, (char *)"iiO!iiO!f:atomselection.contacts",
        &mol1, &frame1, &PyTuple_Type, &selected1,
        &mol2, &frame2, &PyTuple_Type, &selected2,
        &cutoff))
    return NULL;
  VMDApp *app = get_vmdapp();
  AtomSel *sel1 = sel_from_py(mol1, frame1, selected1, app);
  AtomSel *sel2 = sel_from_py(mol2, frame2, selected2, app);
  if (!sel1 || !sel2) {
    delete sel1;
    delete sel2;
    return NULL;
  }
  const float *ts1 = sel1->coordinates(app->moleculeList);
  const float *ts2 = sel2->coordinates(app->moleculeList);
  if (!ts1 || !ts2) {
    PyErr_SetString(PyExc_ValueError, "No coordinates in selection");
    delete sel1;
    delete sel2;
    return NULL;
  }
  Molecule *mol = app->moleculeList->mol_from_id(mol1);

  GridSearchPair *pairlist = vmd_gridsearch3(
      ts1, sel1->num_atoms, sel1->on,
      ts2, sel2->num_atoms, sel2->on,
      cutoff, -1, (sel1->num_atoms + sel2->num_atoms) * 27);

  delete sel1;
  delete sel2;
  GridSearchPair *p, *tmp;
  PyObject *list1 = PyList_New(0);
  PyObject *list2 = PyList_New(0);
  PyObject *tmp1;
  PyObject *tmp2;
  for (p=pairlist; p != NULL; p=tmp) {
    // throw out pairs that are already bonded
    MolAtom *a1 = mol->atom(p->ind1);
    if (mol1 != mol2 || !a1->bonded(p->ind2)) {
      // Needed to avoid a memory leak. Append increments the refcount 
      // of whatever gets added to it, but so does PyInt_FromLong.
      // Without a decref, the integers created never have their refcount
      //  go to zero, and you leak memory.
      tmp1 = PyInt_FromLong(p->ind1);
      tmp2 = PyInt_FromLong(p->ind2);
      PyList_Append(list1, tmp1);
      PyList_Append(list2, tmp2);
      Py_DECREF(tmp1);
      Py_DECREF(tmp2);
    }
    tmp = p->next;
    free(p);
  }
  PyObject *result = PyList_New(2);
  PyList_SET_ITEM(result, 0, list1);
  PyList_SET_ITEM(result, 1, list2);
  return result;
}