source: src/World.cpp@ ce133f

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 ce133f was 38f991, checked in by Frederik Heber <heber@…>, 13 years ago

FormatParser now listens to World::AtomRemoved and ::AtomInserted notifications.

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