Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/World.cpp

    rb9c847 r3839e5  
    99
    1010#include "World.hpp"
     11
     12#include <functional>
    1113
    1214#include "atom.hpp"
     
    2224#include "Actions/ManipulateAtomsProcess.hpp"
    2325#include "Helpers/Assert.hpp"
     26#include "Box.hpp"
     27#include "Matrix.hpp"
     28#include "defs.hpp"
    2429
    2530#include "Patterns/Singleton_impl.hpp"
     31#include "Patterns/ObservedContainer_impl.hpp"
    2632
    2733using namespace std;
     
    7480// system
    7581
    76 double * World::getDomain() {
    77   return cell_size;
     82Box& World::getDomain() {
     83  return *cell_size;
     84}
     85
     86void World::setDomain(const Matrix &mat){
     87  *cell_size = mat;
    7888}
    7989
    8090void World::setDomain(double * matrix)
    8191{
    82   OBSERVE;
    83   cell_size[0] = matrix[0];
    84   cell_size[1] = matrix[1];
    85   cell_size[2] = matrix[2];
    86   cell_size[3] = matrix[3];
    87   cell_size[4] = matrix[4];
    88   cell_size[5] = matrix[5];
     92  Matrix M = ReturnFullMatrixforSymmetric(matrix);
     93  cell_size->setM(M);
    8994}
    9095
     
    119124  molecule *mol = NULL;
    120125  mol = NewMolecule();
    121   ASSERT(!molecules.count(currMoleculeId),"currMoleculeId did not specify an unused ID");
    122   mol->setId(currMoleculeId++);
     126  moleculeId_t id = getNextMoleculeId();
     127  ASSERT(!molecules.count(id),"proposed id did not specify an unused ID");
     128  mol->setId(id);
    123129  // store the molecule by ID
    124130  molecules[mol->getId()] = mol;
     
    138144  DeleteMolecule(mol);
    139145  molecules.erase(id);
    140 }
    141 
    142 double *World::cell_size = NULL;
     146  releaseMoleculeId(id);
     147}
    143148
    144149atom *World::createAtom(){
    145150  OBSERVE;
    146151  atomId_t id = getNextAtomId();
     152  ASSERT(!atoms.count(id),"proposed id did not specify an unused ID");
    147153  atom *res = NewAtom(id);
    148154  res->setWorld(this);
     
    221227
    222228atomId_t World::getNextAtomId(){
    223   // see if we can reuse some Id
    224   if(atomIdPool.empty()){
    225     return currAtomId++;
    226   }
    227   else{
    228     // we give out the first ID from the pool
    229     atomId_t id = *(atomIdPool.begin());
    230     atomIdPool.erase(id);
     229  // try to find an Id in the pool;
     230  if(!atomIdPool.empty()){
     231    atomIdPool_t::iterator iter=atomIdPool.begin();
     232    atomId_t id = iter->first;
     233    pair<atomId_t,atomId_t> newRange = make_pair(id+1,iter->second);
     234    // we wont use this iterator anymore, so we don't care about invalidating
     235    atomIdPool.erase(iter);
     236    if(newRange.first<newRange.second){
     237      atomIdPool.insert(newRange);
     238    }
    231239    return id;
    232240  }
     241  // Nothing in the pool... we are out of luck
     242  return currAtomId++;
    233243}
    234244
    235245void World::releaseAtomId(atomId_t id){
    236   atomIdPool.insert(id);
    237   // defragmentation of the pool
    238   set<atomId_t>::reverse_iterator iter;
    239   // go through all Ids in the pool that lie immediately below the border
    240   while(!atomIdPool.empty() && *(atomIdPool.rbegin())==(currAtomId-1)){
    241     atomIdPool.erase(--currAtomId);
    242   }
     246  atomIdPool.insert(make_pair(id,id+1));
     247  defragAtomIdPool();
    243248}
    244249
    245250bool World::reserveAtomId(atomId_t id){
    246251  if(id>=currAtomId ){
    247     // add all ids between the new one and current border as available
    248     for(atomId_t pos=currAtomId; pos<id; ++pos){
    249       atomIdPool.insert(pos);
     252    pair<atomId_t,atomId_t> newRange = make_pair(currAtomId,id);
     253    if(newRange.first<newRange.second){
     254      atomIdPool.insert(newRange);
    250255    }
    251256    currAtomId=id+1;
     257    defragAtomIdPool();
    252258    return true;
    253259  }
    254   else if(atomIdPool.count(id)){
    255     atomIdPool.erase(id);
     260  // look for a range that matches the request
     261  for(atomIdPool_t::iterator iter=atomIdPool.begin();iter!=atomIdPool.end();++iter){
     262    if(iter->first>id){
     263      // we have coverd all available ranges... nothing to be found here
     264      break;
     265    }
     266    // no need to check first, since it has to be <=id, since otherwise we would have broken out
     267    if(iter->second > id){
     268      // we found a matching range... get the id from this range
     269
     270      // split up this range at the point of id
     271      pair<atomId_t,atomId_t> bottomRange = make_pair(iter->first,id);
     272      pair<atomId_t,atomId_t> topRange = make_pair(id+1,iter->second);
     273      // remove this range
     274      atomIdPool.erase(iter);
     275      if(bottomRange.first<bottomRange.second){
     276        atomIdPool.insert(bottomRange);
     277      }
     278      if(topRange.first<topRange.second){
     279        atomIdPool.insert(topRange);
     280      }
     281      defragAtomIdPool();
     282      return true;
     283    }
     284  }
     285  // this ID could not be reserved
     286  return false;
     287}
     288
     289void World::defragAtomIdPool(){
     290  // check if the situation is bad enough to make defragging neccessary
     291  if((numAtomDefragSkips<MAX_FRAGMENTATION_SKIPS) &&
     292     (atomIdPool.size()<lastAtomPoolSize+MAX_POOL_FRAGMENTATION)){
     293    ++numAtomDefragSkips;
     294    return;
     295  }
     296  for(atomIdPool_t::iterator iter = atomIdPool.begin();iter!=atomIdPool.end();){
     297    // see if this range is adjacent to the next one
     298    atomIdPool_t::iterator next = iter;
     299    next++;
     300    if(next!=atomIdPool.end() && (next->first==iter->second)){
     301      // merge the two ranges
     302      pair<atomId_t,atomId_t> newRange = make_pair(iter->first,next->second);
     303      atomIdPool.erase(iter);
     304      atomIdPool.erase(next);
     305      pair<atomIdPool_t::iterator,bool> res = atomIdPool.insert(newRange);
     306      ASSERT(res.second,"Id-Pool was confused");
     307      iter=res.first;
     308      continue;
     309    }
     310    ++iter;
     311  }
     312  if(!atomIdPool.empty()){
     313    // check if the last range is at the border
     314    atomIdPool_t::iterator iter = atomIdPool.end();
     315    iter--;
     316    if(iter->second==currAtomId){
     317      currAtomId=iter->first;
     318      atomIdPool.erase(iter);
     319    }
     320  }
     321  lastAtomPoolSize=atomIdPool.size();
     322  numAtomDefragSkips=0;
     323}
     324
     325// Molecules
     326
     327moleculeId_t World::getNextMoleculeId(){
     328  // try to find an Id in the pool;
     329  if(!moleculeIdPool.empty()){
     330    moleculeIdPool_t::iterator iter=moleculeIdPool.begin();
     331    moleculeId_t id = iter->first;
     332    pair<moleculeId_t,moleculeId_t> newRange = make_pair(id+1,iter->second);
     333    // we wont use this iterator anymore, so we don't care about invalidating
     334    moleculeIdPool.erase(iter);
     335    if(newRange.first<newRange.second){
     336      moleculeIdPool.insert(newRange);
     337    }
     338    return id;
     339  }
     340  // Nothing in the pool... we are out of luck
     341  return currMoleculeId++;
     342}
     343
     344void World::releaseMoleculeId(moleculeId_t id){
     345  moleculeIdPool.insert(make_pair(id,id+1));
     346  defragMoleculeIdPool();
     347}
     348
     349bool World::reserveMoleculeId(moleculeId_t id){
     350  if(id>=currMoleculeId ){
     351    pair<moleculeId_t,moleculeId_t> newRange = make_pair(currMoleculeId,id);
     352    if(newRange.first<newRange.second){
     353      moleculeIdPool.insert(newRange);
     354    }
     355    currMoleculeId=id+1;
     356    defragMoleculeIdPool();
    256357    return true;
    257358  }
    258   else{
    259     // this ID could not be reserved
    260     return false;
    261   }
     359  // look for a range that matches the request
     360  for(moleculeIdPool_t::iterator iter=moleculeIdPool.begin();iter!=moleculeIdPool.end();++iter){
     361    if(iter->first>id){
     362      // we have coverd all available ranges... nothing to be found here
     363      break;
     364    }
     365    // no need to check first, since it has to be <=id, since otherwise we would have broken out
     366    if(iter->second > id){
     367      // we found a matching range... get the id from this range
     368
     369      // split up this range at the point of id
     370      pair<moleculeId_t,moleculeId_t> bottomRange = make_pair(iter->first,id);
     371      pair<moleculeId_t,moleculeId_t> topRange = make_pair(id+1,iter->second);
     372      // remove this range
     373      moleculeIdPool.erase(iter);
     374      if(bottomRange.first<bottomRange.second){
     375        moleculeIdPool.insert(bottomRange);
     376      }
     377      if(topRange.first<topRange.second){
     378        moleculeIdPool.insert(topRange);
     379      }
     380      defragMoleculeIdPool();
     381      return true;
     382    }
     383  }
     384  // this ID could not be reserved
     385  return false;
     386}
     387
     388void World::defragMoleculeIdPool(){
     389  // check if the situation is bad enough to make defragging neccessary
     390  if((numMoleculeDefragSkips<MAX_FRAGMENTATION_SKIPS) &&
     391     (moleculeIdPool.size()<lastMoleculePoolSize+MAX_POOL_FRAGMENTATION)){
     392    ++numMoleculeDefragSkips;
     393    return;
     394  }
     395  for(moleculeIdPool_t::iterator iter = moleculeIdPool.begin();iter!=moleculeIdPool.end();){
     396    // see if this range is adjacent to the next one
     397    moleculeIdPool_t::iterator next = iter;
     398    next++;
     399    if(next!=moleculeIdPool.end() && (next->first==iter->second)){
     400      // merge the two ranges
     401      pair<moleculeId_t,moleculeId_t> newRange = make_pair(iter->first,next->second);
     402      moleculeIdPool.erase(iter);
     403      moleculeIdPool.erase(next);
     404      pair<moleculeIdPool_t::iterator,bool> res = moleculeIdPool.insert(newRange);
     405      ASSERT(res.second,"Id-Pool was confused");
     406      iter=res.first;
     407      continue;
     408    }
     409    ++iter;
     410  }
     411  if(!moleculeIdPool.empty()){
     412    // check if the last range is at the border
     413    moleculeIdPool_t::iterator iter = moleculeIdPool.end();
     414    iter--;
     415    if(iter->second==currMoleculeId){
     416      currMoleculeId=iter->first;
     417      moleculeIdPool.erase(iter);
     418    }
     419  }
     420  lastMoleculePoolSize=moleculeIdPool.size();
     421  numMoleculeDefragSkips=0;
     422}
     423
     424/******************************* Iterators ********************************/
     425
     426// external parts with observers
     427
     428CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet,AtomDescriptor);
     429
     430World::AtomIterator
     431World::getAtomIter(AtomDescriptor descr){
     432    return AtomIterator(descr,atoms);
     433}
     434
     435World::AtomIterator
     436World::getAtomIter(){
     437    return AtomIterator(AllAtoms(),atoms);
     438}
     439
     440World::AtomIterator
     441World::atomEnd(){
     442  return AtomIterator(AllAtoms(),atoms,atoms.end());
     443}
     444
     445CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor);
     446
     447World::MoleculeIterator
     448World::getMoleculeIter(MoleculeDescriptor descr){
     449    return MoleculeIterator(descr,molecules);
     450}
     451
     452World::MoleculeIterator
     453World::getMoleculeIter(){
     454    return MoleculeIterator(AllMolecules(),molecules);
     455}
     456
     457World::MoleculeIterator
     458World::moleculeEnd(){
     459  return MoleculeIterator(AllMolecules(),molecules,molecules.end());
     460}
     461
     462// Internal parts, without observers
     463
     464// Build the AtomIterator from template
     465CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet::set_t,AtomDescriptor);
     466
     467
     468World::internal_AtomIterator
     469World::getAtomIter_internal(AtomDescriptor descr){
     470  return internal_AtomIterator(descr,atoms.getContent());
     471}
     472
     473World::internal_AtomIterator
     474World::atomEnd_internal(){
     475  return internal_AtomIterator(AllAtoms(),atoms.getContent(),atoms.end_internal());
     476}
     477
     478// build the MoleculeIterator from template
     479CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet::set_t,MoleculeDescriptor);
     480
     481World::internal_MoleculeIterator World::getMoleculeIter_internal(MoleculeDescriptor descr){
     482  return internal_MoleculeIterator(descr,molecules.getContent());
     483}
     484
     485World::internal_MoleculeIterator World::moleculeEnd_internal(){
     486  return internal_MoleculeIterator(AllMolecules(),molecules.getContent(),molecules.end_internal());
     487}
     488
     489/************************** Selection of Atoms and molecules ******************/
     490
     491// Atoms
     492
     493void World::clearAtomSelection(){
     494  selectedAtoms.clear();
     495}
     496
     497void World::selectAtom(atom *atom){
     498  ASSERT(atom,"Invalid pointer in selection of atom");
     499  selectedAtoms[atom->getId()]=atom;
     500}
     501
     502void World::selectAtom(atomId_t id){
     503  ASSERT(atoms.count(id),"Atom Id selected that was not in the world");
     504  selectedAtoms[id]=atoms[id];
     505}
     506
     507void World::selectAllAtoms(AtomDescriptor descr){
     508  internal_AtomIterator begin = getAtomIter_internal(descr);
     509  internal_AtomIterator end = atomEnd_internal();
     510  void (World::*func)(atom*) = &World::selectAtom; // needed for type resolution of overloaded function
     511  for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
     512}
     513
     514void World::selectAtomsOfMolecule(molecule *_mol){
     515  ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
     516  // need to make it const to get the fast iterators
     517  const molecule *mol = _mol;
     518  void (World::*func)(atom*) = &World::selectAtom; // needed for type resolution of overloaded function
     519  for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is select... see above
     520}
     521
     522void World::selectAtomsOfMolecule(moleculeId_t id){
     523  ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
     524  selectAtomsOfMolecule(molecules[id]);
     525}
     526
     527void World::unselectAtom(atom *atom){
     528  ASSERT(atom,"Invalid pointer in unselection of atom");
     529  unselectAtom(atom->getId());
     530}
     531
     532void World::unselectAtom(atomId_t id){
     533  ASSERT(atoms.count(id),"Atom Id unselected that was not in the world");
     534  selectedAtoms.erase(id);
     535}
     536
     537void World::unselectAllAtoms(AtomDescriptor descr){
     538  internal_AtomIterator begin = getAtomIter_internal(descr);
     539  internal_AtomIterator end = atomEnd_internal();
     540  void (World::*func)(atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
     541  for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
     542}
     543
     544void World::unselectAtomsOfMolecule(molecule *_mol){
     545  ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
     546  // need to make it const to get the fast iterators
     547  const molecule *mol = _mol;
     548  void (World::*func)(atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
     549  for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is unsselect... see above
     550}
     551
     552void World::unselectAtomsOfMolecule(moleculeId_t id){
     553  ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
     554  unselectAtomsOfMolecule(molecules[id]);
    262555}
    263556
    264557// Molecules
    265558
    266 /******************************* Iterators ********************************/
    267 
    268 // Build the AtomIterator from template
    269 CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet,AtomDescriptor);
    270 
    271 
    272 World::AtomIterator World::getAtomIter(AtomDescriptor descr){
    273   return AtomIterator(descr,atoms);
    274 }
    275 
    276 World::AtomIterator World::atomEnd(){
    277   return AtomIterator(AllAtoms(),atoms,atoms.end());
    278 }
    279 
    280 // build the MoleculeIterator from template
    281 CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor);
    282 
    283 World::MoleculeIterator World::getMoleculeIter(MoleculeDescriptor descr){
    284   return MoleculeIterator(descr,molecules);
    285 }
    286 
    287 World::MoleculeIterator World::moleculeEnd(){
    288   return MoleculeIterator(AllMolecules(),molecules,molecules.end());
     559void World::clearMoleculeSelection(){
     560  selectedMolecules.clear();
     561}
     562
     563void World::selectMolecule(molecule *mol){
     564  ASSERT(mol,"Invalid pointer to molecule in selection");
     565  selectedMolecules[mol->getId()]=mol;
     566}
     567
     568void World::selectMolecule(moleculeId_t id){
     569  ASSERT(molecules.count(id),"Molecule Id selected that was not in the world");
     570  selectedMolecules[id]=molecules[id];
     571}
     572
     573void World::selectAllMoleculess(MoleculeDescriptor descr){
     574  internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
     575  internal_MoleculeIterator end = moleculeEnd_internal();
     576  void (World::*func)(molecule*) = &World::selectMolecule; // needed for type resolution of overloaded function
     577  for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
     578}
     579
     580void World::selectMoleculeOfAtom(atom *atom){
     581  ASSERT(atom,"Invalid atom pointer in selection of MoleculeOfAtom");
     582  molecule *mol=atom->getMolecule();
     583  // the atom might not be part of a molecule
     584  if(mol){
     585    selectMolecule(mol);
     586  }
     587}
     588
     589void World::selectMoleculeOfAtom(atomId_t id){
     590  ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
     591  selectMoleculeOfAtom(atoms[id]);
     592}
     593
     594void World::unselectMolecule(molecule *mol){
     595  ASSERT(mol,"invalid pointer in unselection of molecule");
     596  unselectMolecule(mol->getId());
     597}
     598
     599void World::unselectMolecule(moleculeId_t id){
     600  ASSERT(molecules.count(id),"No such molecule with ID in unselection");
     601  selectedMolecules.erase(id);
     602}
     603
     604void World::unselectAllMoleculess(MoleculeDescriptor descr){
     605  internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
     606  internal_MoleculeIterator end = moleculeEnd_internal();
     607  void (World::*func)(molecule*) = &World::unselectMolecule; // needed for type resolution of overloaded function
     608  for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
     609}
     610
     611void World::unselectMoleculeOfAtom(atom *atom){
     612  ASSERT(atom,"Invalid atom pointer in selection of MoleculeOfAtom");
     613  molecule *mol=atom->getMolecule();
     614  // the atom might not be part of a molecule
     615  if(mol){
     616    unselectMolecule(mol);
     617  }
     618}
     619
     620void World::unselectMoleculeOfAtom(atomId_t id){
     621  ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
     622  unselectMoleculeOfAtom(atoms[id]);
     623}
     624
     625/******************* Iterators over Selection *****************************/
     626World::AtomSelectionIterator World::beginAtomSelection(){
     627  return selectedAtoms.begin();
     628}
     629
     630World::AtomSelectionIterator World::endAtomSelection(){
     631  return selectedAtoms.end();
     632}
     633
     634
     635World::MoleculeSelectionIterator World::beginMoleculeSelection(){
     636  return selectedMolecules.begin();
     637}
     638
     639World::MoleculeSelectionIterator World::endMoleculeSelection(){
     640  return selectedMolecules.end();
    289641}
    290642
     
    297649    Thermostats(new ThermoStatContainer),
    298650    ExitFlag(0),
    299     atoms(),
     651    atoms(this),
     652    selectedAtoms(this),
    300653    currAtomId(0),
    301     molecules(),
     654    lastAtomPoolSize(0),
     655    numAtomDefragSkips(0),
     656    molecules(this),
     657    selectedMolecules(this),
    302658    currMoleculeId(0),
    303659    molecules_deprecated(new MoleculeListClass(this))
    304660{
    305   cell_size = new double[6];
    306   cell_size[0] = 20.;
    307   cell_size[1] = 0.;
    308   cell_size[2] = 20.;
    309   cell_size[3] = 0.;
    310   cell_size[4] = 0.;
    311   cell_size[5] = 20.;
     661  cell_size = new Box;
     662  Matrix domain;
     663  domain.at(0,0) = 20;
     664  domain.at(1,1) = 20;
     665  domain.at(2,2) = 20;
     666  cell_size->setM(domain);
    312667  defaultName = "none";
    313668  molecules_deprecated->signOn(this);
     
    317672{
    318673  molecules_deprecated->signOff(this);
    319   delete[] cell_size;
     674  delete cell_size;
    320675  delete molecules_deprecated;
    321676  delete periode;
Note: See TracChangeset for help on using the changeset viewer.