Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/molecule.cpp

    rf8e486 r7baf4a  
    55 */
    66
     7#ifdef HAVE_CONFIG_H
     8#include <config.h>
     9#endif
     10
    711#include "Helpers/MemDebug.hpp"
    812
    913#include <cstring>
    1014#include <boost/bind.hpp>
     15#include <boost/foreach.hpp>
     16
     17#include <gsl/gsl_inline.h>
     18#include <gsl/gsl_heapsort.h>
    1119
    1220#include "World.hpp"
     
    2230#include "log.hpp"
    2331#include "molecule.hpp"
    24 #include "memoryallocator.hpp"
     32
    2533#include "periodentafel.hpp"
    2634#include "stackclass.hpp"
    2735#include "tesselation.hpp"
    2836#include "vector.hpp"
     37#include "Matrix.hpp"
    2938#include "World.hpp"
     39#include "Box.hpp"
    3040#include "Plane.hpp"
    3141#include "Exceptions/LinearDependenceException.hpp"
     
    3949molecule::molecule(const periodentafel * const teil) :
    4050  Observable("molecule"),
    41   elemente(teil),  MDSteps(0),  BondCount(0), ElementCount(0), NoNonHydrogen(0), NoNonBonds(0),
     51  elemente(teil),  MDSteps(0),  BondCount(0), NoNonHydrogen(0), NoNonBonds(0),
    4252  NoCyclicBonds(0), BondDistance(0.),  ActiveFlag(false), IndexNr(-1),
    43   formula(this,boost::bind(&molecule::calcFormula,this),"formula"),
    44   AtomCount(this,boost::bind(&molecule::doCountAtoms,this),"AtomCount"), last_atom(0),  InternalPointer(begin())
    45 {
    46 
    47   // other stuff
    48   for(int i=MAX_ELEMENTS;i--;)
    49     ElementsInMolecule[i] = 0;
    50   strcpy(name,World::getInstance().getDefaultName());
     53  AtomCount(this,boost::bind(&molecule::doCountAtoms,this),"AtomCount"), last_atom(0),  InternalPointer(atoms.begin())
     54{
     55
     56  strcpy(name,World::getInstance().getDefaultName().c_str());
    5157};
    5258
     
    7985void molecule::setName(const std::string _name){
    8086  OBSERVE;
     87  cout << "Set name of molecule " << getId() << " to " << _name << endl;
    8188  strncpy(name,_name.c_str(),MAXSTRINGSIZE);
    8289}
     
    9097}
    9198
    92 const std::string molecule::getFormula(){
    93   return *formula;
    94 }
    95 
    96 std::string molecule::calcFormula(){
    97   std::map<atomicNumber_t,unsigned int> counts;
    98   stringstream sstr;
    99   periodentafel *periode = World::getInstance().getPeriode();
    100   for (molecule::const_iterator iter = begin(); iter != end(); ++iter) {
    101     counts[(*iter)->type->getNumber()]++;
    102   }
    103   std::map<atomicNumber_t,unsigned int>::reverse_iterator iter;
    104   for(iter = counts.rbegin(); iter != counts.rend(); ++iter) {
    105     atomicNumber_t Z = (*iter).first;
    106     sstr << periode->FindElement(Z)->symbol << (*iter).second;
    107   }
    108   return sstr.str();
     99const Formula &molecule::getFormula(){
     100  return formula;
     101}
     102
     103unsigned int molecule::getElementCount(){
     104  return formula.getElementCount();
     105}
     106
     107bool molecule::hasElement(const element *element) const{
     108  return formula.hasElement(element);
     109}
     110
     111bool molecule::hasElement(atomicNumber_t Z) const{
     112  return formula.hasElement(Z);
     113}
     114
     115bool molecule::hasElement(const string &shorthand) const{
     116  return formula.hasElement(shorthand);
    109117}
    110118
     
    143151molecule::const_iterator molecule::erase( const_iterator loc )
    144152{
     153  OBSERVE;
    145154  molecule::const_iterator iter = loc;
    146155  iter--;
    147156  atom* atom = *loc;
    148   atoms.erase( loc );
     157  atomIds.erase( atom->getId() );
     158  atoms.remove( atom );
     159  formula-=atom->type;
    149160  atom->removeFromMolecule();
    150161  return iter;
     
    153164molecule::const_iterator molecule::erase( atom * key )
    154165{
    155   cout << "trying to erase atom" << endl;
     166  OBSERVE;
    156167  molecule::const_iterator iter = find(key);
    157168  if (iter != end()){
    158     atoms.erase( iter++ );
     169    atomIds.erase( key->getId() );
     170    atoms.remove( key );
     171    formula-=key->type;
    159172    key->removeFromMolecule();
    160173  }
     
    164177molecule::const_iterator molecule::find ( atom * key ) const
    165178{
    166   return atoms.find( key );
     179  molecule::const_iterator iter;
     180  for (molecule::const_iterator Runner = begin(); Runner != end(); ++Runner) {
     181    if (*Runner == key)
     182      return molecule::const_iterator(Runner);
     183  }
     184  return molecule::const_iterator(atoms.end());
    167185}
    168186
    169187pair<molecule::iterator,bool> molecule::insert ( atom * const key )
    170188{
    171   pair<atomSet::iterator,bool> res = atoms.insert(key);
    172   return pair<iterator,bool>(iterator(res.first,this),res.second);
     189  OBSERVE;
     190  pair<atomIdSet::iterator,bool> res = atomIds.insert(key->getId());
     191  if (res.second) { // push atom if went well
     192    atoms.push_back(key);
     193    formula+=key->type;
     194    return pair<iterator,bool>(molecule::iterator(--end()),res.second);
     195  } else {
     196    return pair<iterator,bool>(molecule::iterator(end()),res.second);
     197  }
    173198}
    174199
    175200bool molecule::containsAtom(atom* key){
    176   return atoms.count(key);
     201  return (find(key) != end());
    177202}
    178203
     
    188213    pointer->sort = &pointer->nr;
    189214    if (pointer->type != NULL) {
    190       if (ElementsInMolecule[pointer->type->Z] == 0)
    191         ElementCount++;
    192       ElementsInMolecule[pointer->type->Z]++; // increase number of elements
     215      formula += pointer->type;
    193216      if (pointer->type->Z != 1)
    194217        NoNonHydrogen++;
     
    216239  if (pointer != NULL) {
    217240    atom *walker = pointer->clone();
     241    formula += walker->type;
    218242    walker->setName(pointer->getName());
    219243    walker->nr = last_atom++;  // increase number within molecule
     
    272296  Vector Orthovector1, Orthovector2;  // temporary vectors in coordination construction
    273297  Vector InBondvector;    // vector in direction of *Bond
    274   double *matrix = NULL;
     298  const Matrix &matrix =  World::getInstance().getDomain().getM();
    275299  bond *Binder = NULL;
    276   double * const cell_size = World::getInstance().getDomain();
    277300
    278301//  Log() << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl;
     
    295318      } // (signs are correct, was tested!)
    296319    }
    297     matrix = ReturnFullMatrixforSymmetric(cell_size);
    298     Orthovector1.MatrixMultiplication(matrix);
     320    Orthovector1 *= matrix;
    299321    InBondvector -= Orthovector1; // subtract just the additional translation
    300     delete[](matrix);
    301322    bondlength = InBondvector.Norm();
    302323//    Log() << Verbose(4) << "Corrected InBondvector is now: ";
     
    529550      break;
    530551  }
    531   delete[](matrix);
    532552
    533553//  Log() << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl;
     
    606626{
    607627  molecule *copy = World::getInstance().createMolecule();
    608   atom *LeftAtom = NULL, *RightAtom = NULL;
    609628
    610629  // copy all atoms
    611   ActOnCopyWithEachAtom ( &molecule::AddCopyAtom, copy );
     630  for_each(atoms.begin(),atoms.end(),bind1st(mem_fun(&molecule::AddCopyAtom),copy));
    612631
    613632  // copy all bonds
    614   bond *Binder = NULL;
    615   bond *NewBond = NULL;
    616633  for(molecule::iterator AtomRunner = begin(); AtomRunner != end(); ++AtomRunner)
    617634    for(BondList::iterator BondRunner = (*AtomRunner)->ListOfBonds.begin(); !(*AtomRunner)->ListOfBonds.empty(); BondRunner = (*AtomRunner)->ListOfBonds.begin())
    618635      if ((*BondRunner)->leftatom == *AtomRunner) {
    619         Binder = (*BondRunner);
     636        bond *Binder = (*BondRunner);
    620637
    621638        // get the pendant atoms of current bond in the copy molecule
    622         copy->ActOnAllAtoms( &atom::EqualsFather, (const atom *)Binder->leftatom, (const atom **)&LeftAtom );
    623         copy->ActOnAllAtoms( &atom::EqualsFather, (const atom *)Binder->rightatom, (const atom **)&RightAtom );
    624 
    625         NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);
     639        atomSet::iterator leftiter=find_if(atoms.begin(),atoms.end(),bind2nd(mem_fun(&atom::isFather),Binder->leftatom));
     640        atomSet::iterator rightiter=find_if(atoms.begin(),atoms.end(),bind2nd(mem_fun(&atom::isFather),Binder->rightatom));
     641        ASSERT(leftiter!=atoms.end(),"No original left atom for bondcopy found");
     642        ASSERT(leftiter!=atoms.end(),"No original right atom for bondcopy found");
     643        atom *LeftAtom = *leftiter;
     644        atom *RightAtom = *rightiter;
     645
     646        bond *NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);
    626647        NewBond->Cyclic = Binder->Cyclic;
    627648        if (Binder->Cyclic)
     
    630651      }
    631652  // correct fathers
    632   ActOnAllAtoms( &atom::CorrectFather );
     653  for_each(atoms.begin(),atoms.end(),mem_fun(&atom::CorrectFather));
    633654
    634655  // copy values
    635   copy->CountElements();
    636656  if (hasBondStructure()) {  // if adjaceny list is present
    637657    copy->BondDistance = BondDistance;
     
    648668 * @param three vectors forming the matrix that defines the shape of the parallelpiped
    649669 */
    650 molecule* molecule::CopyMoleculeFromSubRegion(const Vector offset, const double *parallelepiped) const {
     670molecule* molecule::CopyMoleculeFromSubRegion(const Shape &region) const {
    651671  molecule *copy = World::getInstance().createMolecule();
    652672
    653   ActOnCopyWithEachAtomIfTrue ( &molecule::AddCopyAtom, copy, &atom::IsInParallelepiped, offset, parallelepiped );
     673  BOOST_FOREACH(atom *iter,atoms){
     674    if(iter->IsInShape(region)){
     675      copy->AddCopyAtom(iter);
     676    }
     677  }
    654678
    655679  //TODO: copy->BuildInducedSubgraph(this);
     
    728752  else
    729753    length = strlen(molname) - strlen(endname);
     754  cout << "Set name of molecule " << getId() << " to " << molname << endl;
    730755  strncpy(name, molname, length);
    731756  name[length]='\0';
     
    737762void molecule::SetBoxDimension(Vector *dim)
    738763{
    739   double * const cell_size = World::getInstance().getDomain();
    740   cell_size[0] = dim->at(0);
    741   cell_size[1] = 0.;
    742   cell_size[2] = dim->at(1);
    743   cell_size[3] = 0.;
    744   cell_size[4] = 0.;
    745   cell_size[5] = dim->at(2);
     764  Matrix domain;
     765  for(int i =0; i<NDIM;++i)
     766    domain.at(i,i) = dim->at(i);
     767  World::getInstance().setDomain(domain);
    746768};
    747769
     
    754776  ASSERT(pointer, "Null pointer passed to molecule::RemoveAtom().");
    755777  OBSERVE;
    756   if (ElementsInMolecule[pointer->type->Z] != 0)  { // this would indicate an error
    757     ElementsInMolecule[pointer->type->Z]--;  // decrease number of atom of this element
    758   } else
    759     DoeLog(1) && (eLog()<< Verbose(1) << "Atom " << pointer->getName() << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl);
    760   if (ElementsInMolecule[pointer->type->Z] == 0)  // was last atom of this element?
    761     ElementCount--;
     778  formula-=pointer->type;
    762779  RemoveBonds(pointer);
    763780  erase(pointer);
     
    773790  if (pointer == NULL)
    774791    return false;
    775   if (ElementsInMolecule[pointer->type->Z] != 0)  // this would indicate an error
    776     ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element
    777   else
    778     DoeLog(1) && (eLog()<< Verbose(1) << "Atom " << pointer->getName() << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl);
    779   if (ElementsInMolecule[pointer->type->Z] == 0)  // was last atom of this element?
    780     ElementCount--;
     792  formula-=pointer->type;
    781793  erase(pointer);
    782794  return true;
     
    790802  for (molecule::iterator iter = begin(); !empty(); iter = begin())
    791803      erase(iter);
     804  return empty();
    792805};
    793806
     
    835848bool molecule::CheckBounds(const Vector *x) const
    836849{
    837   double * const cell_size = World::getInstance().getDomain();
     850  const Matrix &domain = World::getInstance().getDomain().getM();
    838851  bool result = true;
    839   int j =-1;
    840852  for (int i=0;i<NDIM;i++) {
    841     j += i+1;
    842     result = result && ((x->at(i) >= 0) && (x->at(i) < cell_size[j]));
     853    result = result && ((x->at(i) >= 0) && (x->at(i) < domain.at(i,i)));
    843854  }
    844855  //return result;
     
    849860 * \param *out output stream
    850861 */
    851 bool molecule::Output(ofstream * const output)
    852 {
    853   int ElementNo[MAX_ELEMENTS], AtomNo[MAX_ELEMENTS];
    854   CountElements();
    855 
    856   for (int i=0;i<MAX_ELEMENTS;++i) {
    857     AtomNo[i] = 0;
    858     ElementNo[i] = 0;
    859   }
     862bool molecule::Output(ostream * const output)
     863{
    860864  if (output == NULL) {
    861865    return false;
    862866  } else {
     867    int AtomNo[MAX_ELEMENTS];
     868    memset(AtomNo,0,(MAX_ELEMENTS-1)*sizeof(*AtomNo));
     869    enumeration<const element*> elementLookup = formula.enumerateElements();
     870    for(map<const element*,unsigned int>::iterator iter=elementLookup.there.begin();
     871        iter!=elementLookup.there.end();++iter){
     872      cout << "Enumerated element " << *iter->first << " with number " << iter->second << endl;
     873    }
    863874    *output << "#Ion_TypeNr._Nr.R[0]    R[1]    R[2]    MoveType (0 MoveIon, 1 FixedIon)" << endl;
    864     SetIndexedArrayForEachAtomTo ( ElementNo, &element::Z, &AbsoluteValue, 1);
    865     int current=1;
    866     for (int i=0;i<MAX_ELEMENTS;++i) {
    867       if (ElementNo[i] == 1)
    868         ElementNo[i] = current++;
    869     }
    870     ActOnAllAtoms( &atom::OutputArrayIndexed, output, (const int *)ElementNo, (int *)AtomNo, (const char *) NULL );
     875    for_each(atoms.begin(),atoms.end(),boost::bind(&atom::OutputArrayIndexed,_1,output,elementLookup,AtomNo,(const char*)0));
    871876    return true;
    872877  }
     
    879884{
    880885  int ElementNo[MAX_ELEMENTS], AtomNo[MAX_ELEMENTS];
    881   CountElements();
    882886
    883887  if (output == NULL) {
     
    912916{
    913917  DoLog(2) && (Log() << Verbose(2) << endl << "From Contents of ListOfBonds, all non-hydrogen atoms:" << endl);
    914   ActOnAllAtoms (&atom::OutputBondOfAtom );
     918  for_each(atoms.begin(),atoms.end(),mem_fun(&atom::OutputBondOfAtom));
    915919  DoLog(0) && (Log() << Verbose(0) << endl);
    916920};
     
    921925bool molecule::Checkout(ofstream * const output)  const
    922926{
    923   return elemente->Checkout(output, ElementsInMolecule);
     927  return formula.checkOut(output);
    924928};
    925929
     
    935939    for (int step=0;step<MDSteps;step++) {
    936940      *output << getAtomCount() << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);
    937       ActOnAllAtoms( &atom::OutputTrajectoryXYZ, output, step );
     941      for_each(atoms.begin(),atoms.end(),boost::bind(&atom::OutputTrajectoryXYZ,_1,output,step));
    938942    }
    939943    return true;
     
    952956    now = time((time_t *)NULL);   // Get the system time and put it into 'now' as 'calender time'
    953957    *output << getAtomCount() << "\n\tCreated by molecuilder on " << ctime(&now);
    954     ActOnAllAtoms( &atom::OutputXYZLine, output );
     958    for_each(atoms.begin(),atoms.end(),bind2nd(mem_fun(&atom::OutputXYZLine),output));
    955959    return true;
    956960  } else
     
    979983};
    980984
    981 /** Brings molecule::ElementCount and molecule::ElementsInMolecule up-to-date.
    982  */
    983 void molecule::CountElements()
    984 {
    985   for(int i=MAX_ELEMENTS;i--;)
    986     ElementsInMolecule[i] = 0;
    987   ElementCount = 0;
    988 
    989   SetIndexedArrayForEachAtomTo ( ElementsInMolecule, &element::Z, &Increment, 1);
    990 
    991   for(int i=MAX_ELEMENTS;i--;)
    992     ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0);
    993 };
    994 
    995 
    996 /** Counts necessary number of valence electrons and returns number and SpinType.
    997  * \param configuration containing everything
    998  */
    999 void molecule::CalculateOrbitals(class config &configuration)
    1000 {
    1001   configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0;
    1002   for(int i=MAX_ELEMENTS;i--;) {
    1003     if (ElementsInMolecule[i] != 0) {
    1004       //Log() << Verbose(0) << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl;
    1005       configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence);
    1006     }
    1007   }
    1008   configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2);
    1009   configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2;
    1010   configuration.MaxPsiDouble /= 2;
    1011   configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1;
    1012   if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) {
    1013     configuration.ProcPEGamma /= 2;
    1014     configuration.ProcPEPsi *= 2;
    1015   } else {
    1016     configuration.ProcPEGamma *= configuration.ProcPEPsi;
    1017     configuration.ProcPEPsi = 1;
    1018   }
    1019   configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble;
    1020 };
    1021 
    1022985/** Determines whether two molecules actually contain the same atoms and coordination.
    1023986 * \param *out output stream for debugging
     
    10381001  /// first count both their atoms and elements and update lists thereby ...
    10391002  //Log() << Verbose(0) << "Counting atoms, updating list" << endl;
    1040   CountElements();
    1041   OtherMolecule->CountElements();
    10421003
    10431004  /// ... and compare:
     
    10491010    } else Log() << Verbose(4) << "AtomCounts match: " << getAtomCount() << " == " << OtherMolecule->getAtomCount() << endl;
    10501011  }
    1051   /// -# ElementCount
     1012  /// -# Formula
    10521013  if (result) {
    1053     if (ElementCount != OtherMolecule->ElementCount) {
    1054       DoLog(4) && (Log() << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl);
     1014    if (formula != OtherMolecule->formula) {
     1015      DoLog(4) && (Log() << Verbose(4) << "Formulas don't match: " << formula << " == " << OtherMolecule->formula << endl);
    10551016      result = false;
    1056     } else Log() << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
    1057   }
    1058   /// -# ElementsInMolecule
    1059   if (result) {
    1060     for (flag=MAX_ELEMENTS;flag--;) {
    1061       //Log() << Verbose(5) << "Element " <<  flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;
    1062       if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag])
    1063         break;
    1064     }
    1065     if (flag < MAX_ELEMENTS) {
    1066       DoLog(4) && (Log() << Verbose(4) << "ElementsInMolecule don't match." << endl);
    1067       result = false;
    1068     } else Log() << Verbose(4) << "ElementsInMolecule match." << endl;
     1017    } else Log() << Verbose(4) << "Formulas match: " << formula << " == " << OtherMolecule->formula << endl;
    10691018  }
    10701019  /// then determine and compare center of gravity for each molecule ...
Note: See TracChangeset for help on using the changeset viewer.