source: src/World.cpp@ ab4a33

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since ab4a33 was ab4a33, checked in by Frederik Heber <heber@…>, 14 years ago

FIX: World::destroyAtom() now informs before atom's destruction, not after.

  • Property mode set to 100644
File size: 23.7 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/*
9 * World.cpp
10 *
11 * Created on: Feb 3, 2010
12 * Author: crueger
13 */
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20#include "CodePatterns/MemDebug.hpp"
21
22#include "World.hpp"
23
24#include <functional>
25
26#include "Actions/ActionTraits.hpp"
27//#include "Actions/FragmentationAction/SubgraphDissectionAction.hpp"
28#include "Actions/ManipulateAtomsProcess.hpp"
29#include "atom.hpp"
30#include "Graph/BondGraph.hpp"
31#include "Box.hpp"
32#include "CodePatterns/Assert.hpp"
33#include "config.hpp"
34#include "Descriptors/AtomDescriptor.hpp"
35#include "Descriptors/AtomDescriptor_impl.hpp"
36#include "Descriptors/MoleculeDescriptor.hpp"
37#include "Descriptors/MoleculeDescriptor_impl.hpp"
38#include "Descriptors/SelectiveIterator_impl.hpp"
39#include "Helpers/defs.hpp"
40#include "LinearAlgebra/RealSpaceMatrix.hpp"
41#include "molecule.hpp"
42#include "periodentafel.hpp"
43#include "ThermoStatContainer.hpp"
44#include "WorldTime.hpp"
45
46#include "CodePatterns/Singleton_impl.hpp"
47#include "CodePatterns/ObservedContainer_impl.hpp"
48
49using namespace std;
50
51const unsigned int MAX_POOL_FRAGMENTATION=20;
52const unsigned int MAX_FRAGMENTATION_SKIPS=100;
53
54/******************************* Notifications ************************/
55
56
57atom* World::_lastchangedatom = NULL;
58molecule* World::_lastchangedmol = NULL;
59
60/******************************* getter and setter ************************/
61periodentafel *&World::getPeriode()
62{
63 return periode;
64}
65
66BondGraph *&World::getBondGraph()
67{
68 return BG;
69}
70
71void World::setBondGraph(BondGraph *_BG){
72 delete (BG);
73 BG = _BG;
74}
75
76config *&World::getConfig(){
77 return configuration;
78}
79
80// Atoms
81
82atom* World::getAtom(AtomDescriptor descriptor){
83 return descriptor.find();
84}
85
86World::AtomComposite World::getAllAtoms(AtomDescriptor descriptor){
87 return descriptor.findAll();
88}
89
90World::AtomComposite World::getAllAtoms(){
91 return getAllAtoms(AllAtoms());
92}
93
94int World::numAtoms(){
95 return atoms.size();
96}
97
98// Molecules
99
100molecule *World::getMolecule(MoleculeDescriptor descriptor){
101 return descriptor.find();
102}
103
104std::vector<molecule*> World::getAllMolecules(MoleculeDescriptor descriptor){
105 return descriptor.findAll();
106}
107
108std::vector<molecule*> World::getAllMolecules(){
109 return getAllMolecules(AllMolecules());
110}
111
112int World::numMolecules(){
113 return molecules_deprecated->ListOfMolecules.size();
114}
115
116// system
117
118Box& World::getDomain() {
119 return *cell_size;
120}
121
122void World::setDomain(const RealSpaceMatrix &mat){
123 OBSERVE;
124 *cell_size = mat;
125}
126
127void World::setDomain(double * matrix)
128{
129 OBSERVE;
130 RealSpaceMatrix M = ReturnFullMatrixforSymmetric(matrix);
131 cell_size->setM(M);
132}
133
134void World::setTime(const unsigned int _step)
135{
136 if (_step != WorldTime::getTime()) {
137 // set new time
138 WorldTime::setTime(_step);
139 // re-instantiate bond structure
140 //FragmentationSubgraphDissection();
141 }
142}
143
144std::string World::getDefaultName() {
145 return defaultName;
146}
147
148void World::setDefaultName(std::string name)
149{
150 OBSERVE;
151 defaultName = name;
152};
153
154class ThermoStatContainer * World::getThermostats()
155{
156 return Thermostats;
157}
158
159
160int World::getExitFlag() {
161 return ExitFlag;
162}
163
164void World::setExitFlag(int flag) {
165 if (ExitFlag < flag)
166 ExitFlag = flag;
167}
168
169/******************** Methods to change World state *********************/
170
171molecule* World::createMolecule(){
172 OBSERVE;
173 molecule *mol = NULL;
174 mol = NewMolecule();
175 moleculeId_t id = getNextMoleculeId();
176 ASSERT(!molecules.count(id),"proposed id did not specify an unused ID");
177 mol->setId(id);
178 // store the molecule by ID
179 molecules[mol->getId()] = mol;
180 mol->signOn(this);
181 _lastchangedmol = mol;
182 NOTIFY(MoleculeInserted);
183 return mol;
184}
185
186void World::destroyMolecule(molecule* mol){
187 OBSERVE;
188 ASSERT(mol,"Molecule that was meant to be destroyed did not exist");
189 destroyMolecule(mol->getId());
190}
191
192void World::destroyMolecule(moleculeId_t id){
193 OBSERVE;
194 molecule *mol = molecules[id];
195 ASSERT(mol,"Molecule id that was meant to be destroyed did not exist");
196 _lastchangedmol = mol;
197 NOTIFY(MoleculeRemoved);
198 DeleteMolecule(mol);
199 molecules.erase(id);
200 releaseMoleculeId(id);
201}
202
203atom *World::createAtom(){
204 OBSERVE;
205 atomId_t id = getNextAtomId();
206 ASSERT(!atoms.count(id),"proposed id did not specify an unused ID");
207 atom *res = NewAtom(id);
208 res->setWorld(this);
209 // store the atom by ID
210 atoms[res->getId()] = res;
211 _lastchangedatom = res;
212 NOTIFY(AtomInserted);
213 return res;
214}
215
216
217int World::registerAtom(atom *atom){
218 OBSERVE;
219 atomId_t id = getNextAtomId();
220 atom->setId(id);
221 atom->setWorld(this);
222 atoms[atom->getId()] = atom;
223 return atom->getId();
224}
225
226void World::destroyAtom(atom* atom){
227 int id = atom->getId();
228 destroyAtom(id);
229}
230
231void World::destroyAtom(atomId_t id) {
232 atom *atom = atoms[id];
233 ASSERT(atom,"Atom ID that was meant to be destroyed did not exist");
234 // give notice about immediate removal
235 {
236 OBSERVE;
237 _lastchangedatom = atom;
238 NOTIFY(AtomRemoved);
239 }
240 DeleteAtom(atom);
241 atoms.erase(id);
242 releaseAtomId(id);
243}
244
245bool World::changeAtomId(atomId_t oldId, atomId_t newId, atom* target){
246 OBSERVE;
247 // in case this call did not originate from inside the atom, we redirect it,
248 // to also let it know that it has changed
249 if(!target){
250 target = atoms[oldId];
251 ASSERT(target,"Atom with that ID not found");
252 return target->changeId(newId);
253 }
254 else{
255 if(reserveAtomId(newId)){
256 atoms.erase(oldId);
257 atoms.insert(pair<atomId_t,atom*>(newId,target));
258 return true;
259 }
260 else{
261 return false;
262 }
263 }
264}
265
266bool World::changeMoleculeId(moleculeId_t oldId, moleculeId_t newId, molecule* target){
267 OBSERVE;
268 // in case this call did not originate from inside the atom, we redirect it,
269 // to also let it know that it has changed
270 if(!target){
271 target = molecules[oldId];
272 ASSERT(target,"Molecule with that ID not found");
273 return target->changeId(newId);
274 }
275 else{
276 if(reserveMoleculeId(newId)){
277 molecules.erase(oldId);
278 molecules.insert(pair<moleculeId_t,molecule*>(newId,target));
279 return true;
280 }
281 else{
282 return false;
283 }
284 }
285}
286
287ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name,AtomDescriptor descr){
288 ActionTraits manipulateTrait(name);
289 return new ManipulateAtomsProcess(op, descr,manipulateTrait,false);
290}
291
292ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name){
293 return manipulateAtoms(op,name,AllAtoms());
294}
295
296/********************* Internal Change methods for double Callback and Observer mechanism ********/
297
298void World::doManipulate(ManipulateAtomsProcess *proc){
299 proc->signOn(this);
300 {
301 OBSERVE;
302 proc->doManipulate(this);
303 }
304 proc->signOff(this);
305}
306/******************************* IDManagement *****************************/
307
308// Atoms
309
310atomId_t World::getNextAtomId(){
311 // try to find an Id in the pool;
312 if(!atomIdPool.empty()){
313 atomIdPool_t::iterator iter=atomIdPool.begin();
314 atomId_t id = iter->first;
315 range<atomId_t> newRange = makeRange(id+1,iter->last);
316 // we wont use this iterator anymore, so we don't care about invalidating
317 atomIdPool.erase(iter);
318 if(newRange.first<newRange.last){
319 atomIdPool.insert(newRange);
320 }
321 return id;
322 }
323 // Nothing in the pool... we are out of luck
324 return currAtomId++;
325}
326
327void World::releaseAtomId(atomId_t id){
328 atomIdPool.insert(makeRange(id,id+1));
329 defragAtomIdPool();
330}
331
332bool World::reserveAtomId(atomId_t id){
333 if(id>=currAtomId ){
334 range<atomId_t> newRange = makeRange(currAtomId,id);
335 if(newRange.first<newRange.last){
336 atomIdPool.insert(newRange);
337 }
338 currAtomId=id+1;
339 defragAtomIdPool();
340 return true;
341 }
342 // look for a range that matches the request
343 for(atomIdPool_t::iterator iter=atomIdPool.begin();iter!=atomIdPool.end();++iter){
344 if(iter->isBefore(id)){
345 // we have covered all available ranges... nothing to be found here
346 break;
347 }
348 // no need to check first, since it has to be <=id, since otherwise we would have broken out
349 if(!iter->isBeyond(id)){
350 // we found a matching range... get the id from this range
351
352 // split up this range at the point of id
353 range<atomId_t> bottomRange = makeRange(iter->first,id);
354 range<atomId_t> topRange = makeRange(id+1,iter->last);
355 // remove this range
356 atomIdPool.erase(iter);
357 if(bottomRange.first<bottomRange.last){
358 atomIdPool.insert(bottomRange);
359 }
360 if(topRange.first<topRange.last){
361 atomIdPool.insert(topRange);
362 }
363 defragAtomIdPool();
364 return true;
365 }
366 }
367 // this ID could not be reserved
368 return false;
369}
370
371void World::defragAtomIdPool(){
372 // check if the situation is bad enough to make defragging neccessary
373 if((numAtomDefragSkips<MAX_FRAGMENTATION_SKIPS) &&
374 (atomIdPool.size()<lastAtomPoolSize+MAX_POOL_FRAGMENTATION)){
375 ++numAtomDefragSkips;
376 return;
377 }
378 for(atomIdPool_t::iterator iter = atomIdPool.begin();iter!=atomIdPool.end();){
379 // see if this range is adjacent to the next one
380 atomIdPool_t::iterator next = iter;
381 next++;
382 if(next!=atomIdPool.end() && (next->first==iter->last)){
383 // merge the two ranges
384 range<atomId_t> newRange = makeRange(iter->first,next->last);
385 atomIdPool.erase(iter);
386 atomIdPool.erase(next);
387 pair<atomIdPool_t::iterator,bool> res = atomIdPool.insert(newRange);
388 ASSERT(res.second,"Id-Pool was confused");
389 iter=res.first;
390 continue;
391 }
392 ++iter;
393 }
394 if(!atomIdPool.empty()){
395 // check if the last range is at the border
396 atomIdPool_t::iterator iter = atomIdPool.end();
397 iter--;
398 if(iter->last==currAtomId){
399 currAtomId=iter->first;
400 atomIdPool.erase(iter);
401 }
402 }
403 lastAtomPoolSize=atomIdPool.size();
404 numAtomDefragSkips=0;
405}
406
407// Molecules
408
409moleculeId_t World::getNextMoleculeId(){
410 // try to find an Id in the pool;
411 if(!moleculeIdPool.empty()){
412 moleculeIdPool_t::iterator iter=moleculeIdPool.begin();
413 moleculeId_t id = iter->first;
414 range<moleculeId_t> newRange = makeRange(id+1,iter->last);
415 // we wont use this iterator anymore, so we don't care about invalidating
416 moleculeIdPool.erase(iter);
417 if(newRange.first<newRange.last){
418 moleculeIdPool.insert(newRange);
419 }
420 return id;
421 }
422 // Nothing in the pool... we are out of luck
423 return currMoleculeId++;
424}
425
426void World::releaseMoleculeId(moleculeId_t id){
427 moleculeIdPool.insert(makeRange(id,id+1));
428 defragMoleculeIdPool();
429}
430
431bool World::reserveMoleculeId(moleculeId_t id){
432 if(id>=currMoleculeId ){
433 range<moleculeId_t> newRange = makeRange(currMoleculeId,id);
434 if(newRange.first<newRange.last){
435 moleculeIdPool.insert(newRange);
436 }
437 currMoleculeId=id+1;
438 defragMoleculeIdPool();
439 return true;
440 }
441 // look for a range that matches the request
442 for(moleculeIdPool_t::iterator iter=moleculeIdPool.begin();iter!=moleculeIdPool.end();++iter){
443 if(iter->isBefore(id)){
444 // we have coverd all available ranges... nothing to be found here
445 break;
446 }
447 // no need to check first, since it has to be <=id, since otherwise we would have broken out
448 if(!iter->isBeyond(id)){
449 // we found a matching range... get the id from this range
450
451 // split up this range at the point of id
452 range<moleculeId_t> bottomRange = makeRange(iter->first,id);
453 range<moleculeId_t> topRange = makeRange(id+1,iter->last);
454 // remove this range
455 moleculeIdPool.erase(iter);
456 if(bottomRange.first<bottomRange.last){
457 moleculeIdPool.insert(bottomRange);
458 }
459 if(topRange.first<topRange.last){
460 moleculeIdPool.insert(topRange);
461 }
462 defragMoleculeIdPool();
463 return true;
464 }
465 }
466 // this ID could not be reserved
467 return false;
468}
469
470void World::defragMoleculeIdPool(){
471 // check if the situation is bad enough to make defragging neccessary
472 if((numMoleculeDefragSkips<MAX_FRAGMENTATION_SKIPS) &&
473 (moleculeIdPool.size()<lastMoleculePoolSize+MAX_POOL_FRAGMENTATION)){
474 ++numMoleculeDefragSkips;
475 return;
476 }
477 for(moleculeIdPool_t::iterator iter = moleculeIdPool.begin();iter!=moleculeIdPool.end();){
478 // see if this range is adjacent to the next one
479 moleculeIdPool_t::iterator next = iter;
480 next++;
481 if(next!=moleculeIdPool.end() && (next->first==iter->last)){
482 // merge the two ranges
483 range<moleculeId_t> newRange = makeRange(iter->first,next->last);
484 moleculeIdPool.erase(iter);
485 moleculeIdPool.erase(next);
486 pair<moleculeIdPool_t::iterator,bool> res = moleculeIdPool.insert(newRange);
487 ASSERT(res.second,"Id-Pool was confused");
488 iter=res.first;
489 continue;
490 }
491 ++iter;
492 }
493 if(!moleculeIdPool.empty()){
494 // check if the last range is at the border
495 moleculeIdPool_t::iterator iter = moleculeIdPool.end();
496 iter--;
497 if(iter->last==currMoleculeId){
498 currMoleculeId=iter->first;
499 moleculeIdPool.erase(iter);
500 }
501 }
502 lastMoleculePoolSize=moleculeIdPool.size();
503 numMoleculeDefragSkips=0;
504}
505
506/******************************* Iterators ********************************/
507
508// external parts with observers
509
510CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet,AtomDescriptor);
511
512World::AtomIterator
513World::getAtomIter(AtomDescriptor descr){
514 return AtomIterator(descr,atoms);
515}
516
517World::AtomIterator
518World::getAtomIter(){
519 return AtomIterator(AllAtoms(),atoms);
520}
521
522World::AtomIterator
523World::atomEnd(){
524 return AtomIterator(AllAtoms(),atoms,atoms.end());
525}
526
527CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor);
528
529World::MoleculeIterator
530World::getMoleculeIter(MoleculeDescriptor descr){
531 return MoleculeIterator(descr,molecules);
532}
533
534World::MoleculeIterator
535World::getMoleculeIter(){
536 return MoleculeIterator(AllMolecules(),molecules);
537}
538
539World::MoleculeIterator
540World::moleculeEnd(){
541 return MoleculeIterator(AllMolecules(),molecules,molecules.end());
542}
543
544// Internal parts, without observers
545
546// Build the AtomIterator from template
547CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet::set_t,AtomDescriptor);
548
549
550World::internal_AtomIterator
551World::getAtomIter_internal(AtomDescriptor descr){
552 return internal_AtomIterator(descr,atoms.getContent());
553}
554
555World::internal_AtomIterator
556World::atomEnd_internal(){
557 return internal_AtomIterator(AllAtoms(),atoms.getContent(),atoms.end_internal());
558}
559
560// build the MoleculeIterator from template
561CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet::set_t,MoleculeDescriptor);
562
563World::internal_MoleculeIterator World::getMoleculeIter_internal(MoleculeDescriptor descr){
564 return internal_MoleculeIterator(descr,molecules.getContent());
565}
566
567World::internal_MoleculeIterator World::moleculeEnd_internal(){
568 return internal_MoleculeIterator(AllMolecules(),molecules.getContent(),molecules.end_internal());
569}
570
571/************************** Selection of Atoms and molecules ******************/
572
573// Atoms
574
575void World::clearAtomSelection(){
576 selectedAtoms.clear();
577}
578
579void World::selectAtom(const atom *_atom){
580 // atom * is unchanged in this function, but we do store entity as changeable
581 ASSERT(_atom,"Invalid pointer in selection of atom");
582 selectedAtoms[_atom->getId()]=const_cast<atom *>(_atom);
583}
584
585void World::selectAtom(const atomId_t id){
586 ASSERT(atoms.count(id),"Atom Id selected that was not in the world");
587 selectedAtoms[id]=atoms[id];
588}
589
590void World::selectAllAtoms(AtomDescriptor descr){
591 internal_AtomIterator begin = getAtomIter_internal(descr);
592 internal_AtomIterator end = atomEnd_internal();
593 void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
594 for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
595}
596
597void World::selectAtomsOfMolecule(const molecule *_mol){
598 ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
599 // need to make it const to get the fast iterators
600 const molecule *mol = _mol;
601 void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
602 for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is select... see above
603}
604
605void World::selectAtomsOfMolecule(const moleculeId_t id){
606 ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
607 selectAtomsOfMolecule(molecules[id]);
608}
609
610void World::unselectAtom(const atom *_atom){
611 ASSERT(_atom,"Invalid pointer in unselection of atom");
612 unselectAtom(_atom->getId());
613}
614
615void World::unselectAtom(const atomId_t id){
616 ASSERT(atoms.count(id),"Atom Id unselected that was not in the world");
617 selectedAtoms.erase(id);
618}
619
620void World::unselectAllAtoms(AtomDescriptor descr){
621 internal_AtomIterator begin = getAtomIter_internal(descr);
622 internal_AtomIterator end = atomEnd_internal();
623 void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
624 for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
625}
626
627void World::unselectAtomsOfMolecule(const molecule *_mol){
628 ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
629 // need to make it const to get the fast iterators
630 const molecule *mol = _mol;
631 void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
632 for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is unsselect... see above
633}
634
635void World::unselectAtomsOfMolecule(const moleculeId_t id){
636 ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
637 unselectAtomsOfMolecule(molecules[id]);
638}
639
640size_t World::countSelectedAtoms() const {
641 size_t count = 0;
642 for (AtomSet::const_iterator iter = selectedAtoms.begin(); iter != selectedAtoms.end(); ++iter)
643 count++;
644 return count;
645}
646
647bool World::isSelected(const atom *_atom) const {
648 return isAtomSelected(_atom->getId());
649}
650
651bool World::isAtomSelected(const atomId_t no) const {
652 return selectedAtoms.find(no) != selectedAtoms.end();
653}
654
655const std::vector<atom *> World::getSelectedAtoms() const {
656 std::vector<atom *> returnAtoms;
657 returnAtoms.resize(countSelectedAtoms());
658 int count = 0;
659 for (AtomSet::const_iterator iter = selectedAtoms.begin(); iter != selectedAtoms.end(); ++iter)
660 returnAtoms[count++] = iter->second;
661 return returnAtoms;
662}
663
664
665// Molecules
666
667void World::clearMoleculeSelection(){
668 selectedMolecules.clear();
669}
670
671void World::selectMolecule(const molecule *_mol){
672 // molecule * is unchanged in this function, but we do store entity as changeable
673 ASSERT(_mol,"Invalid pointer to molecule in selection");
674 selectedMolecules[_mol->getId()]=const_cast<molecule *>(_mol);
675}
676
677void World::selectMolecule(const moleculeId_t id){
678 ASSERT(molecules.count(id),"Molecule Id selected that was not in the world");
679 selectedMolecules[id]=molecules[id];
680}
681
682void World::selectAllMolecules(MoleculeDescriptor descr){
683 internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
684 internal_MoleculeIterator end = moleculeEnd_internal();
685 void (World::*func)(const molecule*) = &World::selectMolecule; // needed for type resolution of overloaded function
686 for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
687}
688
689void World::selectMoleculeOfAtom(const atom *_atom){
690 ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom");
691 molecule *mol=_atom->getMolecule();
692 // the atom might not be part of a molecule
693 if(mol){
694 selectMolecule(mol);
695 }
696}
697
698void World::selectMoleculeOfAtom(const atomId_t id){
699 ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
700 selectMoleculeOfAtom(atoms[id]);
701}
702
703void World::unselectMolecule(const molecule *_mol){
704 ASSERT(_mol,"invalid pointer in unselection of molecule");
705 unselectMolecule(_mol->getId());
706}
707
708void World::unselectMolecule(const moleculeId_t id){
709 ASSERT(molecules.count(id),"No such molecule with ID in unselection");
710 selectedMolecules.erase(id);
711}
712
713void World::unselectAllMolecules(MoleculeDescriptor descr){
714 internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
715 internal_MoleculeIterator end = moleculeEnd_internal();
716 void (World::*func)(const molecule*) = &World::unselectMolecule; // needed for type resolution of overloaded function
717 for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
718}
719
720void World::unselectMoleculeOfAtom(const atom *_atom){
721 ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom");
722 molecule *mol=_atom->getMolecule();
723 // the atom might not be part of a molecule
724 if(mol){
725 unselectMolecule(mol);
726 }
727}
728
729void World::unselectMoleculeOfAtom(const atomId_t id){
730 ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
731 unselectMoleculeOfAtom(atoms[id]);
732}
733
734size_t World::countSelectedMolecules() const {
735 size_t count = 0;
736 for (MoleculeSet::const_iterator iter = selectedMolecules.begin(); iter != selectedMolecules.end(); ++iter)
737 count++;
738 return count;
739}
740
741bool World::isSelected(const molecule *_mol) const {
742 return isMoleculeSelected(_mol->getId());
743}
744
745bool World::isMoleculeSelected(const moleculeId_t no) const {
746 return selectedMolecules.find(no) != selectedMolecules.end();
747}
748
749const std::vector<molecule *> World::getSelectedMolecules() const {
750 std::vector<molecule *> returnMolecules;
751 returnMolecules.resize(countSelectedMolecules());
752 int count = 0;
753 for (MoleculeSet::const_iterator iter = selectedMolecules.begin(); iter != selectedMolecules.end(); ++iter)
754 returnMolecules[count++] = iter->second;
755 return returnMolecules;
756}
757
758/******************* Iterators over Selection *****************************/
759World::AtomSelectionIterator World::beginAtomSelection(){
760 return selectedAtoms.begin();
761}
762
763World::AtomSelectionIterator World::endAtomSelection(){
764 return selectedAtoms.end();
765}
766
767
768World::MoleculeSelectionIterator World::beginMoleculeSelection(){
769 return selectedMolecules.begin();
770}
771
772World::MoleculeSelectionIterator World::endMoleculeSelection(){
773 return selectedMolecules.end();
774}
775
776/******************************* Singleton Stuff **************************/
777
778World::World() :
779 Observable("World"),
780 BG(new BondGraph(true)), // assume Angstroem for the moment
781 periode(new periodentafel),
782 configuration(new config),
783 Thermostats(new ThermoStatContainer),
784 ExitFlag(0),
785 atoms(this),
786 selectedAtoms(this),
787 currAtomId(0),
788 lastAtomPoolSize(0),
789 numAtomDefragSkips(0),
790 molecules(this),
791 selectedMolecules(this),
792 currMoleculeId(0),
793 lastMoleculePoolSize(0),
794 numMoleculeDefragSkips(0),
795 molecules_deprecated(new MoleculeListClass(this))
796{
797 cell_size = new Box;
798 RealSpaceMatrix domain;
799 domain.at(0,0) = 20;
800 domain.at(1,1) = 20;
801 domain.at(2,2) = 20;
802 cell_size->setM(domain);
803 defaultName = "none";
804 NotificationChannels = new Channels(this);
805 for (size_t type = 0; type < (size_t)NotificationType_MAX; ++type)
806 NotificationChannels->addChannel(type);
807 molecules_deprecated->signOn(this);
808}
809
810World::~World()
811{
812 molecules_deprecated->signOff(this);
813 delete cell_size;
814 delete molecules_deprecated;
815 MoleculeSet::iterator molIter;
816 for(molIter=molecules.begin();molIter!=molecules.end();++molIter){
817 DeleteMolecule((*molIter).second);
818 }
819 molecules.clear();
820 AtomSet::iterator atIter;
821 for(atIter=atoms.begin();atIter!=atoms.end();++atIter){
822 DeleteAtom((*atIter).second);
823 }
824 atoms.clear();
825
826 // empty notifications
827 delete NotificationChannels;
828
829 delete BG;
830 delete periode;
831 delete configuration;
832 delete Thermostats;
833}
834
835// Explicit instantiation of the singleton mechanism at this point
836
837CONSTRUCT_SINGLETON(World)
838
839CONSTRUCT_OBSERVEDCONTAINER(World::AtomSTLSet)
840
841CONSTRUCT_OBSERVEDCONTAINER(World::MoleculeSTLSet)
842
843/******************************* deprecated Legacy Stuff ***********************/
844
845MoleculeListClass *&World::getMolecules() {
846 return molecules_deprecated;
847}
Note: See TracBrowser for help on using the repository browser.