source: src/World.cpp@ efd020

AutomationFragmentation_failures Candidate_v1.6.1 ChemicalSpaceEvaluator Enhanced_StructuralOptimization_continued Exclude_Hydrogens_annealWithBondGraph ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_contraction-expansion Gui_displays_atomic_force_velocity PythonUI_with_named_parameters StoppableMakroAction TremoloParser_IncreasedPrecision
Last change on this file since efd020 was 7294dc, checked in by Frederik Heber <frederik.heber@…>, 8 years ago

FIX: Fixing the use of the trajectories that were changed to maps.

  • as the atom's trajectories are now stored inside a map, i.e. not every step necessarily needs to be present, there will still some places in the code that were meant for the old vector storing.
  • Atom::UpdateStep() updates the current step, not the future step.
  • AtomInfo::append/removeTrajectoryStep() now no longer ASSERT that the step is not the current one. Due to the trajectory in map concept (with current it simply sought by lower_bound()) this is no longer necessary.
  • HydrogenPool no longer adds all trajectory steps till current time.
  • World has commented out code for also copying the current atom positions in case a new time step is added, but this is not used as so far we do not recognize whether it is a new time step ... and also it is not really necessary.
  • TESTS: Removed XFAILs from tests of previous commit. They are all working again.
  • Property mode set to 100644
File size: 33.2 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 * Copyright (C) 2013 Frederik Heber. All rights reserved.
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/>.
22 */
23
24/*
25 * World.cpp
26 *
27 * Created on: Feb 3, 2010
28 * Author: crueger
29 */
30
31// include config.h
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36//#include "CodePatterns/MemDebug.hpp"
37
38#include "World.hpp"
39
40#include <functional>
41
42#include "Actions/ActionTrait.hpp"
43#include "Actions/ManipulateAtomsProcess.hpp"
44#include "Atom/atom.hpp"
45#include "Box.hpp"
46#include "CodePatterns/Assert.hpp"
47#include "config.hpp"
48#include "Descriptors/AtomDescriptor.hpp"
49#include "Descriptors/AtomDescriptor_impl.hpp"
50#include "Descriptors/AtomIdDescriptor.hpp"
51#include "Descriptors/AtomSelectionDescriptor.hpp"
52#include "Descriptors/MoleculeDescriptor.hpp"
53#include "Descriptors/MoleculeDescriptor_impl.hpp"
54#include "Descriptors/MoleculeIdDescriptor.hpp"
55#include "Descriptors/MoleculeSelectionDescriptor.hpp"
56#include "Descriptors/SelectiveConstIterator_impl.hpp"
57#include "Descriptors/SelectiveIterator_impl.hpp"
58#include "Element/periodentafel.hpp"
59#include "Fragmentation/Homology/HomologyContainer.hpp"
60#include "Graph/BondGraph.hpp"
61#include "Graph/DepthFirstSearchAnalysis.hpp"
62#include "Helpers/defs.hpp"
63#include "LinearAlgebra/RealSpaceMatrix.hpp"
64#include "LinkedCell/LinkedCell_Controller.hpp"
65#include "LinkedCell/PointCloudAdaptor.hpp"
66#include "molecule.hpp"
67#include "Thermostats/ThermoStatContainer.hpp"
68#include "WorldTime.hpp"
69
70#include "IdPool_impl.hpp"
71
72#include "CodePatterns/IteratorAdaptors.hpp"
73#include "CodePatterns/Singleton_impl.hpp"
74#include "CodePatterns/Observer/Channels.hpp"
75#include "CodePatterns/Observer/ObservedContainer_impl.hpp"
76
77using namespace MoleCuilder;
78
79/******************************* Notifications ************************/
80
81
82atom* World::_lastchangedatom = NULL;
83atomId_t World::_lastchangedatomid = -1;
84molecule* World::_lastchangedmol = NULL;
85moleculeId_t World::_lastchangedmolid = -1;
86
87/******************************* getter and setter ************************/
88periodentafel *&World::getPeriode()
89{
90 return periode;
91}
92
93BondGraph *&World::getBondGraph()
94{
95 return BG;
96}
97
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
115void World::setBondGraph(BondGraph *_BG){
116 delete (BG);
117 BG = _BG;
118}
119
120config *&World::getConfig(){
121 return configuration;
122}
123
124// Atoms
125
126atom* World::getAtom(AtomDescriptor descriptor){
127 return descriptor.find();
128}
129
130const atom* World::getAtom(AtomDescriptor descriptor) const{
131 return const_cast<const AtomDescriptor &>(descriptor).find();
132}
133
134World::AtomComposite World::getAllAtoms(AtomDescriptor descriptor){
135 return descriptor.findAll();
136}
137
138World::ConstAtomComposite World::getAllAtoms(AtomDescriptor descriptor) const {
139 return const_cast<const AtomDescriptor &>(descriptor).findAll();
140}
141
142World::AtomComposite World::getAllAtoms(){
143 return getAllAtoms(AllAtoms());
144}
145
146World::ConstAtomComposite World::getAllAtoms() const {
147 return getAllAtoms(AllAtoms());
148}
149
150int World::numAtoms() const {
151 return atoms.size();
152}
153
154// Molecules
155
156molecule *World::getMolecule(MoleculeDescriptor descriptor){
157 return descriptor.find();
158}
159
160const molecule *World::getMolecule(MoleculeDescriptor descriptor) const {
161 return const_cast<const MoleculeDescriptor &>(descriptor).find();
162}
163
164std::vector<molecule*> World::getAllMolecules(MoleculeDescriptor descriptor){
165 return descriptor.findAll();
166}
167
168std::vector<const molecule*> World::getAllMolecules(MoleculeDescriptor descriptor) const {
169 return const_cast<const MoleculeDescriptor &>(descriptor).findAll();
170}
171
172std::vector<molecule*> World::getAllMolecules(){
173 return getAllMolecules(AllMolecules());
174}
175
176std::vector<const molecule*> World::getAllMolecules() const {
177 return getAllMolecules(AllMolecules());
178}
179
180int World::numMolecules() const {
181 return molecules.size();
182}
183
184// system
185
186Box& World::getDomain() {
187 return *cell_size;
188}
189
190void World::setDomain(const RealSpaceMatrix &mat){
191 OBSERVE;
192 *cell_size = mat;
193}
194
195void World::setDomain(double * matrix)
196{
197 OBSERVE;
198 RealSpaceMatrix M = ReturnFullMatrixforSymmetric(matrix);
199 cell_size->setM(M);
200}
201
202LinkedCell::LinkedCell_View World::getLinkedCell(double distance)
203{
204 ASSERT( distance >= 0,
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 }
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
218const unsigned World::getTime() const
219{
220 return WorldTime::getTime();
221}
222
223static bool areBondsPresent(const unsigned int _step)
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
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
249static void copyBondgraph(const unsigned int _srcstep, const unsigned int _deststep)
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;
268 bond::ptr const _bond =
269 const_cast<atom *>(Walker)->addBond(_deststep, const_cast<atom *>(OtherWalker));
270 _bond->setDegree((*bonditer)->getDegree());
271 }
272}
273
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//}
285
286void World::setTime(const unsigned int _step)
287{
288 if (_step != WorldTime::getTime()) {
289 const unsigned int oldstep = WorldTime::getTime();
290
291// if (!areAtomsPresent(_step))
292// copyAtoms(oldstep, _step);
293
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
302 WorldTime::getInstance().setTime(_step);
303
304 // 4. scan for connected subgraphs => molecules
305 DepthFirstSearchAnalysis DFS;
306 DFS();
307 DFS.UpdateMoleculeStructure();
308 }
309}
310
311std::string World::getDefaultName() {
312 return defaultName;
313}
314
315void World::setDefaultName(std::string name)
316{
317 OBSERVE;
318 defaultName = name;
319};
320
321class ThermoStatContainer * World::getThermostats()
322{
323 return Thermostats;
324}
325
326
327int World::getExitFlag() {
328 return ExitFlag;
329}
330
331void World::setExitFlag(int flag) {
332 if (ExitFlag < flag)
333 ExitFlag = flag;
334}
335
336/******************** Methods to change World state *********************/
337
338molecule* World::createMolecule(){
339 OBSERVE;
340 molecule *mol = NULL;
341 mol = NewMolecule();
342 moleculeId_t id = moleculeIdPool.getNextId();
343 ASSERT(!molecules.count(id),"proposed id did not specify an unused ID");
344 mol->setId(id);
345 // store the molecule by ID
346 molecules[mol->getId()] = mol;
347 _lastchangedmol = mol;
348 _lastchangedmolid = mol->getId();
349 NOTIFY(MoleculeInserted);
350 return mol;
351}
352
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
369void World::destroyMolecule(molecule* mol){
370 ASSERT(mol,"Molecule that was meant to be destroyed did not exist");
371 destroyMolecule(mol->getId());
372}
373
374void World::destroyMolecule(moleculeId_t id){
375 molecule *mol = molecules[id];
376 ASSERT(mol,"Molecule id that was meant to be destroyed did not exist");
377 // give notice about immediate removal
378 {
379 OBSERVE;
380 _lastchangedmol = mol;
381 _lastchangedmolid = mol->getId();
382 NOTIFY(MoleculeRemoved);
383 }
384 if (isMoleculeSelected(id)) {
385 selectedMolecules.erase(id);
386 NOTIFY(SelectionChanged);
387 }
388 DeleteMolecule(mol);
389 molecules.erase(id);
390 moleculeIdPool.releaseId(id);
391}
392
393atom *World::createAtom(){
394 OBSERVE;
395 atomId_t id = atomIdPool.getNextId();
396 ASSERT(!atoms.count(id),"proposed id did not specify an unused ID");
397 atom *res = NewAtom(id);
398 res->setWorld(this);
399 // store the atom by ID
400 atoms[res->getId()] = res;
401 _lastchangedatom = res;
402 _lastchangedatomid = res->getId();
403 NOTIFY(AtomInserted);
404 return res;
405}
406
407atom *World::recreateAtom(const atomId_t _id){
408 if (!atoms.count(_id)) {
409 OBSERVE;
410 atom *res = NewAtom(_id);
411 res->setWorld(this);
412 // store the atom by ID
413 atoms[res->getId()] = res;
414 _lastchangedatom = res;
415 _lastchangedatomid = res->getId();
416 NOTIFY(AtomInserted);
417 return res;
418 } else
419 return NULL;
420}
421
422
423int World::registerAtom(atom *atom){
424 OBSERVE;
425 atomId_t id = atomIdPool.getNextId();
426 atom->setId(id);
427 atom->setWorld(this);
428 atoms[atom->getId()] = atom;
429 _lastchangedatom = atom;
430 _lastchangedatomid = atom->getId();
431 NOTIFY(AtomInserted);
432 return atom->getId();
433}
434
435void World::destroyAtom(atom* atom){
436 int id = atom->getId();
437 destroyAtom(id);
438}
439
440void World::destroyAtom(atomId_t id) {
441 atom *atom = atoms[id];
442 ASSERT(atom,"Atom ID that was meant to be destroyed did not exist");
443 // give notice about immediate removal
444 {
445 OBSERVE;
446 _lastchangedatom = atom;
447 _lastchangedatomid = atom->getId();
448 NOTIFY(AtomRemoved);
449 }
450 // check if it's the last atom
451 molecule *_mol = const_cast<molecule *>(atom->getMolecule());
452 if ((_mol == NULL) || (_mol->getAtomCount() > 1))
453 _mol = NULL;
454 if (isAtomSelected(id)) {
455 selectedAtoms.erase(id);
456 NOTIFY(SelectionChanged);
457 }
458 DeleteAtom(atom);
459 atoms.erase(id);
460 atomIdPool.releaseId(id);
461 // remove molecule if empty
462 if (_mol != NULL)
463 destroyMolecule(_mol);
464}
465
466bool World::changeAtomId(atomId_t oldId, atomId_t newId, atom* target){
467 OBSERVE;
468 // in case this call did not originate from inside the atom, we redirect it,
469 // to also let it know that it has changed
470 if(!target){
471 target = atoms[oldId];
472 ASSERT(target,"Atom with that ID not found");
473 return target->changeId(newId);
474 }
475 else{
476 if(atomIdPool.reserveId(newId)){
477 atoms.erase(oldId);
478 atoms.insert(pair<atomId_t,atom*>(newId,target));
479 return true;
480 }
481 else{
482 return false;
483 }
484 }
485}
486
487bool World::changeMoleculeId(moleculeId_t oldId, moleculeId_t newId, molecule* target){
488 OBSERVE;
489 // in case this call did not originate from inside the atom, we redirect it,
490 // to also let it know that it has changed
491 if(!target){
492 target = molecules[oldId];
493 ASSERT(target,"Molecule with that ID not found");
494 return target->changeId(newId);
495 }
496 else{
497 if(moleculeIdPool.reserveId(newId)){
498 molecules.erase(oldId);
499 molecules.insert(pair<moleculeId_t,molecule*>(newId,target));
500 return true;
501 }
502 else{
503 return false;
504 }
505 }
506}
507
508ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name,AtomDescriptor descr){
509 ActionTrait manipulateTrait(name);
510 return new ManipulateAtomsProcess(op, descr,manipulateTrait);
511}
512
513ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name){
514 return manipulateAtoms(op,name,AllAtoms());
515}
516
517/********************* Internal Change methods for double Callback and Observer mechanism ********/
518
519void World::doManipulate(ManipulateAtomsProcess *proc){
520 proc->signOn(this);
521 {
522 OBSERVE;
523 proc->doManipulate(this);
524 }
525 proc->signOff(this);
526}
527/******************************* Iterators ********************************/
528
529// external parts with observers
530
531CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet,AtomDescriptor)
532
533CONSTRUCT_SELECTIVE_CONST_ITERATOR(atom*,World::AtomSet,AtomDescriptor)
534
535World::AtomIterator
536World::getAtomIter(AtomDescriptor descr){
537 return AtomIterator(descr,atoms);
538}
539
540World::AtomConstIterator
541World::getAtomIter(AtomDescriptor descr) const{
542 return AtomConstIterator(descr,atoms);
543}
544
545World::AtomIterator
546World::getAtomIter(){
547 return AtomIterator(AllAtoms(),atoms);
548}
549
550World::AtomConstIterator
551World::getAtomIter() const{
552 return AtomConstIterator(AllAtoms(),atoms);
553}
554
555World::AtomIterator
556World::atomEnd(){
557 return AtomIterator(AllAtoms(),atoms,atoms.end());
558}
559
560World::AtomConstIterator
561World::atomEnd() const{
562 return AtomConstIterator(AllAtoms(),atoms,atoms.end());
563}
564
565CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor)
566
567CONSTRUCT_SELECTIVE_CONST_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor)
568
569World::MoleculeIterator
570World::getMoleculeIter(MoleculeDescriptor descr){
571 return MoleculeIterator(descr,molecules);
572}
573
574World::MoleculeConstIterator
575World::getMoleculeIter(MoleculeDescriptor descr) const{
576 return MoleculeConstIterator(descr,molecules);
577}
578
579World::MoleculeIterator
580World::getMoleculeIter(){
581 return MoleculeIterator(AllMolecules(),molecules);
582}
583
584World::MoleculeConstIterator
585World::getMoleculeIter() const{
586 return MoleculeConstIterator(AllMolecules(),molecules);
587}
588
589World::MoleculeIterator
590World::moleculeEnd(){
591 return MoleculeIterator(AllMolecules(),molecules,molecules.end());
592}
593
594World::MoleculeConstIterator
595World::moleculeEnd() const{
596 return MoleculeConstIterator(AllMolecules(),molecules,molecules.end());
597}
598
599// Internal parts, without observers
600
601// Build the AtomIterator from template
602CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet::set_t,AtomDescriptor);
603
604
605World::internal_AtomIterator
606World::getAtomIter_internal(AtomDescriptor descr){
607 return internal_AtomIterator(descr,atoms.getContent());
608}
609
610World::internal_AtomIterator
611World::atomEnd_internal(){
612 return internal_AtomIterator(AllAtoms(),atoms.getContent(),atoms.end_internal());
613}
614
615// build the MoleculeIterator from template
616CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet::set_t,MoleculeDescriptor);
617
618World::internal_MoleculeIterator World::getMoleculeIter_internal(MoleculeDescriptor descr){
619 return internal_MoleculeIterator(descr,molecules.getContent());
620}
621
622World::internal_MoleculeIterator World::moleculeEnd_internal(){
623 return internal_MoleculeIterator(AllMolecules(),molecules.getContent(),molecules.end_internal());
624}
625
626/************************** Selection of Atoms and molecules ******************/
627
628// translate type's selection member functions to overloaded with specific type
629
630template <class T>
631void World::selectVectorOfInstances(const typename T::iterator _begin, const typename T::iterator _end)
632{
633 std::for_each(_begin,_end,
634 boost::bind(&World::selectInstance<typename T::value_type::second_type>,
635 boost::bind(_take<typename T::value_type::second_type,typename T::value_type>::get, _1)));
636}
637
638template <class T>
639void World::unselectVectorOfInstances(const typename T::iterator _begin, const typename T::iterator _end)
640{
641 std::for_each(_begin,_end,
642 boost::bind(&World::unselectInstance<typename T::value_type::second_type>,
643 boost::bind(_take<typename T::value_type::second_type,typename T::value_type>::get, _1)));
644}
645
646// Atoms
647
648void World::clearAtomSelection(){
649 OBSERVE;
650 NOTIFY(SelectionChanged);
651 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
652 selectedAtoms.clear();
653}
654
655void World::invertAtomSelection(){
656 // get all atoms not selected
657 AtomComposite invertedSelection(getAllAtoms());
658 bool (World::*predicate)(const atom*) const = &World::isSelected; // needed for type resolution of overloaded function
659 AtomComposite::iterator iter =
660 std::remove_if(invertedSelection.begin(), invertedSelection.end(),
661 std::bind1st(std::mem_fun(predicate), this));
662 invertedSelection.erase(iter, invertedSelection.end());
663 // apply new selection
664 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
665 selectedAtoms.clear();
666 void (World::*selector)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
667 std::for_each(invertedSelection.begin(),invertedSelection.end(),
668 std::bind1st(std::mem_fun(selector),this)); // func is select... see above
669}
670
671void World::popAtomSelection(){
672 if (!selectedAtoms_Stack.empty()) {
673 OBSERVE;
674 NOTIFY(SelectionChanged);
675 const atomIdsVector_t atomids = selectedAtoms_Stack.top();
676 boost::function<void (const atomId_t)> IdSelector =
677 boost::bind(static_cast<void (World::*)(const atomId_t)>(&World::selectAtom), this, _1);
678 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
679 selectedAtoms.clear();
680 std::for_each(atomids.begin(),atomids.end(), IdSelector);
681 selectedAtoms_Stack.pop();
682 }
683}
684
685void World::pushAtomSelection(){
686 OBSERVE;
687 NOTIFY(SelectionChanged);
688 atomIdsVector_t atomids(countSelectedAtoms(), (atomId_t)-1);
689 std::copy(
690 MapKeyIterator<AtomSelectionConstIterator>(beginAtomSelection()),
691 MapKeyIterator<AtomSelectionConstIterator>(endAtomSelection()),
692 atomids.begin());
693 selectedAtoms_Stack.push( atomids );
694 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
695 selectedAtoms.clear();
696}
697
698void World::selectAtom(const atom *_atom){
699 OBSERVE;
700 NOTIFY(SelectionChanged);
701 // atom * is unchanged in this function, but we do store entity as changeable
702 ASSERT(_atom,"Invalid pointer in selection of atom");
703 selectAtom(_atom->getId());
704}
705
706void World::selectAtom(const atomId_t id){
707 OBSERVE;
708 NOTIFY(SelectionChanged);
709 ASSERT(atoms.count(id),"Atom Id selected that was not in the world");
710 selectedAtoms[id]=atoms[id];
711 atoms[id]->select();
712}
713
714void World::selectAllAtoms(AtomDescriptor descr){
715 OBSERVE;
716 NOTIFY(SelectionChanged);
717 internal_AtomIterator begin = getAtomIter_internal(descr);
718 internal_AtomIterator end = atomEnd_internal();
719 void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
720 for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
721}
722
723void World::selectAtomsOfMolecule(const molecule *_mol){
724 OBSERVE;
725 NOTIFY(SelectionChanged);
726 ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
727 // need to make it const to get the fast iterators
728 const molecule *mol = _mol;
729 void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
730 for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is select... see above
731}
732
733void World::selectAtomsOfMolecule(const moleculeId_t id){
734 OBSERVE;
735 NOTIFY(SelectionChanged);
736 ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
737 selectAtomsOfMolecule(molecules[id]);
738}
739
740void World::unselectAtom(const atom *_atom){
741 OBSERVE;
742 NOTIFY(SelectionChanged);
743 ASSERT(_atom,"Invalid pointer in unselection of atom");
744 unselectAtom(_atom->getId());
745}
746
747void World::unselectAtom(const atomId_t id){
748 OBSERVE;
749 NOTIFY(SelectionChanged);
750 ASSERT(atoms.count(id),"Atom Id unselected that was not in the world");
751 atoms[id]->unselect();
752 selectedAtoms.erase(id);
753}
754
755void World::unselectAllAtoms(AtomDescriptor descr){
756 OBSERVE;
757 NOTIFY(SelectionChanged);
758 internal_AtomIterator begin = getAtomIter_internal(descr);
759 internal_AtomIterator end = atomEnd_internal();
760 void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
761 for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
762}
763
764void World::unselectAtomsOfMolecule(const molecule *_mol){
765 OBSERVE;
766 NOTIFY(SelectionChanged);
767 ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
768 // need to make it const to get the fast iterators
769 const molecule *mol = _mol;
770 void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
771 for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is unselect... see above
772}
773
774void World::unselectAtomsOfMolecule(const moleculeId_t id){
775 OBSERVE;
776 NOTIFY(SelectionChanged);
777 ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
778 unselectAtomsOfMolecule(molecules[id]);
779}
780
781size_t World::countSelectedAtoms() const {
782 size_t count = 0;
783 for (AtomSet::const_iterator iter = selectedAtoms.begin(); iter != selectedAtoms.end(); ++iter)
784 count++;
785 return count;
786}
787
788bool World::isSelected(const atom *_atom) const {
789 const bool status = isAtomSelected(_atom->getId());
790 ASSERT( status == _atom->selected,
791 "World::isSelected() - mismatch between selection state in atom "+
792 toString(_atom->getId())+" and World.");
793 return status;
794}
795
796bool World::isAtomSelected(const atomId_t no) const {
797 return selectedAtoms.find(no) != selectedAtoms.end();
798}
799
800std::vector<atom *> World::getSelectedAtoms() {
801 std::vector<atom *> returnAtoms;
802 std::transform(
803 selectedAtoms.begin(),
804 selectedAtoms.end(),
805 back_inserter(returnAtoms),
806 _take<atom*,World::AtomSet::value_type>::get);
807 return returnAtoms;
808}
809
810std::vector<const atom *> World::getSelectedAtoms() const {
811 std::vector<const atom *> returnAtoms;
812 std::transform(
813 selectedAtoms.begin(),
814 selectedAtoms.end(),
815 back_inserter(returnAtoms),
816 _take<atom*,World::AtomSet::value_type>::get);
817 return returnAtoms;
818}
819
820std::vector<atomId_t> World::getSelectedAtomIds() const {
821 std::vector<atomId_t> returnAtomIds;
822 std::transform(
823 selectedAtoms.begin(),
824 selectedAtoms.end(),
825 back_inserter(returnAtomIds),
826 _take<atom*,World::AtomSet::value_type>::getKey);
827 return returnAtomIds;
828}
829
830// Molecules
831
832void World::clearMoleculeSelection(){
833 OBSERVE;
834 NOTIFY(SelectionChanged);
835 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
836 selectedMolecules.clear();
837}
838
839void World::invertMoleculeSelection(){
840 // get all molecules not selected
841 typedef std::vector<molecule *> MoleculeVector_t;
842 MoleculeVector_t invertedSelection(getAllMolecules());
843 bool (World::*predicate)(const molecule*) const = &World::isSelected; // needed for type resolution of overloaded function
844 MoleculeVector_t::iterator iter =
845 std::remove_if(invertedSelection.begin(), invertedSelection.end(),
846 std::bind1st(std::mem_fun(predicate), this));
847 invertedSelection.erase(iter, invertedSelection.end());
848 // apply new selection
849 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
850 selectedMolecules.clear();
851 void (World::*selector)(const molecule*) = &World::selectMolecule; // needed for type resolution of overloaded function
852 std::for_each(invertedSelection.begin(),invertedSelection.end(),
853 std::bind1st(std::mem_fun(selector),this)); // func is select... see above
854}
855
856void World::popMoleculeSelection(){
857 if (!selectedMolecules_Stack.empty()) {
858 OBSERVE;
859 NOTIFY(SelectionChanged);
860 const moleculeIdsVector_t moleculeids = selectedMolecules_Stack.top();
861 boost::function<void (const moleculeId_t)> IdSelector =
862 boost::bind(static_cast<void (World::*)(const moleculeId_t)>(&World::selectMolecule), this, _1);
863 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
864 selectedMolecules.clear();
865 std::for_each(moleculeids.begin(),moleculeids.end(), IdSelector);
866 selectedMolecules_Stack.pop();
867 }
868}
869
870void World::pushMoleculeSelection(){
871 OBSERVE;
872 NOTIFY(SelectionChanged);
873 moleculeIdsVector_t moleculeids(countSelectedMolecules(), (moleculeId_t)-1);
874 boost::function<moleculeId_t (const molecule*)> IdRetriever =
875 boost::bind(&molecule::getId, _1);
876 std::copy(
877 MapKeyIterator<MoleculeSelectionConstIterator>(beginMoleculeSelection()),
878 MapKeyIterator<MoleculeSelectionConstIterator>(endMoleculeSelection()),
879 moleculeids.begin());
880 selectedMolecules_Stack.push( moleculeids );
881 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
882 selectedMolecules.clear();
883}
884
885void World::selectMolecule(const molecule *_mol){
886 OBSERVE;
887 NOTIFY(SelectionChanged);
888 // molecule * is unchanged in this function, but we do store entity as changeable
889 ASSERT(_mol,"Invalid pointer to molecule in selection");
890 selectMolecule(_mol->getId());
891}
892
893void World::selectMolecule(const moleculeId_t id){
894 OBSERVE;
895 NOTIFY(SelectionChanged);
896 ASSERT(molecules.count(id),"Molecule Id selected that was not in the world");
897 molecules[id]->select();
898 selectedMolecules[id]=molecules[id];
899}
900
901void World::selectAllMolecules(MoleculeDescriptor descr){
902 OBSERVE;
903 NOTIFY(SelectionChanged);
904 internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
905 internal_MoleculeIterator end = moleculeEnd_internal();
906 void (World::*func)(const molecule*) = &World::selectMolecule; // needed for type resolution of overloaded function
907 for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
908}
909
910void World::selectMoleculeOfAtom(const atom *_atom){
911 OBSERVE;
912 NOTIFY(SelectionChanged);
913 ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom");
914 const molecule *mol=_atom->getMolecule();
915 // the atom might not be part of a molecule
916 if(mol){
917 selectMolecule(mol);
918 }
919}
920
921void World::selectMoleculeOfAtom(const atomId_t id){
922 OBSERVE;
923 NOTIFY(SelectionChanged);
924 ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
925 selectMoleculeOfAtom(atoms[id]);
926}
927
928void World::unselectMolecule(const molecule *_mol){
929 OBSERVE;
930 NOTIFY(SelectionChanged);
931 ASSERT(_mol,"invalid pointer in unselection of molecule");
932 unselectMolecule(_mol->getId());
933}
934
935void World::unselectMolecule(const moleculeId_t id){
936 OBSERVE;
937 NOTIFY(SelectionChanged);
938 ASSERT(molecules.count(id),"No such molecule with ID in unselection");
939 molecules[id]->unselect();
940 selectedMolecules.erase(id);
941}
942
943void World::unselectAllMolecules(MoleculeDescriptor descr){
944 OBSERVE;
945 NOTIFY(SelectionChanged);
946 internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
947 internal_MoleculeIterator end = moleculeEnd_internal();
948 void (World::*func)(const molecule*) = &World::unselectMolecule; // needed for type resolution of overloaded function
949 for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
950}
951
952void World::unselectMoleculeOfAtom(const atom *_atom){
953 OBSERVE;
954 NOTIFY(SelectionChanged);
955 ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom");
956 const molecule *mol=_atom->getMolecule();
957 // the atom might not be part of a molecule
958 if(mol){
959 unselectMolecule(mol);
960 }
961}
962
963void World::unselectMoleculeOfAtom(const atomId_t id){
964 OBSERVE;
965 NOTIFY(SelectionChanged);
966 ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
967 unselectMoleculeOfAtom(atoms[id]);
968}
969
970size_t World::countSelectedMolecules() const {
971 size_t count = 0;
972 for (MoleculeSet::const_iterator iter = selectedMolecules.begin(); iter != selectedMolecules.end(); ++iter)
973 count++;
974 return count;
975}
976
977bool World::isSelected(const molecule *_mol) const {
978 const bool status = isMoleculeSelected(_mol->getId());
979 ASSERT( status == _mol->selected,
980 "World::isSelected() - mismatch in selection status between mol "+
981 toString(_mol->getId())+" and World.");
982 return status;
983}
984
985bool World::isMoleculeSelected(const moleculeId_t no) const {
986 return selectedMolecules.find(no) != selectedMolecules.end();
987}
988
989std::vector<molecule *> World::getSelectedMolecules() {
990 std::vector<molecule *> returnMolecules;
991 std::transform(
992 selectedMolecules.begin(),
993 selectedMolecules.end(),
994 back_inserter(returnMolecules),
995 _take<molecule*,World::MoleculeSet::value_type>::get);
996 return returnMolecules;
997}
998
999std::vector<const molecule *> World::getSelectedMolecules() const {
1000 std::vector<const molecule *> returnMolecules;
1001 std::transform(
1002 selectedMolecules.begin(),
1003 selectedMolecules.end(),
1004 back_inserter(returnMolecules),
1005 _take<molecule*,World::MoleculeSet::value_type>::get);
1006 return returnMolecules;
1007}
1008
1009std::vector<moleculeId_t> World::getSelectedMoleculeIds() const {
1010 std::vector<moleculeId_t> returnMoleculeIds;
1011 std::transform(
1012 selectedMolecules.begin(),
1013 selectedMolecules.end(),
1014 back_inserter(returnMoleculeIds),
1015 _take<molecule*,World::MoleculeSet::value_type>::getKey);
1016 return returnMoleculeIds;
1017}
1018
1019/******************* Iterators over Selection *****************************/
1020World::AtomSelectionIterator World::beginAtomSelection(){
1021 return selectedAtoms.begin();
1022}
1023
1024World::AtomSelectionIterator World::endAtomSelection(){
1025 return selectedAtoms.end();
1026}
1027
1028World::AtomSelectionConstIterator World::beginAtomSelection() const{
1029 return selectedAtoms.begin();
1030}
1031
1032World::AtomSelectionConstIterator World::endAtomSelection() const{
1033 return selectedAtoms.end();
1034}
1035
1036
1037World::MoleculeSelectionIterator World::beginMoleculeSelection(){
1038 return selectedMolecules.begin();
1039}
1040
1041World::MoleculeSelectionIterator World::endMoleculeSelection(){
1042 return selectedMolecules.end();
1043}
1044
1045World::MoleculeSelectionConstIterator World::beginMoleculeSelection() const{
1046 return selectedMolecules.begin();
1047}
1048
1049World::MoleculeSelectionConstIterator World::endMoleculeSelection() const{
1050 return selectedMolecules.end();
1051}
1052
1053/******************************* Singleton Stuff **************************/
1054
1055World::World() :
1056 Observable("World"),
1057 BG(new BondGraph(true)), // assume Angstroem for the moment
1058 periode(new periodentafel(true)),
1059 configuration(new config),
1060 homologies(new HomologyContainer()),
1061 Thermostats(new ThermoStatContainer),
1062 ExitFlag(0),
1063 atoms(this),
1064 selectedAtoms(this),
1065 atomIdPool(0, 20, 100),
1066 molecules(this),
1067 selectedMolecules(this),
1068 moleculeIdPool(0, 20,100)
1069{
1070 cell_size = new Box;
1071 RealSpaceMatrix domain;
1072 domain.at(0,0) = 20;
1073 domain.at(1,1) = 20;
1074 domain.at(2,2) = 20;
1075 cell_size->setM(domain);
1076 LCcontroller = new LinkedCell::LinkedCell_Controller(*cell_size);
1077 defaultName = "none";
1078 Channels *OurChannel = new Channels;
1079 Observable::insertNotificationChannel( std::make_pair( static_cast<Observable *>(this), OurChannel) );
1080 for (size_t type = 0; type < (size_t)NotificationType_MAX; ++type)
1081 OurChannel->addChannel(type);
1082}
1083
1084World::~World()
1085{
1086 delete LCcontroller;
1087 delete cell_size;
1088 MoleculeSet::iterator molIter;
1089 for(molIter=molecules.begin();molIter!=molecules.end();++molIter){
1090 DeleteMolecule((*molIter).second);
1091 }
1092 molecules.clear();
1093 AtomSet::iterator atIter;
1094 for(atIter=atoms.begin();atIter!=atoms.end();++atIter){
1095 DeleteAtom((*atIter).second);
1096 }
1097 atoms.clear();
1098
1099 delete BG;
1100 delete periode;
1101 delete configuration;
1102 delete Thermostats;
1103 delete homologies;
1104}
1105
1106// Explicit instantiation of the singleton mechanism at this point
1107
1108// moleculeId_t und atomId_t sind gleicher Basistyp, deswegen nur einen von beiden konstruieren
1109CONSTRUCT_IDPOOL(atomId_t, uniqueId)
1110CONSTRUCT_IDPOOL(moleculeId_t, continuousId)
1111
1112CONSTRUCT_SINGLETON(World)
1113
1114CONSTRUCT_OBSERVEDCONTAINER(World::AtomSTLSet, UnobservedIterator<World::AtomSTLSet> )
1115
1116CONSTRUCT_OBSERVEDCONTAINER(World::MoleculeSTLSet, UnobservedIterator<World::MoleculeSTLSet> )
Note: See TracBrowser for help on using the repository browser.