source: src/World.cpp@ e4b9d5

Candidate_v1.7.1 stable
Last change on this file since e4b9d5 was 25aa214, checked in by Frederik Heber <frederik.heber@…>, 2 weeks ago

FIX: fragmentation hydrogens do not trigger AtomInserted.

  • we had already switched off position and element changes. However, the fragmentation hydrogens could still be briefly seen on creation because the AtomInserted notification is still triggered. The World::createAtom allows now to suppress the notifcation. The switch options are put into an enum to make them very verbose in the code. This should really only be used by the HydrogenPool.
  • Property mode set to 100644
File size: 33.3 KB
RevLine 
[bcf653]1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
[0aa122]4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
[5aaa43]5 * Copyright (C) 2013 Frederik Heber. All rights reserved.
[94d5ac6]6 *
7 *
8 * This file is part of MoleCuilder.
9 *
10 * MoleCuilder is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * MoleCuilder is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
[bcf653]22 */
23
[5d1611]24/*
25 * World.cpp
26 *
27 * Created on: Feb 3, 2010
28 * Author: crueger
29 */
30
[bf3817]31// include config.h
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
[9eb71b3]36//#include "CodePatterns/MemDebug.hpp"
[112b09]37
[5d1611]38#include "World.hpp"
39
[90c4280]40#include <functional>
[5d1611]41
[3139b2]42#include "Actions/ActionTrait.hpp"
[d297a3]43#include "Actions/ManipulateAtomsProcess.hpp"
[6f0841]44#include "Atom/atom.hpp"
[d297a3]45#include "Box.hpp"
46#include "CodePatterns/Assert.hpp"
[8e1f7af]47#include "config.hpp"
[fc1b24]48#include "Descriptors/AtomDescriptor.hpp"
[865a945]49#include "Descriptors/AtomDescriptor_impl.hpp"
[c1d837]50#include "Descriptors/AtomIdDescriptor.hpp"
[ebc499]51#include "Descriptors/AtomSelectionDescriptor.hpp"
[1c51c8]52#include "Descriptors/MoleculeDescriptor.hpp"
53#include "Descriptors/MoleculeDescriptor_impl.hpp"
[c1d837]54#include "Descriptors/MoleculeIdDescriptor.hpp"
[ebc499]55#include "Descriptors/MoleculeSelectionDescriptor.hpp"
[feb5d0]56#include "Descriptors/SelectiveConstIterator_impl.hpp"
[6e97e5]57#include "Descriptors/SelectiveIterator_impl.hpp"
[42127c]58#include "Element/periodentafel.hpp"
[98dbee]59#include "Fragmentation/Homology/HomologyContainer.hpp"
[3139b2]60#include "Graph/BondGraph.hpp"
[4b8630]61#include "Graph/DepthFirstSearchAnalysis.hpp"
[e4fe8d]62#include "Helpers/defs.hpp"
[d297a3]63#include "LinearAlgebra/RealSpaceMatrix.hpp"
[4834f4]64#include "LinkedCell/LinkedCell_Controller.hpp"
65#include "LinkedCell/PointCloudAdaptor.hpp"
[d297a3]66#include "molecule.hpp"
[ab26c3]67#include "Thermostats/ThermoStatContainer.hpp"
[d297a3]68#include "WorldTime.hpp"
[d346b6]69
[3e4fb6]70#include "IdPool_impl.hpp"
71
[4834f4]72#include "CodePatterns/IteratorAdaptors.hpp"
[ad011c]73#include "CodePatterns/Singleton_impl.hpp"
[02ce36]74#include "CodePatterns/Observer/Channels.hpp"
75#include "CodePatterns/Observer/ObservedContainer_impl.hpp"
[23b547]76
[ce7fdc]77using namespace MoleCuilder;
[4d9c01]78
[7188b1]79/******************************* Notifications ************************/
80
81
82atom* World::_lastchangedatom = NULL;
[fb95a5]83atomId_t World::_lastchangedatomid = -1;
[7188b1]84molecule* World::_lastchangedmol = NULL;
[fb95a5]85moleculeId_t World::_lastchangedmolid = -1;
[7188b1]86
[5d1611]87/******************************* getter and setter ************************/
[f71baf]88periodentafel *&World::getPeriode()
89{
[5d1611]90 return periode;
91}
92
[f71baf]93BondGraph *&World::getBondGraph()
94{
95 return BG;
96}
97
[98dbee]98HomologyContainer &World::getHomologies()
99{
100 return *homologies;
101}
102
103void World::resetHomologies(HomologyContainer *&_homologies)
104{
105 HomologyContainer *oldhomologies = homologies;
106
107 // install new instance, resetting given pointer
108 homologies = _homologies;
109 _homologies = NULL;
110
111 // delete old instance which also informs all observers
112 delete oldhomologies;
113}
114
[f71baf]115void World::setBondGraph(BondGraph *_BG){
116 delete (BG);
117 BG = _BG;
118}
119
[8e1f7af]120config *&World::getConfig(){
121 return configuration;
122}
123
[1c51c8]124// Atoms
125
[7a1ce5]126atom* World::getAtom(AtomDescriptor descriptor){
[fc1b24]127 return descriptor.find();
128}
129
[795c0f]130const atom* World::getAtom(AtomDescriptor descriptor) const{
131 return const_cast<const AtomDescriptor &>(descriptor).find();
132}
133
[4d72e4]134World::AtomComposite World::getAllAtoms(AtomDescriptor descriptor){
[fc1b24]135 return descriptor.findAll();
136}
137
[795c0f]138World::ConstAtomComposite World::getAllAtoms(AtomDescriptor descriptor) const {
139 return const_cast<const AtomDescriptor &>(descriptor).findAll();
140}
141
[4d72e4]142World::AtomComposite World::getAllAtoms(){
[0e2a47]143 return getAllAtoms(AllAtoms());
144}
145
[795c0f]146World::ConstAtomComposite World::getAllAtoms() const {
147 return getAllAtoms(AllAtoms());
148}
149
150int World::numAtoms() const {
[354859]151 return atoms.size();
152}
153
[1c51c8]154// Molecules
155
156molecule *World::getMolecule(MoleculeDescriptor descriptor){
157 return descriptor.find();
158}
159
[97445f]160const molecule *World::getMolecule(MoleculeDescriptor descriptor) const {
161 return const_cast<const MoleculeDescriptor &>(descriptor).find();
162}
163
[1c51c8]164std::vector<molecule*> World::getAllMolecules(MoleculeDescriptor descriptor){
165 return descriptor.findAll();
166}
167
[97445f]168std::vector<const molecule*> World::getAllMolecules(MoleculeDescriptor descriptor) const {
169 return const_cast<const MoleculeDescriptor &>(descriptor).findAll();
170}
171
[97ebf8]172std::vector<molecule*> World::getAllMolecules(){
173 return getAllMolecules(AllMolecules());
174}
175
[97445f]176std::vector<const molecule*> World::getAllMolecules() const {
177 return getAllMolecules(AllMolecules());
178}
179
180int World::numMolecules() const {
[2affd1]181 return molecules.size();
[354859]182}
183
[5f612ee]184// system
185
[84c494]186Box& World::getDomain() {
187 return *cell_size;
188}
189
[cca9ef]190void World::setDomain(const RealSpaceMatrix &mat){
[be97a8]191 OBSERVE;
[84c494]192 *cell_size = mat;
[5f612ee]193}
194
195void World::setDomain(double * matrix)
196{
[b9c847]197 OBSERVE;
[cca9ef]198 RealSpaceMatrix M = ReturnFullMatrixforSymmetric(matrix);
[84c494]199 cell_size->setM(M);
[5f612ee]200}
201
[03abd0]202LinkedCell::LinkedCell_View World::getLinkedCell(double distance)
[4834f4]203{
[d067e35]204 ASSERT( distance >= 0,
[03abd0]205 "World::getLinkedCell() - distance is not positive.");
206 if (distance < 1.) {
207 ELOG(2, "Linked cell grid with length less than 1. is very memory-intense!");
208 distance = 1.;
209 }
[4834f4]210 // we have to grope past the ObservedContainer mechanism and transmorph the map
211 // into a traversable list for the adaptor
212 PointCloudAdaptor< AtomSet::set_t, MapValueIterator<AtomSet::set_t::iterator> > atomset(
213 &(atoms.getContent()),
214 std::string("WorldsAtoms"));
215 return LCcontroller->getView(distance, atomset);
216}
217
[2a8731]218const unsigned World::getTime() const
219{
220 return WorldTime::getTime();
221}
222
[7294dc]223static bool areBondsPresent(const unsigned int _step)
[388ddd]224{
225 bool status = false;
226
227 for (World::AtomConstIterator iter = const_cast<const World &>(World::getInstance()).getAtomIter();
228 (!status) && (iter != const_cast<const World &>(World::getInstance()).atomEnd()); ++iter) {
229 const atom * const Walker = *iter;
230 status |= !Walker->getListOfBondsAtStep(_step).empty();
231 }
232
233 return status;
234}
235
[7294dc]236static bool areAtomsPresent(const unsigned int _step)
237{
238 bool status = false;
239
240 for (World::AtomConstIterator iter = const_cast<const World &>(World::getInstance()).getAtomIter();
241 (!status) && (iter != const_cast<const World &>(World::getInstance()).atomEnd()); ++iter) {
242 const atom * const Walker = *iter;
243 status |= (Walker->getTrajectorySize() >= _step);
244 }
245
246 return status;
247}
248
[9f2071]249static void copyBondgraph(const unsigned int _srcstep, const unsigned int _deststep)
[388ddd]250{
251 // gather all bonds from _srcstep
252 std::set<bond *> SetOfBonds;
253 for (World::AtomConstIterator iter = const_cast<const World &>(World::getInstance()).getAtomIter();
254 iter != const_cast<const World &>(World::getInstance()).atomEnd(); ++iter) {
255 const atom * const Walker = *iter;
256 const BondList bonds = Walker->getListOfBondsAtStep(_srcstep);
257 BOOST_FOREACH( bond::ptr bondptr, bonds) {
258 SetOfBonds.insert(bondptr.get());
259 }
260 }
261 LOG(4, "DEBUG: We gathered " << SetOfBonds.size() << " bonds in total.");
262
263 // copy bond to new time step
264 for (std::set<bond *>::const_iterator bonditer = SetOfBonds.begin();
265 bonditer != SetOfBonds.end(); ++bonditer) {
266 const atom * const Walker = (*bonditer)->leftatom;
267 const atom * const OtherWalker = (*bonditer)->rightatom;
[0763ce]268 bond::ptr const _bond =
269 const_cast<atom *>(Walker)->addBond(_deststep, const_cast<atom *>(OtherWalker));
270 _bond->setDegree((*bonditer)->getDegree());
[388ddd]271 }
272}
273
[7294dc]274//static void copyAtoms(const unsigned int _srcstep, const unsigned int _deststep)
275//{
276// for (World::AtomIterator iter = World::getInstance().getAtomIter();
277// iter != World::getInstance().atomEnd(); ++iter) {
278// atom * const Walker = *iter;
279// Walker->UpdateStep(_deststep);
280// Walker->setPositionAtStep(_deststep, Walker->getPositionAtStep(_srcstep));
281// Walker->setAtomicVelocityAtStep(_deststep, Walker->getAtomicVelocityAtStep(_srcstep));
282// Walker->setAtomicForceAtStep(_deststep, Walker->getAtomicForceAtStep(_srcstep));
283// }
284//}
[9f2071]285
[d297a3]286void World::setTime(const unsigned int _step)
287{
[76163d]288 if (_step != WorldTime::getTime()) {
[388ddd]289 const unsigned int oldstep = WorldTime::getTime();
[46ce1c]290
[7294dc]291// if (!areAtomsPresent(_step))
292// copyAtoms(oldstep, _step);
293
[46ce1c]294 // 1. copy bond graph (such not each addBond causes GUI update)
295 if (!areBondsPresent(_step)) {
296// AtomComposite Set = getAllAtoms();
297// BG->cleanAdjacencyList(Set);
298 copyBondgraph(oldstep, _step);
299 }
300
301 // 2. set new time
[040a5c]302 WorldTime::getInstance().setTime(_step);
[46ce1c]303
304 // 4. scan for connected subgraphs => molecules
[4b8630]305 DepthFirstSearchAnalysis DFS;
306 DFS();
307 DFS.UpdateMoleculeStructure();
[76163d]308 }
[d297a3]309}
310
[387b36]311std::string World::getDefaultName() {
[5f612ee]312 return defaultName;
313}
314
[387b36]315void World::setDefaultName(std::string name)
[5f612ee]316{
[be97a8]317 OBSERVE;
[387b36]318 defaultName = name;
[5f612ee]319};
320
[43dad6]321class ThermoStatContainer * World::getThermostats()
322{
323 return Thermostats;
324}
325
326
[e4b5de]327int World::getExitFlag() {
328 return ExitFlag;
329}
330
331void World::setExitFlag(int flag) {
332 if (ExitFlag < flag)
333 ExitFlag = flag;
334}
[5f612ee]335
[afb47f]336/******************** Methods to change World state *********************/
337
[354859]338molecule* World::createMolecule(){
339 OBSERVE;
340 molecule *mol = NULL;
[cbc5fb]341 mol = NewMolecule();
[3e4fb6]342 moleculeId_t id = moleculeIdPool.getNextId();
[127a8e]343 ASSERT(!molecules.count(id),"proposed id did not specify an unused ID");
344 mol->setId(id);
[244d26]345 // store the molecule by ID
[cbc5fb]346 molecules[mol->getId()] = mol;
[7188b1]347 _lastchangedmol = mol;
[fb95a5]348 _lastchangedmolid = mol->getId();
[7188b1]349 NOTIFY(MoleculeInserted);
[354859]350 return mol;
351}
352
[5cf341]353molecule* World::recreateMolecule(const moleculeId_t &_id)
354{
355 molecule *mol = NULL;
356 if (!molecules.count(_id)) {
357 OBSERVE;
358 mol = NewMolecule();
359 mol->setId(_id);
360 // store the molecule by ID
361 molecules[mol->getId()] = mol;
362 _lastchangedmol = mol;
363 _lastchangedmolid = mol->getId();
364 NOTIFY(MoleculeInserted);
365 }
366 return mol;
367}
368
[cbc5fb]369void World::destroyMolecule(molecule* mol){
[fa7989]370 ASSERT(mol,"Molecule that was meant to be destroyed did not exist");
[cbc5fb]371 destroyMolecule(mol->getId());
372}
373
374void World::destroyMolecule(moleculeId_t id){
375 molecule *mol = molecules[id];
[6d574a]376 ASSERT(mol,"Molecule id that was meant to be destroyed did not exist");
[38f991]377 // give notice about immediate removal
378 {
379 OBSERVE;
380 _lastchangedmol = mol;
[fb95a5]381 _lastchangedmolid = mol->getId();
[38f991]382 NOTIFY(MoleculeRemoved);
383 }
[4965d9f]384 if (isMoleculeSelected(id)) {
[38f991]385 selectedMolecules.erase(id);
[4965d9f]386 NOTIFY(SelectionChanged);
387 }
[f02b53]388 DeleteMolecule(mol);
[7eec64]389 molecules.erase(id);
[3e4fb6]390 moleculeIdPool.releaseId(id);
[cbc5fb]391}
392
[25aa214]393atom *World::createAtom(const CreateAtomNotificationType _notify){
[46d958]394 OBSERVE;
[3e4fb6]395 atomId_t id = atomIdPool.getNextId();
[127a8e]396 ASSERT(!atoms.count(id),"proposed id did not specify an unused ID");
[88d586]397 atom *res = NewAtom(id);
[46d958]398 res->setWorld(this);
[244d26]399 // store the atom by ID
[46d958]400 atoms[res->getId()] = res;
[7188b1]401 _lastchangedatom = res;
[fb95a5]402 _lastchangedatomid = res->getId();
[25aa214]403 if (_notify == NOTIFY_ON_CREATE_ATOM)
404 NOTIFY(AtomInserted);
[46d958]405 return res;
406}
407
[5cf341]408atom *World::recreateAtom(const atomId_t _id){
409 if (!atoms.count(_id)) {
410 OBSERVE;
411 atom *res = NewAtom(_id);
412 res->setWorld(this);
413 // store the atom by ID
414 atoms[res->getId()] = res;
415 _lastchangedatom = res;
416 _lastchangedatomid = res->getId();
417 NOTIFY(AtomInserted);
418 return res;
419 } else
420 return NULL;
421}
422
[5f612ee]423
[46d958]424int World::registerAtom(atom *atom){
425 OBSERVE;
[3e4fb6]426 atomId_t id = atomIdPool.getNextId();
[88d586]427 atom->setId(id);
[46d958]428 atom->setWorld(this);
429 atoms[atom->getId()] = atom;
[65d7ca]430 _lastchangedatom = atom;
[fb95a5]431 _lastchangedatomid = atom->getId();
[65d7ca]432 NOTIFY(AtomInserted);
[46d958]433 return atom->getId();
434}
435
436void World::destroyAtom(atom* atom){
437 int id = atom->getId();
438 destroyAtom(id);
439}
440
[cbc5fb]441void World::destroyAtom(atomId_t id) {
[46d958]442 atom *atom = atoms[id];
[6d574a]443 ASSERT(atom,"Atom ID that was meant to be destroyed did not exist");
[ab4a33]444 // give notice about immediate removal
445 {
446 OBSERVE;
447 _lastchangedatom = atom;
[fb95a5]448 _lastchangedatomid = atom->getId();
[ab4a33]449 NOTIFY(AtomRemoved);
450 }
[a7aebd]451 // check if it's the last atom
[270bdf]452 molecule *_mol = const_cast<molecule *>(atom->getMolecule());
[cad383]453 if ((_mol == NULL) || (_mol->getAtomCount() > 1))
[a7aebd]454 _mol = NULL;
[4965d9f]455 if (isAtomSelected(id)) {
[38f991]456 selectedAtoms.erase(id);
[4965d9f]457 NOTIFY(SelectionChanged);
458 }
[f02b53]459 DeleteAtom(atom);
[59e7996]460 atoms.erase(id);
[3e4fb6]461 atomIdPool.releaseId(id);
[a7aebd]462 // remove molecule if empty
463 if (_mol != NULL)
464 destroyMolecule(_mol);
[88d586]465}
466
467bool World::changeAtomId(atomId_t oldId, atomId_t newId, atom* target){
468 OBSERVE;
469 // in case this call did not originate from inside the atom, we redirect it,
470 // to also let it know that it has changed
471 if(!target){
472 target = atoms[oldId];
[6d574a]473 ASSERT(target,"Atom with that ID not found");
[88d586]474 return target->changeId(newId);
475 }
476 else{
[3e4fb6]477 if(atomIdPool.reserveId(newId)){
[88d586]478 atoms.erase(oldId);
479 atoms.insert(pair<atomId_t,atom*>(newId,target));
480 return true;
481 }
482 else{
483 return false;
484 }
485 }
[46d958]486}
487
[a7a087]488bool World::changeMoleculeId(moleculeId_t oldId, moleculeId_t newId, molecule* target){
489 OBSERVE;
490 // in case this call did not originate from inside the atom, we redirect it,
491 // to also let it know that it has changed
492 if(!target){
493 target = molecules[oldId];
494 ASSERT(target,"Molecule with that ID not found");
495 return target->changeId(newId);
496 }
497 else{
[3e4fb6]498 if(moleculeIdPool.reserveId(newId)){
[a7a087]499 molecules.erase(oldId);
500 molecules.insert(pair<moleculeId_t,molecule*>(newId,target));
501 return true;
502 }
503 else{
504 return false;
505 }
506 }
507}
508
[7c4e29]509ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name,AtomDescriptor descr){
[3139b2]510 ActionTrait manipulateTrait(name);
[126867]511 return new ManipulateAtomsProcess(op, descr,manipulateTrait);
[7c4e29]512}
513
[0e2a47]514ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name){
515 return manipulateAtoms(op,name,AllAtoms());
516}
517
[afb47f]518/********************* Internal Change methods for double Callback and Observer mechanism ********/
519
520void World::doManipulate(ManipulateAtomsProcess *proc){
521 proc->signOn(this);
522 {
523 OBSERVE;
524 proc->doManipulate(this);
525 }
526 proc->signOff(this);
527}
[865a945]528/******************************* Iterators ********************************/
529
[fa0b18]530// external parts with observers
531
[feb5d0]532CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet,AtomDescriptor)
533
534CONSTRUCT_SELECTIVE_CONST_ITERATOR(atom*,World::AtomSet,AtomDescriptor)
[6e97e5]535
[fa0b18]536World::AtomIterator
537World::getAtomIter(AtomDescriptor descr){
538 return AtomIterator(descr,atoms);
539}
[865a945]540
[feb5d0]541World::AtomConstIterator
542World::getAtomIter(AtomDescriptor descr) const{
543 return AtomConstIterator(descr,atoms);
544}
545
[fa0b18]546World::AtomIterator
547World::getAtomIter(){
548 return AtomIterator(AllAtoms(),atoms);
[865a945]549}
[354859]550
[feb5d0]551World::AtomConstIterator
552World::getAtomIter() const{
553 return AtomConstIterator(AllAtoms(),atoms);
554}
555
[fa0b18]556World::AtomIterator
557World::atomEnd(){
[6e97e5]558 return AtomIterator(AllAtoms(),atoms,atoms.end());
[7c4e29]559}
560
[feb5d0]561World::AtomConstIterator
562World::atomEnd() const{
563 return AtomConstIterator(AllAtoms(),atoms,atoms.end());
564}
565
566CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor)
567
568CONSTRUCT_SELECTIVE_CONST_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor)
[6e97e5]569
[5d880e]570World::MoleculeIterator
571World::getMoleculeIter(MoleculeDescriptor descr){
572 return MoleculeIterator(descr,molecules);
573}
574
[feb5d0]575World::MoleculeConstIterator
576World::getMoleculeIter(MoleculeDescriptor descr) const{
577 return MoleculeConstIterator(descr,molecules);
578}
579
[5d880e]580World::MoleculeIterator
581World::getMoleculeIter(){
582 return MoleculeIterator(AllMolecules(),molecules);
[1c51c8]583}
584
[feb5d0]585World::MoleculeConstIterator
586World::getMoleculeIter() const{
587 return MoleculeConstIterator(AllMolecules(),molecules);
588}
589
[5d880e]590World::MoleculeIterator
591World::moleculeEnd(){
[6e97e5]592 return MoleculeIterator(AllMolecules(),molecules,molecules.end());
[1c51c8]593}
594
[feb5d0]595World::MoleculeConstIterator
596World::moleculeEnd() const{
597 return MoleculeConstIterator(AllMolecules(),molecules,molecules.end());
598}
599
[fa0b18]600// Internal parts, without observers
601
602// Build the AtomIterator from template
603CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet::set_t,AtomDescriptor);
604
605
606World::internal_AtomIterator
607World::getAtomIter_internal(AtomDescriptor descr){
608 return internal_AtomIterator(descr,atoms.getContent());
609}
610
611World::internal_AtomIterator
612World::atomEnd_internal(){
613 return internal_AtomIterator(AllAtoms(),atoms.getContent(),atoms.end_internal());
614}
615
[6e97e5]616// build the MoleculeIterator from template
[e3d865]617CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet::set_t,MoleculeDescriptor);
[6e97e5]618
[e3d865]619World::internal_MoleculeIterator World::getMoleculeIter_internal(MoleculeDescriptor descr){
620 return internal_MoleculeIterator(descr,molecules.getContent());
[1c51c8]621}
622
[e3d865]623World::internal_MoleculeIterator World::moleculeEnd_internal(){
624 return internal_MoleculeIterator(AllMolecules(),molecules.getContent(),molecules.end_internal());
[1c51c8]625}
626
[90c4280]627/************************** Selection of Atoms and molecules ******************/
628
[7f1865d]629// translate type's selection member functions to overloaded with specific type
630
631template <class T>
632void World::selectVectorOfInstances(const typename T::iterator _begin, const typename T::iterator _end)
633{
634 std::for_each(_begin,_end,
635 boost::bind(&World::selectInstance<typename T::value_type::second_type>,
636 boost::bind(_take<typename T::value_type::second_type,typename T::value_type>::get, _1)));
637}
638
639template <class T>
640void World::unselectVectorOfInstances(const typename T::iterator _begin, const typename T::iterator _end)
641{
642 std::for_each(_begin,_end,
643 boost::bind(&World::unselectInstance<typename T::value_type::second_type>,
644 boost::bind(_take<typename T::value_type::second_type,typename T::value_type>::get, _1)));
645}
646
[90c4280]647// Atoms
648
649void World::clearAtomSelection(){
[69643a]650 OBSERVE;
651 NOTIFY(SelectionChanged);
[7f1865d]652 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
[90c4280]653 selectedAtoms.clear();
654}
655
[ebc499]656void World::invertAtomSelection(){
657 // get all atoms not selected
658 AtomComposite invertedSelection(getAllAtoms());
659 bool (World::*predicate)(const atom*) const = &World::isSelected; // needed for type resolution of overloaded function
660 AtomComposite::iterator iter =
661 std::remove_if(invertedSelection.begin(), invertedSelection.end(),
662 std::bind1st(std::mem_fun(predicate), this));
663 invertedSelection.erase(iter, invertedSelection.end());
664 // apply new selection
[7f1865d]665 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
[ebc499]666 selectedAtoms.clear();
667 void (World::*selector)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
668 std::for_each(invertedSelection.begin(),invertedSelection.end(),
669 std::bind1st(std::mem_fun(selector),this)); // func is select... see above
670}
671
[cad383]672void World::popAtomSelection(){
[0249ce]673 if (!selectedAtoms_Stack.empty()) {
674 OBSERVE;
675 NOTIFY(SelectionChanged);
676 const atomIdsVector_t atomids = selectedAtoms_Stack.top();
677 boost::function<void (const atomId_t)> IdSelector =
678 boost::bind(static_cast<void (World::*)(const atomId_t)>(&World::selectAtom), this, _1);
679 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
680 selectedAtoms.clear();
681 std::for_each(atomids.begin(),atomids.end(), IdSelector);
682 selectedAtoms_Stack.pop();
683 }
[cad383]684}
685
686void World::pushAtomSelection(){
687 OBSERVE;
688 NOTIFY(SelectionChanged);
[c1d837]689 atomIdsVector_t atomids(countSelectedAtoms(), (atomId_t)-1);
690 std::copy(
691 MapKeyIterator<AtomSelectionConstIterator>(beginAtomSelection()),
692 MapKeyIterator<AtomSelectionConstIterator>(endAtomSelection()),
693 atomids.begin());
694 selectedAtoms_Stack.push( atomids );
[7f1865d]695 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
[cad383]696 selectedAtoms.clear();
697}
698
[e4afb4]699void World::selectAtom(const atom *_atom){
[69643a]700 OBSERVE;
701 NOTIFY(SelectionChanged);
[e4afb4]702 // atom * is unchanged in this function, but we do store entity as changeable
703 ASSERT(_atom,"Invalid pointer in selection of atom");
[7f1865d]704 selectAtom(_atom->getId());
[90c4280]705}
706
[e4afb4]707void World::selectAtom(const atomId_t id){
[69643a]708 OBSERVE;
709 NOTIFY(SelectionChanged);
[90c4280]710 ASSERT(atoms.count(id),"Atom Id selected that was not in the world");
711 selectedAtoms[id]=atoms[id];
[7f1865d]712 atoms[id]->select();
[90c4280]713}
714
715void World::selectAllAtoms(AtomDescriptor descr){
[69643a]716 OBSERVE;
717 NOTIFY(SelectionChanged);
[90c4280]718 internal_AtomIterator begin = getAtomIter_internal(descr);
719 internal_AtomIterator end = atomEnd_internal();
[e4afb4]720 void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
[90c4280]721 for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
722}
723
[e4afb4]724void World::selectAtomsOfMolecule(const molecule *_mol){
[69643a]725 OBSERVE;
726 NOTIFY(SelectionChanged);
[90c4280]727 ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
728 // need to make it const to get the fast iterators
729 const molecule *mol = _mol;
[e4afb4]730 void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
[90c4280]731 for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is select... see above
732}
733
[e4afb4]734void World::selectAtomsOfMolecule(const moleculeId_t id){
[69643a]735 OBSERVE;
736 NOTIFY(SelectionChanged);
[90c4280]737 ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
738 selectAtomsOfMolecule(molecules[id]);
739}
740
[e4afb4]741void World::unselectAtom(const atom *_atom){
[69643a]742 OBSERVE;
743 NOTIFY(SelectionChanged);
[e4afb4]744 ASSERT(_atom,"Invalid pointer in unselection of atom");
745 unselectAtom(_atom->getId());
[61d655e]746}
747
[e4afb4]748void World::unselectAtom(const atomId_t id){
[69643a]749 OBSERVE;
750 NOTIFY(SelectionChanged);
[61d655e]751 ASSERT(atoms.count(id),"Atom Id unselected that was not in the world");
[7f1865d]752 atoms[id]->unselect();
[61d655e]753 selectedAtoms.erase(id);
754}
755
756void World::unselectAllAtoms(AtomDescriptor descr){
[69643a]757 OBSERVE;
758 NOTIFY(SelectionChanged);
[61d655e]759 internal_AtomIterator begin = getAtomIter_internal(descr);
760 internal_AtomIterator end = atomEnd_internal();
[e4afb4]761 void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
[61d655e]762 for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
763}
764
[e4afb4]765void World::unselectAtomsOfMolecule(const molecule *_mol){
[69643a]766 OBSERVE;
767 NOTIFY(SelectionChanged);
[61d655e]768 ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
769 // need to make it const to get the fast iterators
770 const molecule *mol = _mol;
[e4afb4]771 void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
[992bd5]772 for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is unselect... see above
[61d655e]773}
774
[e4afb4]775void World::unselectAtomsOfMolecule(const moleculeId_t id){
[69643a]776 OBSERVE;
777 NOTIFY(SelectionChanged);
[61d655e]778 ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
779 unselectAtomsOfMolecule(molecules[id]);
780}
781
[e472eab]782size_t World::countSelectedAtoms() const {
[eacc3b]783 size_t count = 0;
[e472eab]784 for (AtomSet::const_iterator iter = selectedAtoms.begin(); iter != selectedAtoms.end(); ++iter)
[eacc3b]785 count++;
786 return count;
787}
788
[e4afb4]789bool World::isSelected(const atom *_atom) const {
[7f1865d]790 const bool status = isAtomSelected(_atom->getId());
791 ASSERT( status == _atom->selected,
792 "World::isSelected() - mismatch between selection state in atom "+
793 toString(_atom->getId())+" and World.");
794 return status;
[89643d]795}
796
797bool World::isAtomSelected(const atomId_t no) const {
798 return selectedAtoms.find(no) != selectedAtoms.end();
[e0e156]799}
800
[99db9b]801std::vector<atom *> World::getSelectedAtoms() {
[e472eab]802 std::vector<atom *> returnAtoms;
[99db9b]803 std::transform(
804 selectedAtoms.begin(),
805 selectedAtoms.end(),
806 back_inserter(returnAtoms),
807 _take<atom*,World::AtomSet::value_type>::get);
808 return returnAtoms;
809}
810
811std::vector<const atom *> World::getSelectedAtoms() const {
812 std::vector<const atom *> returnAtoms;
813 std::transform(
814 selectedAtoms.begin(),
815 selectedAtoms.end(),
816 back_inserter(returnAtoms),
817 _take<atom*,World::AtomSet::value_type>::get);
[e472eab]818 return returnAtoms;
819}
820
[143263]821std::vector<atomId_t> World::getSelectedAtomIds() const {
822 std::vector<atomId_t> returnAtomIds;
823 std::transform(
824 selectedAtoms.begin(),
825 selectedAtoms.end(),
826 back_inserter(returnAtomIds),
827 _take<atom*,World::AtomSet::value_type>::getKey);
828 return returnAtomIds;
829}
[e472eab]830
[90c4280]831// Molecules
832
833void World::clearMoleculeSelection(){
[69643a]834 OBSERVE;
835 NOTIFY(SelectionChanged);
[7f1865d]836 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
[90c4280]837 selectedMolecules.clear();
838}
839
[ebc499]840void World::invertMoleculeSelection(){
841 // get all molecules not selected
842 typedef std::vector<molecule *> MoleculeVector_t;
843 MoleculeVector_t invertedSelection(getAllMolecules());
844 bool (World::*predicate)(const molecule*) const = &World::isSelected; // needed for type resolution of overloaded function
845 MoleculeVector_t::iterator iter =
846 std::remove_if(invertedSelection.begin(), invertedSelection.end(),
847 std::bind1st(std::mem_fun(predicate), this));
848 invertedSelection.erase(iter, invertedSelection.end());
849 // apply new selection
[7f1865d]850 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
[ebc499]851 selectedMolecules.clear();
852 void (World::*selector)(const molecule*) = &World::selectMolecule; // needed for type resolution of overloaded function
853 std::for_each(invertedSelection.begin(),invertedSelection.end(),
854 std::bind1st(std::mem_fun(selector),this)); // func is select... see above
855}
856
[cad383]857void World::popMoleculeSelection(){
[0249ce]858 if (!selectedMolecules_Stack.empty()) {
859 OBSERVE;
860 NOTIFY(SelectionChanged);
861 const moleculeIdsVector_t moleculeids = selectedMolecules_Stack.top();
862 boost::function<void (const moleculeId_t)> IdSelector =
863 boost::bind(static_cast<void (World::*)(const moleculeId_t)>(&World::selectMolecule), this, _1);
864 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
865 selectedMolecules.clear();
866 std::for_each(moleculeids.begin(),moleculeids.end(), IdSelector);
867 selectedMolecules_Stack.pop();
868 }
[cad383]869}
870
871void World::pushMoleculeSelection(){
872 OBSERVE;
873 NOTIFY(SelectionChanged);
[c1d837]874 moleculeIdsVector_t moleculeids(countSelectedMolecules(), (moleculeId_t)-1);
875 boost::function<moleculeId_t (const molecule*)> IdRetriever =
876 boost::bind(&molecule::getId, _1);
877 std::copy(
878 MapKeyIterator<MoleculeSelectionConstIterator>(beginMoleculeSelection()),
879 MapKeyIterator<MoleculeSelectionConstIterator>(endMoleculeSelection()),
880 moleculeids.begin());
881 selectedMolecules_Stack.push( moleculeids );
[7f1865d]882 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
[cad383]883 selectedMolecules.clear();
884}
885
[e4afb4]886void World::selectMolecule(const molecule *_mol){
[69643a]887 OBSERVE;
888 NOTIFY(SelectionChanged);
[e4afb4]889 // molecule * is unchanged in this function, but we do store entity as changeable
890 ASSERT(_mol,"Invalid pointer to molecule in selection");
[7f1865d]891 selectMolecule(_mol->getId());
[90c4280]892}
893
[e4afb4]894void World::selectMolecule(const moleculeId_t id){
[69643a]895 OBSERVE;
896 NOTIFY(SelectionChanged);
[90c4280]897 ASSERT(molecules.count(id),"Molecule Id selected that was not in the world");
[7f1865d]898 molecules[id]->select();
[90c4280]899 selectedMolecules[id]=molecules[id];
900}
901
[e472eab]902void World::selectAllMolecules(MoleculeDescriptor descr){
[69643a]903 OBSERVE;
904 NOTIFY(SelectionChanged);
[90c4280]905 internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
906 internal_MoleculeIterator end = moleculeEnd_internal();
[e4afb4]907 void (World::*func)(const molecule*) = &World::selectMolecule; // needed for type resolution of overloaded function
[90c4280]908 for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
909}
910
[e4afb4]911void World::selectMoleculeOfAtom(const atom *_atom){
[69643a]912 OBSERVE;
913 NOTIFY(SelectionChanged);
[e4afb4]914 ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom");
[270bdf]915 const molecule *mol=_atom->getMolecule();
[90c4280]916 // the atom might not be part of a molecule
917 if(mol){
918 selectMolecule(mol);
919 }
920}
921
[e4afb4]922void World::selectMoleculeOfAtom(const atomId_t id){
[69643a]923 OBSERVE;
924 NOTIFY(SelectionChanged);
[90c4280]925 ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
926 selectMoleculeOfAtom(atoms[id]);
927}
928
[e4afb4]929void World::unselectMolecule(const molecule *_mol){
[69643a]930 OBSERVE;
931 NOTIFY(SelectionChanged);
[e4afb4]932 ASSERT(_mol,"invalid pointer in unselection of molecule");
933 unselectMolecule(_mol->getId());
[61d655e]934}
935
[e4afb4]936void World::unselectMolecule(const moleculeId_t id){
[69643a]937 OBSERVE;
938 NOTIFY(SelectionChanged);
[61d655e]939 ASSERT(molecules.count(id),"No such molecule with ID in unselection");
[7f1865d]940 molecules[id]->unselect();
[61d655e]941 selectedMolecules.erase(id);
942}
943
[e472eab]944void World::unselectAllMolecules(MoleculeDescriptor descr){
[69643a]945 OBSERVE;
946 NOTIFY(SelectionChanged);
[61d655e]947 internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
948 internal_MoleculeIterator end = moleculeEnd_internal();
[e4afb4]949 void (World::*func)(const molecule*) = &World::unselectMolecule; // needed for type resolution of overloaded function
[61d655e]950 for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
951}
952
[e4afb4]953void World::unselectMoleculeOfAtom(const atom *_atom){
[69643a]954 OBSERVE;
955 NOTIFY(SelectionChanged);
[e4afb4]956 ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom");
[270bdf]957 const molecule *mol=_atom->getMolecule();
[61d655e]958 // the atom might not be part of a molecule
959 if(mol){
960 unselectMolecule(mol);
961 }
962}
963
[e4afb4]964void World::unselectMoleculeOfAtom(const atomId_t id){
[69643a]965 OBSERVE;
966 NOTIFY(SelectionChanged);
[61d655e]967 ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
968 unselectMoleculeOfAtom(atoms[id]);
969}
970
[e472eab]971size_t World::countSelectedMolecules() const {
[eacc3b]972 size_t count = 0;
[e472eab]973 for (MoleculeSet::const_iterator iter = selectedMolecules.begin(); iter != selectedMolecules.end(); ++iter)
[eacc3b]974 count++;
975 return count;
976}
977
[e4afb4]978bool World::isSelected(const molecule *_mol) const {
[7f1865d]979 const bool status = isMoleculeSelected(_mol->getId());
980 ASSERT( status == _mol->selected,
981 "World::isSelected() - mismatch in selection status between mol "+
982 toString(_mol->getId())+" and World.");
983 return status;
[89643d]984}
985
986bool World::isMoleculeSelected(const moleculeId_t no) const {
987 return selectedMolecules.find(no) != selectedMolecules.end();
[e0e156]988}
989
[97445f]990std::vector<molecule *> World::getSelectedMolecules() {
[e472eab]991 std::vector<molecule *> returnMolecules;
[97445f]992 std::transform(
993 selectedMolecules.begin(),
994 selectedMolecules.end(),
995 back_inserter(returnMolecules),
996 _take<molecule*,World::MoleculeSet::value_type>::get);
997 return returnMolecules;
998}
999
1000std::vector<const molecule *> World::getSelectedMolecules() const {
1001 std::vector<const molecule *> returnMolecules;
1002 std::transform(
1003 selectedMolecules.begin(),
1004 selectedMolecules.end(),
1005 back_inserter(returnMolecules),
1006 _take<molecule*,World::MoleculeSet::value_type>::get);
[e472eab]1007 return returnMolecules;
1008}
1009
[143263]1010std::vector<moleculeId_t> World::getSelectedMoleculeIds() const {
1011 std::vector<moleculeId_t> returnMoleculeIds;
1012 std::transform(
1013 selectedMolecules.begin(),
1014 selectedMolecules.end(),
1015 back_inserter(returnMoleculeIds),
1016 _take<molecule*,World::MoleculeSet::value_type>::getKey);
1017 return returnMoleculeIds;
1018}
1019
[3839e5]1020/******************* Iterators over Selection *****************************/
1021World::AtomSelectionIterator World::beginAtomSelection(){
1022 return selectedAtoms.begin();
1023}
1024
1025World::AtomSelectionIterator World::endAtomSelection(){
1026 return selectedAtoms.end();
1027}
1028
[38f991]1029World::AtomSelectionConstIterator World::beginAtomSelection() const{
1030 return selectedAtoms.begin();
1031}
1032
1033World::AtomSelectionConstIterator World::endAtomSelection() const{
1034 return selectedAtoms.end();
1035}
1036
[3839e5]1037
1038World::MoleculeSelectionIterator World::beginMoleculeSelection(){
1039 return selectedMolecules.begin();
1040}
1041
1042World::MoleculeSelectionIterator World::endMoleculeSelection(){
1043 return selectedMolecules.end();
1044}
1045
[38f991]1046World::MoleculeSelectionConstIterator World::beginMoleculeSelection() const{
1047 return selectedMolecules.begin();
1048}
1049
1050World::MoleculeSelectionConstIterator World::endMoleculeSelection() const{
1051 return selectedMolecules.end();
1052}
1053
[5d1611]1054/******************************* Singleton Stuff **************************/
1055
[7a1ce5]1056World::World() :
[cd5047]1057 Observable("World"),
[f71baf]1058 BG(new BondGraph(true)), // assume Angstroem for the moment
[4ae823]1059 periode(new periodentafel(true)),
[8e1f7af]1060 configuration(new config),
[98dbee]1061 homologies(new HomologyContainer()),
[43dad6]1062 Thermostats(new ThermoStatContainer),
[e4b5de]1063 ExitFlag(0),
[fa0b18]1064 atoms(this),
[90c4280]1065 selectedAtoms(this),
[e0e77e]1066 atomIdPool(0, 0, 0),
[51be2a]1067 molecules(this),
[90c4280]1068 selectedMolecules(this),
[2affd1]1069 moleculeIdPool(0, 20,100)
[7dad10]1070{
[84c494]1071 cell_size = new Box;
[cca9ef]1072 RealSpaceMatrix domain;
[84c494]1073 domain.at(0,0) = 20;
1074 domain.at(1,1) = 20;
1075 domain.at(2,2) = 20;
1076 cell_size->setM(domain);
[4834f4]1077 LCcontroller = new LinkedCell::LinkedCell_Controller(*cell_size);
[387b36]1078 defaultName = "none";
[02ce36]1079 Channels *OurChannel = new Channels;
[574d377]1080 Observable::insertNotificationChannel( std::make_pair( static_cast<Observable *>(this), OurChannel) );
[7188b1]1081 for (size_t type = 0; type < (size_t)NotificationType_MAX; ++type)
[02ce36]1082 OurChannel->addChannel(type);
[7dad10]1083}
[5d1611]1084
1085World::~World()
[354859]1086{
[4834f4]1087 delete LCcontroller;
[84c494]1088 delete cell_size;
[cbc5fb]1089 MoleculeSet::iterator molIter;
1090 for(molIter=molecules.begin();molIter!=molecules.end();++molIter){
1091 DeleteMolecule((*molIter).second);
1092 }
1093 molecules.clear();
1094 AtomSet::iterator atIter;
1095 for(atIter=atoms.begin();atIter!=atoms.end();++atIter){
1096 DeleteAtom((*atIter).second);
[46d958]1097 }
1098 atoms.clear();
[7188b1]1099
[f71baf]1100 delete BG;
[6cb9c76]1101 delete periode;
1102 delete configuration;
1103 delete Thermostats;
[09f615]1104 delete homologies;
[354859]1105}
[5d1611]1106
[23b547]1107// Explicit instantiation of the singleton mechanism at this point
[5d1611]1108
[3e4fb6]1109// moleculeId_t und atomId_t sind gleicher Basistyp, deswegen nur einen von beiden konstruieren
[b97a60]1110CONSTRUCT_IDPOOL(atomId_t, uniqueId)
1111CONSTRUCT_IDPOOL(moleculeId_t, continuousId)
[3e4fb6]1112
[23b547]1113CONSTRUCT_SINGLETON(World)
[5d1611]1114
[e2c2b1]1115CONSTRUCT_OBSERVEDCONTAINER(World::AtomSTLSet, UnobservedIterator<World::AtomSTLSet> )
[5f1d5b8]1116
[e2c2b1]1117CONSTRUCT_OBSERVEDCONTAINER(World::MoleculeSTLSet, UnobservedIterator<World::MoleculeSTLSet> )
Note: See TracBrowser for help on using the repository browser.