Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/molecule.cpp

    r83f176 r952f38  
    1 /*
    2  * Project: MoleCuilder
    3  * Description: creates and alters molecular systems
    4  * Copyright (C)  2010 University of Bonn. All rights reserved.
    5  * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
    6  */
    7 
    81/** \file molecules.cpp
    92 *
     
    125 */
    136
    14 // include config.h
    157#ifdef HAVE_CONFIG_H
    168#include <config.h>
     
    9789}
    9890
    99 bool molecule::changeId(moleculeId_t newId){
    100   // first we move ourselves in the world
    101   // the world lets us know if that succeeded
    102   if(World::getInstance().changeMoleculeId(id,newId,this)){
    103     id = newId;
    104     return true;
    105   }
    106   else{
    107     return false;
    108   }
    109 }
    110 
    111 
    11291moleculeId_t molecule::getId(){
    11392  return id;
     
    172151molecule::const_iterator molecule::erase( const_iterator loc )
    173152{
    174   OBSERVE;
    175153  molecule::const_iterator iter = loc;
    176154  iter--;
     
    178156  atomIds.erase( atom->getId() );
    179157  atoms.remove( atom );
    180   formula-=atom->getType();
    181158  atom->removeFromMolecule();
    182159  return iter;
     
    185162molecule::const_iterator molecule::erase( atom * key )
    186163{
    187   OBSERVE;
    188164  molecule::const_iterator iter = find(key);
    189165  if (iter != end()){
    190166    atomIds.erase( key->getId() );
    191167    atoms.remove( key );
    192     formula-=key->getType();
    193168    key->removeFromMolecule();
    194169  }
     
    208183pair<molecule::iterator,bool> molecule::insert ( atom * const key )
    209184{
    210   OBSERVE;
    211185  pair<atomIdSet::iterator,bool> res = atomIds.insert(key->getId());
    212186  if (res.second) { // push atom if went well
    213187    atoms.push_back(key);
    214     formula+=key->getType();
    215188    return pair<iterator,bool>(molecule::iterator(--end()),res.second);
    216189  } else {
     
    233206  if (pointer != NULL) {
    234207    pointer->sort = &pointer->nr;
    235     if (pointer->getType() != NULL) {
    236       if (pointer->getType()->getAtomicNumber() != 1)
     208    if (pointer->type != NULL) {
     209      formula += pointer->type;
     210      if (pointer->type->Z != 1)
    237211        NoNonHydrogen++;
    238212      if(pointer->getName() == "Unknown"){
    239213        stringstream sstr;
    240         sstr << pointer->getType()->getSymbol() << pointer->nr+1;
     214        sstr << pointer->type->symbol << pointer->nr+1;
    241215        pointer->setName(sstr.str());
    242216      }
     
    262236    walker->nr = last_atom++;  // increase number within molecule
    263237    insert(walker);
    264     if ((pointer->getType() != NULL) && (pointer->getType()->getAtomicNumber() != 1))
     238    if ((pointer->type != NULL) && (pointer->type->Z != 1))
    265239      NoNonHydrogen++;
    266240    retval=walker;
     
    320294//  Log() << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl;
    321295  // create vector in direction of bond
    322   InBondvector = TopReplacement->getPosition() - TopOrigin->getPosition();
     296  InBondvector = TopReplacement->x - TopOrigin->x;
    323297  bondlength = InBondvector.Norm();
    324298
     
    332306    Orthovector1.Zero();
    333307    for (int i=NDIM;i--;) {
    334       l = TopReplacement->at(i) - TopOrigin->at(i);
     308      l = TopReplacement->x[i] - TopOrigin->x[i];
    335309      if (fabs(l) > BondDistance) { // is component greater than bond distance
    336310        Orthovector1[i] = (l < 0) ? -1. : +1.;
     
    347321  InBondvector.Normalize();
    348322  // get typical bond length and store as scale factor for later
    349   ASSERT(TopOrigin->getType() != NULL, "AddHydrogenReplacementAtom: element of TopOrigin is not given.");
    350   BondRescale = TopOrigin->getType()->getHBondDistance(TopBond->BondDegree-1);
     323  ASSERT(TopOrigin->type != NULL, "AddHydrogenReplacementAtom: element of TopOrigin is not given.");
     324  BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1];
    351325  if (BondRescale == -1) {
    352326    DoeLog(1) && (eLog()<< Verbose(1) << "There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->getName() << "<->" << TopReplacement->getName() << ") of degree " << TopBond->BondDegree << "!" << endl);
     
    362336    case 1:
    363337      FirstOtherAtom = World::getInstance().createAtom();    // new atom
    364       FirstOtherAtom->setType(1);  // element is Hydrogen
    365       FirstOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
     338      FirstOtherAtom->type = elemente->FindElement(1);  // element is Hydrogen
     339      FirstOtherAtom->v = TopReplacement->v; // copy velocity
    366340      FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    367       if (TopReplacement->getType()->getAtomicNumber() == 1) { // neither rescale nor replace if it's already hydrogen
     341      if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen
    368342        FirstOtherAtom->father = TopReplacement;
    369343        BondRescale = bondlength;
     
    372346      }
    373347      InBondvector *= BondRescale;   // rescale the distance vector to Hydrogen bond length
    374       FirstOtherAtom->setPosition(TopOrigin->getPosition() + InBondvector); // set coordination to origin and add distance vector to replacement atom
     348      FirstOtherAtom->x = TopOrigin->x; // set coordination to origin ...
     349      FirstOtherAtom->x += InBondvector;  // ... and add distance vector to replacement atom
    375350      AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
    376351//      Log() << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
     
    405380        // determine the plane of these two with the *origin
    406381        try {
    407           Orthovector1 =Plane(TopOrigin->getPosition(), FirstOtherAtom->getPosition(), SecondOtherAtom->getPosition()).getNormal();
     382          Orthovector1 =Plane(TopOrigin->x, FirstOtherAtom->x, SecondOtherAtom->x).getNormal();
    408383        }
    409384        catch(LinearDependenceException &excp){
     
    426401      FirstOtherAtom = World::getInstance().createAtom();
    427402      SecondOtherAtom = World::getInstance().createAtom();
    428       FirstOtherAtom->setType(1);
    429       SecondOtherAtom->setType(1);
    430       FirstOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
     403      FirstOtherAtom->type = elemente->FindElement(1);
     404      SecondOtherAtom->type = elemente->FindElement(1);
     405      FirstOtherAtom->v = TopReplacement->v; // copy velocity
    431406      FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    432       SecondOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
     407      SecondOtherAtom->v = TopReplacement->v; // copy velocity
    433408      SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
    434409      FirstOtherAtom->father = NULL;  // we are just an added hydrogen with no father
    435410      SecondOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
    436       bondangle = TopOrigin->getType()->getHBondAngle(1);
     411      bondangle = TopOrigin->type->HBondAngle[1];
    437412      if (bondangle == -1) {
    438413        DoeLog(1) && (eLog()<< Verbose(1) << "There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->getName() << "<->" << TopReplacement->getName() << ") of degree " << TopBond->BondDegree << "!" << endl);
     
    448423//      Log() << Verbose(0) << endl;
    449424//      Log() << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl;
    450       FirstOtherAtom->Zero();
    451       SecondOtherAtom->Zero();
     425      FirstOtherAtom->x.Zero();
     426      SecondOtherAtom->x.Zero();
    452427      for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction)
    453         FirstOtherAtom->set(i, InBondvector[i] * cos(bondangle) + Orthovector1[i] * (sin(bondangle)));
    454         SecondOtherAtom->set(i, InBondvector[i] * cos(bondangle) + Orthovector1[i] * (-sin(bondangle)));
    455       }
    456       FirstOtherAtom->Scale(BondRescale);  // rescale by correct BondDistance
    457       SecondOtherAtom->Scale(BondRescale);
     428        FirstOtherAtom->x[i] = InBondvector[i] * cos(bondangle) + Orthovector1[i] * (sin(bondangle));
     429        SecondOtherAtom->x[i] = InBondvector[i] * cos(bondangle) + Orthovector1[i] * (-sin(bondangle));
     430      }
     431      FirstOtherAtom->x *= BondRescale;  // rescale by correct BondDistance
     432      SecondOtherAtom->x *= BondRescale;
    458433      //Log() << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl;
    459       *FirstOtherAtom += TopOrigin->getPosition();
    460       *SecondOtherAtom += TopOrigin->getPosition();
     434      for(int i=NDIM;i--;) { // and make relative to origin atom
     435        FirstOtherAtom->x[i] += TopOrigin->x[i];
     436        SecondOtherAtom->x[i] += TopOrigin->x[i];
     437      }
    461438      // ... and add to molecule
    462439      AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
     
    480457      SecondOtherAtom = World::getInstance().createAtom();
    481458      ThirdOtherAtom = World::getInstance().createAtom();
    482       FirstOtherAtom->setType(1);
    483       SecondOtherAtom->setType(1);
    484       ThirdOtherAtom->setType(1);
    485       FirstOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
     459      FirstOtherAtom->type = elemente->FindElement(1);
     460      SecondOtherAtom->type = elemente->FindElement(1);
     461      ThirdOtherAtom->type = elemente->FindElement(1);
     462      FirstOtherAtom->v = TopReplacement->v; // copy velocity
    486463      FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    487       SecondOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
     464      SecondOtherAtom->v = TopReplacement->v; // copy velocity
    488465      SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
    489       ThirdOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
     466      ThirdOtherAtom->v = TopReplacement->v; // copy velocity
    490467      ThirdOtherAtom->FixedIon = TopReplacement->FixedIon;
    491468      FirstOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
     
    510487
    511488      // create correct coordination for the three atoms
    512       alpha = (TopOrigin->getType()->getHBondAngle(2))/180.*M_PI/2.;  // retrieve triple bond angle from database
     489      alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.;  // retrieve triple bond angle from database
    513490      l = BondRescale;        // desired bond length
    514491      b = 2.*l*sin(alpha);    // base length of isosceles triangle
     
    521498      factors[1] = f;
    522499      factors[2] = 0.;
    523       FirstOtherAtom->LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
     500      FirstOtherAtom->x.LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
    524501      factors[1] = -0.5*f;
    525502      factors[2] = g;
    526       SecondOtherAtom->LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
     503      SecondOtherAtom->x.LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
    527504      factors[2] = -g;
    528       ThirdOtherAtom->LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
     505      ThirdOtherAtom->x.LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
    529506
    530507      // rescale each to correct BondDistance
     
    534511
    535512      // and relative to *origin atom
    536       *FirstOtherAtom += TopOrigin->getPosition();
    537       *SecondOtherAtom += TopOrigin->getPosition();
    538       *ThirdOtherAtom += TopOrigin->getPosition();
     513      FirstOtherAtom->x += TopOrigin->x;
     514      SecondOtherAtom->x += TopOrigin->x;
     515      ThirdOtherAtom->x += TopOrigin->x;
    539516
    540517      // ... and add to molecule
     
    612589    *item >> x[1];
    613590    *item >> x[2];
    614     Walker->setType(elemente->FindElement(shorthand));
    615     if (Walker->getType() == NULL) {
     591    Walker->type = elemente->FindElement(shorthand);
     592    if (Walker->type == NULL) {
    616593      DoeLog(1) && (eLog()<< Verbose(1) << "Could not parse the element at line: '" << line << "', setting to H.");
    617       Walker->setType(1);
     594      Walker->type = elemente->FindElement(1);
    618595    }
    619596    if (Walker->Trajectory.R.size() <= (unsigned int)MDSteps) {
     
    622599      Walker->Trajectory.F.resize(MDSteps+10);
    623600    }
    624     Walker->setPosition(Vector(x));
    625601    for(j=NDIM;j--;) {
     602      Walker->x[j] = x[j];
    626603      Walker->Trajectory.R.at(MDSteps-1)[j] = x[j];
    627604      Walker->Trajectory.U.at(MDSteps-1)[j] = 0;
     
    642619{
    643620  molecule *copy = World::getInstance().createMolecule();
     621  atom *LeftAtom = NULL, *RightAtom = NULL;
    644622
    645623  // copy all atoms
    646   for_each(atoms.begin(),atoms.end(),bind1st(mem_fun(&molecule::AddCopyAtom),copy));
     624  ActOnCopyWithEachAtom ( &molecule::AddCopyAtom, copy );
    647625
    648626  // copy all bonds
     627  bond *Binder = NULL;
     628  bond *NewBond = NULL;
    649629  for(molecule::iterator AtomRunner = begin(); AtomRunner != end(); ++AtomRunner)
    650630    for(BondList::iterator BondRunner = (*AtomRunner)->ListOfBonds.begin(); !(*AtomRunner)->ListOfBonds.empty(); BondRunner = (*AtomRunner)->ListOfBonds.begin())
    651631      if ((*BondRunner)->leftatom == *AtomRunner) {
    652         bond *Binder = (*BondRunner);
     632        Binder = (*BondRunner);
    653633
    654634        // get the pendant atoms of current bond in the copy molecule
    655         atomSet::iterator leftiter=find_if(atoms.begin(),atoms.end(),bind2nd(mem_fun(&atom::isFather),Binder->leftatom));
    656         atomSet::iterator rightiter=find_if(atoms.begin(),atoms.end(),bind2nd(mem_fun(&atom::isFather),Binder->rightatom));
    657         ASSERT(leftiter!=atoms.end(),"No original left atom for bondcopy found");
    658         ASSERT(leftiter!=atoms.end(),"No original right atom for bondcopy found");
    659         atom *LeftAtom = *leftiter;
    660         atom *RightAtom = *rightiter;
    661 
    662         bond *NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);
     635        copy->ActOnAllAtoms( &atom::EqualsFather, (const atom *)Binder->leftatom, (const atom **)&LeftAtom );
     636        copy->ActOnAllAtoms( &atom::EqualsFather, (const atom *)Binder->rightatom, (const atom **)&RightAtom );
     637
     638        NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);
    663639        NewBond->Cyclic = Binder->Cyclic;
    664640        if (Binder->Cyclic)
     
    667643      }
    668644  // correct fathers
    669   for_each(atoms.begin(),atoms.end(),mem_fun(&atom::CorrectFather));
     645  ActOnAllAtoms( &atom::CorrectFather );
    670646
    671647  // copy values
     
    718694  atom1->RegisterBond(Binder);
    719695  atom2->RegisterBond(Binder);
    720   if ((atom1->getType() != NULL) && (atom1->getType()->getAtomicNumber() != 1) && (atom2->getType() != NULL) && (atom2->getType()->getAtomicNumber() != 1))
     696  if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1))
    721697    NoNonBonds++;
    722698
     
    784760};
    785761
    786 /** Removes atom from molecule list and removes all of its bonds.
     762/** Removes atom from molecule list and deletes it.
    787763 * \param *pointer atom to be removed
    788764 * \return true - succeeded, false - atom not found in list
     
    792768  ASSERT(pointer, "Null pointer passed to molecule::RemoveAtom().");
    793769  OBSERVE;
     770  formula-=pointer->type;
    794771  RemoveBonds(pointer);
    795772  erase(pointer);
     
    805782  if (pointer == NULL)
    806783    return false;
     784  formula-=pointer->type;
    807785  erase(pointer);
    808786  return true;
     
    815793{
    816794  for (molecule::iterator iter = begin(); !empty(); iter = begin())
    817     erase(*iter);
     795      erase(iter);
    818796  return empty();
    819797};
     
    874852 * \param *out output stream
    875853 */
    876 bool molecule::Output(ostream * const output)
    877 {
     854bool molecule::Output(ofstream * const output)
     855{
     856  int ElementNo[MAX_ELEMENTS], AtomNo[MAX_ELEMENTS];
     857
     858  for (int i=0;i<MAX_ELEMENTS;++i) {
     859    AtomNo[i] = 0;
     860    ElementNo[i] = 0;
     861  }
    878862  if (output == NULL) {
    879863    return false;
    880864  } else {
    881     int AtomNo[MAX_ELEMENTS];
    882     memset(AtomNo,0,(MAX_ELEMENTS-1)*sizeof(*AtomNo));
    883     enumeration<const element*> elementLookup = formula.enumerateElements();
    884     for(map<const element*,unsigned int>::iterator iter=elementLookup.there.begin();
    885         iter!=elementLookup.there.end();++iter){
    886       cout << "Enumerated element " << *iter->first << " with number " << iter->second << endl;
    887     }
    888865    *output << "#Ion_TypeNr._Nr.R[0]    R[1]    R[2]    MoveType (0 MoveIon, 1 FixedIon)" << endl;
    889     for_each(atoms.begin(),atoms.end(),boost::bind(&atom::OutputArrayIndexed,_1,output,elementLookup,AtomNo,(const char*)0));
     866    SetIndexedArrayForEachAtomTo ( ElementNo, &element::Z, &AbsoluteValue, 1);
     867    int current=1;
     868    for (int i=0;i<MAX_ELEMENTS;++i) {
     869      if (ElementNo[i] == 1)
     870        ElementNo[i] = current++;
     871    }
     872    ActOnAllAtoms( &atom::OutputArrayIndexed, (ostream * const) output, (const int *)ElementNo, (int *)AtomNo, (const char *) NULL );
    890873    return true;
    891874  }
     
    912895        ElementNo[i] = 0;
    913896      }
    914       for(molecule::iterator iter = begin(); iter != end(); ++iter) {
    915         ElementNo[(*iter)->getType()->getAtomicNumber()] = 1;
    916       }
     897      SetIndexedArrayForEachAtomTo ( ElementNo, &element::Z, &AbsoluteValue, 1);
    917898      int current=1;
    918899      for (int i=0;i<MAX_ELEMENTS;++i) {
     
    932913{
    933914  DoLog(2) && (Log() << Verbose(2) << endl << "From Contents of ListOfBonds, all non-hydrogen atoms:" << endl);
    934   for_each(atoms.begin(),atoms.end(),mem_fun(&atom::OutputBondOfAtom));
     915  ActOnAllAtoms (&atom::OutputBondOfAtom );
    935916  DoLog(0) && (Log() << Verbose(0) << endl);
    936917};
     
    955936    for (int step=0;step<MDSteps;step++) {
    956937      *output << getAtomCount() << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);
    957       for_each(atoms.begin(),atoms.end(),boost::bind(&atom::OutputTrajectoryXYZ,_1,output,step));
     938      ActOnAllAtoms( &atom::OutputTrajectoryXYZ, output, step );
    958939    }
    959940    return true;
     
    972953    now = time((time_t *)NULL);   // Get the system time and put it into 'now' as 'calender time'
    973954    *output << getAtomCount() << "\n\tCreated by molecuilder on " << ctime(&now);
    974     for_each(atoms.begin(),atoms.end(),bind2nd(mem_fun(&atom::OutputXYZLine),output));
     955    ActOnAllAtoms( &atom::OutputXYZLine, output );
    975956    return true;
    976957  } else
     
    988969  for (molecule::const_iterator iter = atoms.begin(); iter != atoms.end(); ++iter) {
    989970    (*iter)->nr = i;   // update number in molecule (for easier referencing in FragmentMolecule lateron)
    990     if ((*iter)->getType()->getAtomicNumber() != 1) // count non-hydrogen atoms whilst at it
     971    if ((*iter)->type->Z != 1) // count non-hydrogen atoms whilst at it
    991972      NoNonHydrogen++;
    992973    stringstream sstr;
    993     sstr << (*iter)->getType()->getSymbol() << (*iter)->nr+1;
     974    sstr << (*iter)->type->symbol << (*iter)->nr+1;
    994975    (*iter)->setName(sstr.str());
    995976    DoLog(3) && (Log() << Verbose(3) << "Naming atom nr. " << (*iter)->nr << " " << (*iter)->getName() << "." << endl);
     
    997978  }
    998979  return res;
     980};
     981
     982/** Determines whether two molecules actually contain the same atoms and coordination.
     983 * \param *out output stream for debugging
     984 * \param *OtherMolecule the molecule to compare this one to
     985 * \param threshold upper limit of difference when comparing the coordination.
     986 * \return NULL - not equal, otherwise an allocated (molecule::AtomCount) permutation map of the atom numbers (which corresponds to which)
     987 */
     988int * molecule::IsEqualToWithinThreshold(molecule *OtherMolecule, double threshold)
     989{
     990  int flag;
     991  double *Distances = NULL, *OtherDistances = NULL;
     992  Vector CenterOfGravity, OtherCenterOfGravity;
     993  size_t *PermMap = NULL, *OtherPermMap = NULL;
     994  int *PermutationMap = NULL;
     995  bool result = true; // status of comparison
     996
     997  DoLog(3) && (Log() << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl);
     998  /// first count both their atoms and elements and update lists thereby ...
     999  //Log() << Verbose(0) << "Counting atoms, updating list" << endl;
     1000
     1001  /// ... and compare:
     1002  /// -# AtomCount
     1003  if (result) {
     1004    if (getAtomCount() != OtherMolecule->getAtomCount()) {
     1005      DoLog(4) && (Log() << Verbose(4) << "AtomCounts don't match: " << getAtomCount() << " == " << OtherMolecule->getAtomCount() << endl);
     1006      result = false;
     1007    } else Log() << Verbose(4) << "AtomCounts match: " << getAtomCount() << " == " << OtherMolecule->getAtomCount() << endl;
     1008  }
     1009  /// -# Formula
     1010  if (result) {
     1011    if (formula != OtherMolecule->formula) {
     1012      DoLog(4) && (Log() << Verbose(4) << "Formulas don't match: " << formula << " == " << OtherMolecule->formula << endl);
     1013      result = false;
     1014    } else Log() << Verbose(4) << "Formulas match: " << formula << " == " << OtherMolecule->formula << endl;
     1015  }
     1016  /// then determine and compare center of gravity for each molecule ...
     1017  if (result) {
     1018    DoLog(5) && (Log() << Verbose(5) << "Calculating Centers of Gravity" << endl);
     1019    DeterminePeriodicCenter(CenterOfGravity);
     1020    OtherMolecule->DeterminePeriodicCenter(OtherCenterOfGravity);
     1021    DoLog(5) && (Log() << Verbose(5) << "Center of Gravity: " << CenterOfGravity << endl);
     1022    DoLog(5) && (Log() << Verbose(5) << "Other Center of Gravity: " << OtherCenterOfGravity << endl);
     1023    if (CenterOfGravity.DistanceSquared(OtherCenterOfGravity) > threshold*threshold) {
     1024      DoLog(4) && (Log() << Verbose(4) << "Centers of gravity don't match." << endl);
     1025      result = false;
     1026    }
     1027  }
     1028
     1029  /// ... then make a list with the euclidian distance to this center for each atom of both molecules
     1030  if (result) {
     1031    DoLog(5) && (Log() << Verbose(5) << "Calculating distances" << endl);
     1032    Distances = new double[getAtomCount()];
     1033    OtherDistances = new double[getAtomCount()];
     1034    SetIndexedArrayForEachAtomTo ( Distances, &atom::nr, &atom::DistanceSquaredToVector, (const Vector &)CenterOfGravity);
     1035    SetIndexedArrayForEachAtomTo ( OtherDistances, &atom::nr, &atom::DistanceSquaredToVector, (const Vector &)CenterOfGravity);
     1036    for(int i=0;i<getAtomCount();i++) {
     1037      Distances[i] = 0.;
     1038      OtherDistances[i] = 0.;
     1039    }
     1040
     1041    /// ... sort each list (using heapsort (o(N log N)) from GSL)
     1042    DoLog(5) && (Log() << Verbose(5) << "Sorting distances" << endl);
     1043    PermMap = new size_t[getAtomCount()];
     1044    OtherPermMap = new size_t[getAtomCount()];
     1045    for(int i=0;i<getAtomCount();i++) {
     1046      PermMap[i] = 0;
     1047      OtherPermMap[i] = 0;
     1048    }
     1049    gsl_heapsort_index (PermMap, Distances, getAtomCount(), sizeof(double), CompareDoubles);
     1050    gsl_heapsort_index (OtherPermMap, OtherDistances, getAtomCount(), sizeof(double), CompareDoubles);
     1051    PermutationMap = new int[getAtomCount()];
     1052    for(int i=0;i<getAtomCount();i++)
     1053      PermutationMap[i] = 0;
     1054    DoLog(5) && (Log() << Verbose(5) << "Combining Permutation Maps" << endl);
     1055    for(int i=getAtomCount();i--;)
     1056      PermutationMap[PermMap[i]] = (int) OtherPermMap[i];
     1057
     1058    /// ... and compare them step by step, whether the difference is individually(!) below \a threshold for all
     1059    DoLog(4) && (Log() << Verbose(4) << "Comparing distances" << endl);
     1060    flag = 0;
     1061    for (int i=0;i<getAtomCount();i++) {
     1062      DoLog(5) && (Log() << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<  threshold << endl);
     1063      if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold)
     1064        flag = 1;
     1065    }
     1066
     1067    // free memory
     1068    delete[](PermMap);
     1069    delete[](OtherPermMap);
     1070    delete[](Distances);
     1071    delete[](OtherDistances);
     1072    if (flag) { // if not equal
     1073      delete[](PermutationMap);
     1074      result = false;
     1075    }
     1076  }
     1077  /// return pointer to map if all distances were below \a threshold
     1078  DoLog(3) && (Log() << Verbose(3) << "End of IsEqualToWithinThreshold." << endl);
     1079  if (result) {
     1080    DoLog(3) && (Log() << Verbose(3) << "Result: Equal." << endl);
     1081    return PermutationMap;
     1082  } else {
     1083    DoLog(3) && (Log() << Verbose(3) << "Result: Not equal." << endl);
     1084    return NULL;
     1085  }
    9991086};
    10001087
Note: See TracChangeset for help on using the changeset viewer.