source: src/World.cpp@ b7ff03

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 b7ff03 was 7188b1, checked in by Frederik Heber <heber@…>, 14 years ago

Introduced atom_observables and GLWorldView observes World, GLMoleculeObject_atom observes its atom.

Observer changes:

  • new Channels pattern required from CodePatterns 1.1.5 and that Observable signing on and off is now with const instance possible.
  • class atom is now observable, encapsulated in class AtomObservable:
    • enums have notification types
    • we use NotificationChannels of Observable to emit these distinct types.
  • atominfo, particleinfo, bondedparticleinfo all have OBSERVE and NOTIFY(..) in their setter functions (thx encapsulation).
  • class GLMoleculeObject_atom signs on to atom to changes to position, element, and index.
  • World equally has notifications for atom (new,remove) and molecules (new, remove).
  • GLWorldView now observes World for these changes.

Other changes:

  • removed additional hierarchy level for GLWidget of molecules (i.e. GLMoleculeScene removed and incorporated into GLWorldScene).
  • Property mode set to 100644
File size: 23.5 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 OBSERVE;
228 int id = atom->getId();
229 destroyAtom(id);
230}
231
232void World::destroyAtom(atomId_t id) {
233 OBSERVE;
234 atom *atom = atoms[id];
235 ASSERT(atom,"Atom ID that was meant to be destroyed did not exist");
236 _lastchangedatom = atom;
237 NOTIFY(AtomRemoved);
238 DeleteAtom(atom);
239 atoms.erase(id);
240 releaseAtomId(id);
241}
242
243bool World::changeAtomId(atomId_t oldId, atomId_t newId, atom* target){
244 OBSERVE;
245 // in case this call did not originate from inside the atom, we redirect it,
246 // to also let it know that it has changed
247 if(!target){
248 target = atoms[oldId];
249 ASSERT(target,"Atom with that ID not found");
250 return target->changeId(newId);
251 }
252 else{
253 if(reserveAtomId(newId)){
254 atoms.erase(oldId);
255 atoms.insert(pair<atomId_t,atom*>(newId,target));
256 return true;
257 }
258 else{
259 return false;
260 }
261 }
262}
263
264bool World::changeMoleculeId(moleculeId_t oldId, moleculeId_t newId, molecule* target){
265 OBSERVE;
266 // in case this call did not originate from inside the atom, we redirect it,
267 // to also let it know that it has changed
268 if(!target){
269 target = molecules[oldId];
270 ASSERT(target,"Molecule with that ID not found");
271 return target->changeId(newId);
272 }
273 else{
274 if(reserveMoleculeId(newId)){
275 molecules.erase(oldId);
276 molecules.insert(pair<moleculeId_t,molecule*>(newId,target));
277 return true;
278 }
279 else{
280 return false;
281 }
282 }
283}
284
285ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name,AtomDescriptor descr){
286 ActionTraits manipulateTrait(name);
287 return new ManipulateAtomsProcess(op, descr,manipulateTrait,false);
288}
289
290ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name){
291 return manipulateAtoms(op,name,AllAtoms());
292}
293
294/********************* Internal Change methods for double Callback and Observer mechanism ********/
295
296void World::doManipulate(ManipulateAtomsProcess *proc){
297 proc->signOn(this);
298 {
299 OBSERVE;
300 proc->doManipulate(this);
301 }
302 proc->signOff(this);
303}
304/******************************* IDManagement *****************************/
305
306// Atoms
307
308atomId_t World::getNextAtomId(){
309 // try to find an Id in the pool;
310 if(!atomIdPool.empty()){
311 atomIdPool_t::iterator iter=atomIdPool.begin();
312 atomId_t id = iter->first;
313 range<atomId_t> newRange = makeRange(id+1,iter->last);
314 // we wont use this iterator anymore, so we don't care about invalidating
315 atomIdPool.erase(iter);
316 if(newRange.first<newRange.last){
317 atomIdPool.insert(newRange);
318 }
319 return id;
320 }
321 // Nothing in the pool... we are out of luck
322 return currAtomId++;
323}
324
325void World::releaseAtomId(atomId_t id){
326 atomIdPool.insert(makeRange(id,id+1));
327 defragAtomIdPool();
328}
329
330bool World::reserveAtomId(atomId_t id){
331 if(id>=currAtomId ){
332 range<atomId_t> newRange = makeRange(currAtomId,id);
333 if(newRange.first<newRange.last){
334 atomIdPool.insert(newRange);
335 }
336 currAtomId=id+1;
337 defragAtomIdPool();
338 return true;
339 }
340 // look for a range that matches the request
341 for(atomIdPool_t::iterator iter=atomIdPool.begin();iter!=atomIdPool.end();++iter){
342 if(iter->isBefore(id)){
343 // we have covered all available ranges... nothing to be found here
344 break;
345 }
346 // no need to check first, since it has to be <=id, since otherwise we would have broken out
347 if(!iter->isBeyond(id)){
348 // we found a matching range... get the id from this range
349
350 // split up this range at the point of id
351 range<atomId_t> bottomRange = makeRange(iter->first,id);
352 range<atomId_t> topRange = makeRange(id+1,iter->last);
353 // remove this range
354 atomIdPool.erase(iter);
355 if(bottomRange.first<bottomRange.last){
356 atomIdPool.insert(bottomRange);
357 }
358 if(topRange.first<topRange.last){
359 atomIdPool.insert(topRange);
360 }
361 defragAtomIdPool();
362 return true;
363 }
364 }
365 // this ID could not be reserved
366 return false;
367}
368
369void World::defragAtomIdPool(){
370 // check if the situation is bad enough to make defragging neccessary
371 if((numAtomDefragSkips<MAX_FRAGMENTATION_SKIPS) &&
372 (atomIdPool.size()<lastAtomPoolSize+MAX_POOL_FRAGMENTATION)){
373 ++numAtomDefragSkips;
374 return;
375 }
376 for(atomIdPool_t::iterator iter = atomIdPool.begin();iter!=atomIdPool.end();){
377 // see if this range is adjacent to the next one
378 atomIdPool_t::iterator next = iter;
379 next++;
380 if(next!=atomIdPool.end() && (next->first==iter->last)){
381 // merge the two ranges
382 range<atomId_t> newRange = makeRange(iter->first,next->last);
383 atomIdPool.erase(iter);
384 atomIdPool.erase(next);
385 pair<atomIdPool_t::iterator,bool> res = atomIdPool.insert(newRange);
386 ASSERT(res.second,"Id-Pool was confused");
387 iter=res.first;
388 continue;
389 }
390 ++iter;
391 }
392 if(!atomIdPool.empty()){
393 // check if the last range is at the border
394 atomIdPool_t::iterator iter = atomIdPool.end();
395 iter--;
396 if(iter->last==currAtomId){
397 currAtomId=iter->first;
398 atomIdPool.erase(iter);
399 }
400 }
401 lastAtomPoolSize=atomIdPool.size();
402 numAtomDefragSkips=0;
403}
404
405// Molecules
406
407moleculeId_t World::getNextMoleculeId(){
408 // try to find an Id in the pool;
409 if(!moleculeIdPool.empty()){
410 moleculeIdPool_t::iterator iter=moleculeIdPool.begin();
411 moleculeId_t id = iter->first;
412 range<moleculeId_t> newRange = makeRange(id+1,iter->last);
413 // we wont use this iterator anymore, so we don't care about invalidating
414 moleculeIdPool.erase(iter);
415 if(newRange.first<newRange.last){
416 moleculeIdPool.insert(newRange);
417 }
418 return id;
419 }
420 // Nothing in the pool... we are out of luck
421 return currMoleculeId++;
422}
423
424void World::releaseMoleculeId(moleculeId_t id){
425 moleculeIdPool.insert(makeRange(id,id+1));
426 defragMoleculeIdPool();
427}
428
429bool World::reserveMoleculeId(moleculeId_t id){
430 if(id>=currMoleculeId ){
431 range<moleculeId_t> newRange = makeRange(currMoleculeId,id);
432 if(newRange.first<newRange.last){
433 moleculeIdPool.insert(newRange);
434 }
435 currMoleculeId=id+1;
436 defragMoleculeIdPool();
437 return true;
438 }
439 // look for a range that matches the request
440 for(moleculeIdPool_t::iterator iter=moleculeIdPool.begin();iter!=moleculeIdPool.end();++iter){
441 if(iter->isBefore(id)){
442 // we have coverd all available ranges... nothing to be found here
443 break;
444 }
445 // no need to check first, since it has to be <=id, since otherwise we would have broken out
446 if(!iter->isBeyond(id)){
447 // we found a matching range... get the id from this range
448
449 // split up this range at the point of id
450 range<moleculeId_t> bottomRange = makeRange(iter->first,id);
451 range<moleculeId_t> topRange = makeRange(id+1,iter->last);
452 // remove this range
453 moleculeIdPool.erase(iter);
454 if(bottomRange.first<bottomRange.last){
455 moleculeIdPool.insert(bottomRange);
456 }
457 if(topRange.first<topRange.last){
458 moleculeIdPool.insert(topRange);
459 }
460 defragMoleculeIdPool();
461 return true;
462 }
463 }
464 // this ID could not be reserved
465 return false;
466}
467
468void World::defragMoleculeIdPool(){
469 // check if the situation is bad enough to make defragging neccessary
470 if((numMoleculeDefragSkips<MAX_FRAGMENTATION_SKIPS) &&
471 (moleculeIdPool.size()<lastMoleculePoolSize+MAX_POOL_FRAGMENTATION)){
472 ++numMoleculeDefragSkips;
473 return;
474 }
475 for(moleculeIdPool_t::iterator iter = moleculeIdPool.begin();iter!=moleculeIdPool.end();){
476 // see if this range is adjacent to the next one
477 moleculeIdPool_t::iterator next = iter;
478 next++;
479 if(next!=moleculeIdPool.end() && (next->first==iter->last)){
480 // merge the two ranges
481 range<moleculeId_t> newRange = makeRange(iter->first,next->last);
482 moleculeIdPool.erase(iter);
483 moleculeIdPool.erase(next);
484 pair<moleculeIdPool_t::iterator,bool> res = moleculeIdPool.insert(newRange);
485 ASSERT(res.second,"Id-Pool was confused");
486 iter=res.first;
487 continue;
488 }
489 ++iter;
490 }
491 if(!moleculeIdPool.empty()){
492 // check if the last range is at the border
493 moleculeIdPool_t::iterator iter = moleculeIdPool.end();
494 iter--;
495 if(iter->last==currMoleculeId){
496 currMoleculeId=iter->first;
497 moleculeIdPool.erase(iter);
498 }
499 }
500 lastMoleculePoolSize=moleculeIdPool.size();
501 numMoleculeDefragSkips=0;
502}
503
504/******************************* Iterators ********************************/
505
506// external parts with observers
507
508CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet,AtomDescriptor);
509
510World::AtomIterator
511World::getAtomIter(AtomDescriptor descr){
512 return AtomIterator(descr,atoms);
513}
514
515World::AtomIterator
516World::getAtomIter(){
517 return AtomIterator(AllAtoms(),atoms);
518}
519
520World::AtomIterator
521World::atomEnd(){
522 return AtomIterator(AllAtoms(),atoms,atoms.end());
523}
524
525CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor);
526
527World::MoleculeIterator
528World::getMoleculeIter(MoleculeDescriptor descr){
529 return MoleculeIterator(descr,molecules);
530}
531
532World::MoleculeIterator
533World::getMoleculeIter(){
534 return MoleculeIterator(AllMolecules(),molecules);
535}
536
537World::MoleculeIterator
538World::moleculeEnd(){
539 return MoleculeIterator(AllMolecules(),molecules,molecules.end());
540}
541
542// Internal parts, without observers
543
544// Build the AtomIterator from template
545CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet::set_t,AtomDescriptor);
546
547
548World::internal_AtomIterator
549World::getAtomIter_internal(AtomDescriptor descr){
550 return internal_AtomIterator(descr,atoms.getContent());
551}
552
553World::internal_AtomIterator
554World::atomEnd_internal(){
555 return internal_AtomIterator(AllAtoms(),atoms.getContent(),atoms.end_internal());
556}
557
558// build the MoleculeIterator from template
559CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet::set_t,MoleculeDescriptor);
560
561World::internal_MoleculeIterator World::getMoleculeIter_internal(MoleculeDescriptor descr){
562 return internal_MoleculeIterator(descr,molecules.getContent());
563}
564
565World::internal_MoleculeIterator World::moleculeEnd_internal(){
566 return internal_MoleculeIterator(AllMolecules(),molecules.getContent(),molecules.end_internal());
567}
568
569/************************** Selection of Atoms and molecules ******************/
570
571// Atoms
572
573void World::clearAtomSelection(){
574 selectedAtoms.clear();
575}
576
577void World::selectAtom(const atom *_atom){
578 // atom * is unchanged in this function, but we do store entity as changeable
579 ASSERT(_atom,"Invalid pointer in selection of atom");
580 selectedAtoms[_atom->getId()]=const_cast<atom *>(_atom);
581}
582
583void World::selectAtom(const atomId_t id){
584 ASSERT(atoms.count(id),"Atom Id selected that was not in the world");
585 selectedAtoms[id]=atoms[id];
586}
587
588void World::selectAllAtoms(AtomDescriptor descr){
589 internal_AtomIterator begin = getAtomIter_internal(descr);
590 internal_AtomIterator end = atomEnd_internal();
591 void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
592 for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
593}
594
595void World::selectAtomsOfMolecule(const molecule *_mol){
596 ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
597 // need to make it const to get the fast iterators
598 const molecule *mol = _mol;
599 void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
600 for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is select... see above
601}
602
603void World::selectAtomsOfMolecule(const moleculeId_t id){
604 ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
605 selectAtomsOfMolecule(molecules[id]);
606}
607
608void World::unselectAtom(const atom *_atom){
609 ASSERT(_atom,"Invalid pointer in unselection of atom");
610 unselectAtom(_atom->getId());
611}
612
613void World::unselectAtom(const atomId_t id){
614 ASSERT(atoms.count(id),"Atom Id unselected that was not in the world");
615 selectedAtoms.erase(id);
616}
617
618void World::unselectAllAtoms(AtomDescriptor descr){
619 internal_AtomIterator begin = getAtomIter_internal(descr);
620 internal_AtomIterator end = atomEnd_internal();
621 void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
622 for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
623}
624
625void World::unselectAtomsOfMolecule(const molecule *_mol){
626 ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
627 // need to make it const to get the fast iterators
628 const molecule *mol = _mol;
629 void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
630 for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is unsselect... see above
631}
632
633void World::unselectAtomsOfMolecule(const moleculeId_t id){
634 ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
635 unselectAtomsOfMolecule(molecules[id]);
636}
637
638size_t World::countSelectedAtoms() const {
639 size_t count = 0;
640 for (AtomSet::const_iterator iter = selectedAtoms.begin(); iter != selectedAtoms.end(); ++iter)
641 count++;
642 return count;
643}
644
645bool World::isSelected(const atom *_atom) const {
646 return selectedAtoms.find(_atom->getId()) != selectedAtoms.end();
647}
648
649const std::vector<atom *> World::getSelectedAtoms() const {
650 std::vector<atom *> returnAtoms;
651 returnAtoms.resize(countSelectedAtoms());
652 int count = 0;
653 for (AtomSet::const_iterator iter = selectedAtoms.begin(); iter != selectedAtoms.end(); ++iter)
654 returnAtoms[count++] = iter->second;
655 return returnAtoms;
656}
657
658
659// Molecules
660
661void World::clearMoleculeSelection(){
662 selectedMolecules.clear();
663}
664
665void World::selectMolecule(const molecule *_mol){
666 // molecule * is unchanged in this function, but we do store entity as changeable
667 ASSERT(_mol,"Invalid pointer to molecule in selection");
668 selectedMolecules[_mol->getId()]=const_cast<molecule *>(_mol);
669}
670
671void World::selectMolecule(const moleculeId_t id){
672 ASSERT(molecules.count(id),"Molecule Id selected that was not in the world");
673 selectedMolecules[id]=molecules[id];
674}
675
676void World::selectAllMolecules(MoleculeDescriptor descr){
677 internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
678 internal_MoleculeIterator end = moleculeEnd_internal();
679 void (World::*func)(const molecule*) = &World::selectMolecule; // needed for type resolution of overloaded function
680 for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
681}
682
683void World::selectMoleculeOfAtom(const atom *_atom){
684 ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom");
685 molecule *mol=_atom->getMolecule();
686 // the atom might not be part of a molecule
687 if(mol){
688 selectMolecule(mol);
689 }
690}
691
692void World::selectMoleculeOfAtom(const atomId_t id){
693 ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
694 selectMoleculeOfAtom(atoms[id]);
695}
696
697void World::unselectMolecule(const molecule *_mol){
698 ASSERT(_mol,"invalid pointer in unselection of molecule");
699 unselectMolecule(_mol->getId());
700}
701
702void World::unselectMolecule(const moleculeId_t id){
703 ASSERT(molecules.count(id),"No such molecule with ID in unselection");
704 selectedMolecules.erase(id);
705}
706
707void World::unselectAllMolecules(MoleculeDescriptor descr){
708 internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
709 internal_MoleculeIterator end = moleculeEnd_internal();
710 void (World::*func)(const molecule*) = &World::unselectMolecule; // needed for type resolution of overloaded function
711 for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
712}
713
714void World::unselectMoleculeOfAtom(const atom *_atom){
715 ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom");
716 molecule *mol=_atom->getMolecule();
717 // the atom might not be part of a molecule
718 if(mol){
719 unselectMolecule(mol);
720 }
721}
722
723void World::unselectMoleculeOfAtom(const atomId_t id){
724 ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
725 unselectMoleculeOfAtom(atoms[id]);
726}
727
728size_t World::countSelectedMolecules() const {
729 size_t count = 0;
730 for (MoleculeSet::const_iterator iter = selectedMolecules.begin(); iter != selectedMolecules.end(); ++iter)
731 count++;
732 return count;
733}
734
735bool World::isSelected(const molecule *_mol) const {
736 return selectedMolecules.find(_mol->getId()) != selectedMolecules.end();
737}
738
739const std::vector<molecule *> World::getSelectedMolecules() const {
740 std::vector<molecule *> returnMolecules;
741 returnMolecules.resize(countSelectedMolecules());
742 int count = 0;
743 for (MoleculeSet::const_iterator iter = selectedMolecules.begin(); iter != selectedMolecules.end(); ++iter)
744 returnMolecules[count++] = iter->second;
745 return returnMolecules;
746}
747
748/******************* Iterators over Selection *****************************/
749World::AtomSelectionIterator World::beginAtomSelection(){
750 return selectedAtoms.begin();
751}
752
753World::AtomSelectionIterator World::endAtomSelection(){
754 return selectedAtoms.end();
755}
756
757
758World::MoleculeSelectionIterator World::beginMoleculeSelection(){
759 return selectedMolecules.begin();
760}
761
762World::MoleculeSelectionIterator World::endMoleculeSelection(){
763 return selectedMolecules.end();
764}
765
766/******************************* Singleton Stuff **************************/
767
768World::World() :
769 Observable("World"),
770 BG(new BondGraph(true)), // assume Angstroem for the moment
771 periode(new periodentafel),
772 configuration(new config),
773 Thermostats(new ThermoStatContainer),
774 ExitFlag(0),
775 atoms(this),
776 selectedAtoms(this),
777 currAtomId(0),
778 lastAtomPoolSize(0),
779 numAtomDefragSkips(0),
780 molecules(this),
781 selectedMolecules(this),
782 currMoleculeId(0),
783 lastMoleculePoolSize(0),
784 numMoleculeDefragSkips(0),
785 molecules_deprecated(new MoleculeListClass(this))
786{
787 cell_size = new Box;
788 RealSpaceMatrix domain;
789 domain.at(0,0) = 20;
790 domain.at(1,1) = 20;
791 domain.at(2,2) = 20;
792 cell_size->setM(domain);
793 defaultName = "none";
794 NotificationChannels = new Channels(this);
795 for (size_t type = 0; type < (size_t)NotificationType_MAX; ++type)
796 NotificationChannels->addChannel(type);
797 molecules_deprecated->signOn(this);
798}
799
800World::~World()
801{
802 molecules_deprecated->signOff(this);
803 delete cell_size;
804 delete molecules_deprecated;
805 MoleculeSet::iterator molIter;
806 for(molIter=molecules.begin();molIter!=molecules.end();++molIter){
807 DeleteMolecule((*molIter).second);
808 }
809 molecules.clear();
810 AtomSet::iterator atIter;
811 for(atIter=atoms.begin();atIter!=atoms.end();++atIter){
812 DeleteAtom((*atIter).second);
813 }
814 atoms.clear();
815
816 // empty notifications
817 delete NotificationChannels;
818
819 delete BG;
820 delete periode;
821 delete configuration;
822 delete Thermostats;
823}
824
825// Explicit instantiation of the singleton mechanism at this point
826
827CONSTRUCT_SINGLETON(World)
828
829CONSTRUCT_OBSERVEDCONTAINER(World::AtomSTLSet)
830
831CONSTRUCT_OBSERVEDCONTAINER(World::MoleculeSTLSet)
832
833/******************************* deprecated Legacy Stuff ***********************/
834
835MoleculeListClass *&World::getMolecules() {
836 return molecules_deprecated;
837}
Note: See TracBrowser for help on using the repository browser.