Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/molecule.cpp

    r952f38 r83f176  
     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
    18/** \file molecules.cpp
    29 *
     
    512 */
    613
     14// include config.h
    715#ifdef HAVE_CONFIG_H
    816#include <config.h>
     
    8997}
    9098
     99bool 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
    91112moleculeId_t molecule::getId(){
    92113  return id;
     
    151172molecule::const_iterator molecule::erase( const_iterator loc )
    152173{
     174  OBSERVE;
    153175  molecule::const_iterator iter = loc;
    154176  iter--;
     
    156178  atomIds.erase( atom->getId() );
    157179  atoms.remove( atom );
     180  formula-=atom->getType();
    158181  atom->removeFromMolecule();
    159182  return iter;
     
    162185molecule::const_iterator molecule::erase( atom * key )
    163186{
     187  OBSERVE;
    164188  molecule::const_iterator iter = find(key);
    165189  if (iter != end()){
    166190    atomIds.erase( key->getId() );
    167191    atoms.remove( key );
     192    formula-=key->getType();
    168193    key->removeFromMolecule();
    169194  }
     
    183208pair<molecule::iterator,bool> molecule::insert ( atom * const key )
    184209{
     210  OBSERVE;
    185211  pair<atomIdSet::iterator,bool> res = atomIds.insert(key->getId());
    186212  if (res.second) { // push atom if went well
    187213    atoms.push_back(key);
     214    formula+=key->getType();
    188215    return pair<iterator,bool>(molecule::iterator(--end()),res.second);
    189216  } else {
     
    206233  if (pointer != NULL) {
    207234    pointer->sort = &pointer->nr;
    208     if (pointer->type != NULL) {
    209       formula += pointer->type;
    210       if (pointer->type->Z != 1)
     235    if (pointer->getType() != NULL) {
     236      if (pointer->getType()->getAtomicNumber() != 1)
    211237        NoNonHydrogen++;
    212238      if(pointer->getName() == "Unknown"){
    213239        stringstream sstr;
    214         sstr << pointer->type->symbol << pointer->nr+1;
     240        sstr << pointer->getType()->getSymbol() << pointer->nr+1;
    215241        pointer->setName(sstr.str());
    216242      }
     
    236262    walker->nr = last_atom++;  // increase number within molecule
    237263    insert(walker);
    238     if ((pointer->type != NULL) && (pointer->type->Z != 1))
     264    if ((pointer->getType() != NULL) && (pointer->getType()->getAtomicNumber() != 1))
    239265      NoNonHydrogen++;
    240266    retval=walker;
     
    294320//  Log() << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl;
    295321  // create vector in direction of bond
    296   InBondvector = TopReplacement->x - TopOrigin->x;
     322  InBondvector = TopReplacement->getPosition() - TopOrigin->getPosition();
    297323  bondlength = InBondvector.Norm();
    298324
     
    306332    Orthovector1.Zero();
    307333    for (int i=NDIM;i--;) {
    308       l = TopReplacement->x[i] - TopOrigin->x[i];
     334      l = TopReplacement->at(i) - TopOrigin->at(i);
    309335      if (fabs(l) > BondDistance) { // is component greater than bond distance
    310336        Orthovector1[i] = (l < 0) ? -1. : +1.;
     
    321347  InBondvector.Normalize();
    322348  // get typical bond length and store as scale factor for later
    323   ASSERT(TopOrigin->type != NULL, "AddHydrogenReplacementAtom: element of TopOrigin is not given.");
    324   BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1];
     349  ASSERT(TopOrigin->getType() != NULL, "AddHydrogenReplacementAtom: element of TopOrigin is not given.");
     350  BondRescale = TopOrigin->getType()->getHBondDistance(TopBond->BondDegree-1);
    325351  if (BondRescale == -1) {
    326352    DoeLog(1) && (eLog()<< Verbose(1) << "There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->getName() << "<->" << TopReplacement->getName() << ") of degree " << TopBond->BondDegree << "!" << endl);
     
    336362    case 1:
    337363      FirstOtherAtom = World::getInstance().createAtom();    // new atom
    338       FirstOtherAtom->type = elemente->FindElement(1);  // element is Hydrogen
    339       FirstOtherAtom->v = TopReplacement->v; // copy velocity
     364      FirstOtherAtom->setType(1);  // element is Hydrogen
     365      FirstOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
    340366      FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    341       if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen
     367      if (TopReplacement->getType()->getAtomicNumber() == 1) { // neither rescale nor replace if it's already hydrogen
    342368        FirstOtherAtom->father = TopReplacement;
    343369        BondRescale = bondlength;
     
    346372      }
    347373      InBondvector *= BondRescale;   // rescale the distance vector to Hydrogen bond length
    348       FirstOtherAtom->x = TopOrigin->x; // set coordination to origin ...
    349       FirstOtherAtom->x += InBondvector;  // ... and add distance vector to replacement atom
     374      FirstOtherAtom->setPosition(TopOrigin->getPosition() + InBondvector); // set coordination to origin and add distance vector to replacement atom
    350375      AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
    351376//      Log() << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
     
    380405        // determine the plane of these two with the *origin
    381406        try {
    382           Orthovector1 =Plane(TopOrigin->x, FirstOtherAtom->x, SecondOtherAtom->x).getNormal();
     407          Orthovector1 =Plane(TopOrigin->getPosition(), FirstOtherAtom->getPosition(), SecondOtherAtom->getPosition()).getNormal();
    383408        }
    384409        catch(LinearDependenceException &excp){
     
    401426      FirstOtherAtom = World::getInstance().createAtom();
    402427      SecondOtherAtom = World::getInstance().createAtom();
    403       FirstOtherAtom->type = elemente->FindElement(1);
    404       SecondOtherAtom->type = elemente->FindElement(1);
    405       FirstOtherAtom->v = TopReplacement->v; // copy velocity
     428      FirstOtherAtom->setType(1);
     429      SecondOtherAtom->setType(1);
     430      FirstOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
    406431      FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    407       SecondOtherAtom->v = TopReplacement->v; // copy velocity
     432      SecondOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
    408433      SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
    409434      FirstOtherAtom->father = NULL;  // we are just an added hydrogen with no father
    410435      SecondOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
    411       bondangle = TopOrigin->type->HBondAngle[1];
     436      bondangle = TopOrigin->getType()->getHBondAngle(1);
    412437      if (bondangle == -1) {
    413438        DoeLog(1) && (eLog()<< Verbose(1) << "There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->getName() << "<->" << TopReplacement->getName() << ") of degree " << TopBond->BondDegree << "!" << endl);
     
    423448//      Log() << Verbose(0) << endl;
    424449//      Log() << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl;
    425       FirstOtherAtom->x.Zero();
    426       SecondOtherAtom->x.Zero();
     450      FirstOtherAtom->Zero();
     451      SecondOtherAtom->Zero();
    427452      for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction)
    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;
     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);
    433458      //Log() << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl;
    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       }
     459      *FirstOtherAtom += TopOrigin->getPosition();
     460      *SecondOtherAtom += TopOrigin->getPosition();
    438461      // ... and add to molecule
    439462      AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
     
    457480      SecondOtherAtom = World::getInstance().createAtom();
    458481      ThirdOtherAtom = World::getInstance().createAtom();
    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
     482      FirstOtherAtom->setType(1);
     483      SecondOtherAtom->setType(1);
     484      ThirdOtherAtom->setType(1);
     485      FirstOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
    463486      FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    464       SecondOtherAtom->v = TopReplacement->v; // copy velocity
     487      SecondOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
    465488      SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
    466       ThirdOtherAtom->v = TopReplacement->v; // copy velocity
     489      ThirdOtherAtom->AtomicVelocity = TopReplacement->AtomicVelocity; // copy velocity
    467490      ThirdOtherAtom->FixedIon = TopReplacement->FixedIon;
    468491      FirstOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
     
    487510
    488511      // create correct coordination for the three atoms
    489       alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.;  // retrieve triple bond angle from database
     512      alpha = (TopOrigin->getType()->getHBondAngle(2))/180.*M_PI/2.;  // retrieve triple bond angle from database
    490513      l = BondRescale;        // desired bond length
    491514      b = 2.*l*sin(alpha);    // base length of isosceles triangle
     
    498521      factors[1] = f;
    499522      factors[2] = 0.;
    500       FirstOtherAtom->x.LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
     523      FirstOtherAtom->LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
    501524      factors[1] = -0.5*f;
    502525      factors[2] = g;
    503       SecondOtherAtom->x.LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
     526      SecondOtherAtom->LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
    504527      factors[2] = -g;
    505       ThirdOtherAtom->x.LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
     528      ThirdOtherAtom->LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors);
    506529
    507530      // rescale each to correct BondDistance
     
    511534
    512535      // and relative to *origin atom
    513       FirstOtherAtom->x += TopOrigin->x;
    514       SecondOtherAtom->x += TopOrigin->x;
    515       ThirdOtherAtom->x += TopOrigin->x;
     536      *FirstOtherAtom += TopOrigin->getPosition();
     537      *SecondOtherAtom += TopOrigin->getPosition();
     538      *ThirdOtherAtom += TopOrigin->getPosition();
    516539
    517540      // ... and add to molecule
     
    589612    *item >> x[1];
    590613    *item >> x[2];
    591     Walker->type = elemente->FindElement(shorthand);
    592     if (Walker->type == NULL) {
     614    Walker->setType(elemente->FindElement(shorthand));
     615    if (Walker->getType() == NULL) {
    593616      DoeLog(1) && (eLog()<< Verbose(1) << "Could not parse the element at line: '" << line << "', setting to H.");
    594       Walker->type = elemente->FindElement(1);
     617      Walker->setType(1);
    595618    }
    596619    if (Walker->Trajectory.R.size() <= (unsigned int)MDSteps) {
     
    599622      Walker->Trajectory.F.resize(MDSteps+10);
    600623    }
     624    Walker->setPosition(Vector(x));
    601625    for(j=NDIM;j--;) {
    602       Walker->x[j] = x[j];
    603626      Walker->Trajectory.R.at(MDSteps-1)[j] = x[j];
    604627      Walker->Trajectory.U.at(MDSteps-1)[j] = 0;
     
    619642{
    620643  molecule *copy = World::getInstance().createMolecule();
    621   atom *LeftAtom = NULL, *RightAtom = NULL;
    622644
    623645  // copy all atoms
    624   ActOnCopyWithEachAtom ( &molecule::AddCopyAtom, copy );
     646  for_each(atoms.begin(),atoms.end(),bind1st(mem_fun(&molecule::AddCopyAtom),copy));
    625647
    626648  // copy all bonds
    627   bond *Binder = NULL;
    628   bond *NewBond = NULL;
    629649  for(molecule::iterator AtomRunner = begin(); AtomRunner != end(); ++AtomRunner)
    630650    for(BondList::iterator BondRunner = (*AtomRunner)->ListOfBonds.begin(); !(*AtomRunner)->ListOfBonds.empty(); BondRunner = (*AtomRunner)->ListOfBonds.begin())
    631651      if ((*BondRunner)->leftatom == *AtomRunner) {
    632         Binder = (*BondRunner);
     652        bond *Binder = (*BondRunner);
    633653
    634654        // get the pendant atoms of current bond in the copy molecule
    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);
     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);
    639663        NewBond->Cyclic = Binder->Cyclic;
    640664        if (Binder->Cyclic)
     
    643667      }
    644668  // correct fathers
    645   ActOnAllAtoms( &atom::CorrectFather );
     669  for_each(atoms.begin(),atoms.end(),mem_fun(&atom::CorrectFather));
    646670
    647671  // copy values
     
    694718  atom1->RegisterBond(Binder);
    695719  atom2->RegisterBond(Binder);
    696   if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1))
     720  if ((atom1->getType() != NULL) && (atom1->getType()->getAtomicNumber() != 1) && (atom2->getType() != NULL) && (atom2->getType()->getAtomicNumber() != 1))
    697721    NoNonBonds++;
    698722
     
    760784};
    761785
    762 /** Removes atom from molecule list and deletes it.
     786/** Removes atom from molecule list and removes all of its bonds.
    763787 * \param *pointer atom to be removed
    764788 * \return true - succeeded, false - atom not found in list
     
    768792  ASSERT(pointer, "Null pointer passed to molecule::RemoveAtom().");
    769793  OBSERVE;
    770   formula-=pointer->type;
    771794  RemoveBonds(pointer);
    772795  erase(pointer);
     
    782805  if (pointer == NULL)
    783806    return false;
    784   formula-=pointer->type;
    785807  erase(pointer);
    786808  return true;
     
    793815{
    794816  for (molecule::iterator iter = begin(); !empty(); iter = begin())
    795       erase(iter);
     817    erase(*iter);
    796818  return empty();
    797819};
     
    852874 * \param *out output stream
    853875 */
    854 bool 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   }
     876bool molecule::Output(ostream * const output)
     877{
    862878  if (output == NULL) {
    863879    return false;
    864880  } 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    }
    865888    *output << "#Ion_TypeNr._Nr.R[0]    R[1]    R[2]    MoveType (0 MoveIon, 1 FixedIon)" << endl;
    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 );
     889    for_each(atoms.begin(),atoms.end(),boost::bind(&atom::OutputArrayIndexed,_1,output,elementLookup,AtomNo,(const char*)0));
    873890    return true;
    874891  }
     
    895912        ElementNo[i] = 0;
    896913      }
    897       SetIndexedArrayForEachAtomTo ( ElementNo, &element::Z, &AbsoluteValue, 1);
     914      for(molecule::iterator iter = begin(); iter != end(); ++iter) {
     915        ElementNo[(*iter)->getType()->getAtomicNumber()] = 1;
     916      }
    898917      int current=1;
    899918      for (int i=0;i<MAX_ELEMENTS;++i) {
     
    913932{
    914933  DoLog(2) && (Log() << Verbose(2) << endl << "From Contents of ListOfBonds, all non-hydrogen atoms:" << endl);
    915   ActOnAllAtoms (&atom::OutputBondOfAtom );
     934  for_each(atoms.begin(),atoms.end(),mem_fun(&atom::OutputBondOfAtom));
    916935  DoLog(0) && (Log() << Verbose(0) << endl);
    917936};
     
    936955    for (int step=0;step<MDSteps;step++) {
    937956      *output << getAtomCount() << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);
    938       ActOnAllAtoms( &atom::OutputTrajectoryXYZ, output, step );
     957      for_each(atoms.begin(),atoms.end(),boost::bind(&atom::OutputTrajectoryXYZ,_1,output,step));
    939958    }
    940959    return true;
     
    953972    now = time((time_t *)NULL);   // Get the system time and put it into 'now' as 'calender time'
    954973    *output << getAtomCount() << "\n\tCreated by molecuilder on " << ctime(&now);
    955     ActOnAllAtoms( &atom::OutputXYZLine, output );
     974    for_each(atoms.begin(),atoms.end(),bind2nd(mem_fun(&atom::OutputXYZLine),output));
    956975    return true;
    957976  } else
     
    969988  for (molecule::const_iterator iter = atoms.begin(); iter != atoms.end(); ++iter) {
    970989    (*iter)->nr = i;   // update number in molecule (for easier referencing in FragmentMolecule lateron)
    971     if ((*iter)->type->Z != 1) // count non-hydrogen atoms whilst at it
     990    if ((*iter)->getType()->getAtomicNumber() != 1) // count non-hydrogen atoms whilst at it
    972991      NoNonHydrogen++;
    973992    stringstream sstr;
    974     sstr << (*iter)->type->symbol << (*iter)->nr+1;
     993    sstr << (*iter)->getType()->getSymbol() << (*iter)->nr+1;
    975994    (*iter)->setName(sstr.str());
    976995    DoLog(3) && (Log() << Verbose(3) << "Naming atom nr. " << (*iter)->nr << " " << (*iter)->getName() << "." << endl);
     
    978997  }
    979998  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  */
    988 int * 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   }
    1086999};
    10871000
Note: See TracChangeset for help on using the changeset viewer.