source: src/World.cpp@ 5de9da

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 5de9da was 5d880e, checked in by Tillmann Crueger <crueger@…>, 15 years ago

Allowed observed access to iterators on Molecules

  • Property mode set to 100644
File size: 14.1 KB
Line 
1/*
2 * World.cpp
3 *
4 * Created on: Feb 3, 2010
5 * Author: crueger
6 */
7
8#include "Helpers/MemDebug.hpp"
9
10#include "World.hpp"
11#include "Patterns/ObservedContainer_impl.hpp"
12
13#include "atom.hpp"
14#include "config.hpp"
15#include "molecule.hpp"
16#include "periodentafel.hpp"
17#include "ThermoStatContainer.hpp"
18#include "Descriptors/AtomDescriptor.hpp"
19#include "Descriptors/AtomDescriptor_impl.hpp"
20#include "Descriptors/MoleculeDescriptor.hpp"
21#include "Descriptors/MoleculeDescriptor_impl.hpp"
22#include "Descriptors/SelectiveIterator_impl.hpp"
23#include "Actions/ManipulateAtomsProcess.hpp"
24#include "Helpers/Assert.hpp"
25#include "Box.hpp"
26#include "Matrix.hpp"
27#include "defs.hpp"
28
29#include "Patterns/Singleton_impl.hpp"
30
31using namespace std;
32
33/******************************* getter and setter ************************/
34periodentafel *&World::getPeriode(){
35 return periode;
36}
37
38config *&World::getConfig(){
39 return configuration;
40}
41
42// Atoms
43
44atom* World::getAtom(AtomDescriptor descriptor){
45 return descriptor.find();
46}
47
48vector<atom*> World::getAllAtoms(AtomDescriptor descriptor){
49 return descriptor.findAll();
50}
51
52vector<atom*> World::getAllAtoms(){
53 return getAllAtoms(AllAtoms());
54}
55
56int World::numAtoms(){
57 return atoms.size();
58}
59
60// Molecules
61
62molecule *World::getMolecule(MoleculeDescriptor descriptor){
63 return descriptor.find();
64}
65
66std::vector<molecule*> World::getAllMolecules(MoleculeDescriptor descriptor){
67 return descriptor.findAll();
68}
69
70std::vector<molecule*> World::getAllMolecules(){
71 return getAllMolecules(AllMolecules());
72}
73
74int World::numMolecules(){
75 return molecules_deprecated->ListOfMolecules.size();
76}
77
78// system
79
80Box& World::getDomain() {
81 return *cell_size;
82}
83
84void World::setDomain(const Matrix &mat){
85 *cell_size = mat;
86}
87
88void World::setDomain(double * matrix)
89{
90 Matrix M = ReturnFullMatrixforSymmetric(matrix);
91 cell_size->setM(M);
92}
93
94std::string World::getDefaultName() {
95 return defaultName;
96}
97
98void World::setDefaultName(std::string name)
99{
100 defaultName = name;
101};
102
103class ThermoStatContainer * World::getThermostats()
104{
105 return Thermostats;
106}
107
108
109int World::getExitFlag() {
110 return ExitFlag;
111}
112
113void World::setExitFlag(int flag) {
114 if (ExitFlag < flag)
115 ExitFlag = flag;
116}
117
118/******************** Methods to change World state *********************/
119
120molecule* World::createMolecule(){
121 OBSERVE;
122 molecule *mol = NULL;
123 mol = NewMolecule();
124 moleculeId_t id = getNextMoleculeId();
125 ASSERT(!molecules.count(id),"proposed id did not specify an unused ID");
126 mol->setId(id);
127 // store the molecule by ID
128 molecules[mol->getId()] = mol;
129 mol->signOn(this);
130 return mol;
131}
132
133void World::destroyMolecule(molecule* mol){
134 OBSERVE;
135 destroyMolecule(mol->getId());
136}
137
138void World::destroyMolecule(moleculeId_t id){
139 OBSERVE;
140 molecule *mol = molecules[id];
141 ASSERT(mol,"Molecule id that was meant to be destroyed did not exist");
142 DeleteMolecule(mol);
143 molecules.erase(id);
144 releaseMoleculeId(id);
145}
146
147atom *World::createAtom(){
148 OBSERVE;
149 atomId_t id = getNextAtomId();
150 ASSERT(!atoms.count(id),"proposed id did not specify an unused ID");
151 atom *res = NewAtom(id);
152 res->setWorld(this);
153 // store the atom by ID
154 atoms[res->getId()] = res;
155 return res;
156}
157
158
159int World::registerAtom(atom *atom){
160 OBSERVE;
161 atomId_t id = getNextAtomId();
162 atom->setId(id);
163 atom->setWorld(this);
164 atoms[atom->getId()] = atom;
165 return atom->getId();
166}
167
168void World::destroyAtom(atom* atom){
169 OBSERVE;
170 int id = atom->getId();
171 destroyAtom(id);
172}
173
174void World::destroyAtom(atomId_t id) {
175 OBSERVE;
176 atom *atom = atoms[id];
177 ASSERT(atom,"Atom ID that was meant to be destroyed did not exist");
178 DeleteAtom(atom);
179 atoms.erase(id);
180 releaseAtomId(id);
181}
182
183bool World::changeAtomId(atomId_t oldId, atomId_t newId, atom* target){
184 OBSERVE;
185 // in case this call did not originate from inside the atom, we redirect it,
186 // to also let it know that it has changed
187 if(!target){
188 target = atoms[oldId];
189 ASSERT(target,"Atom with that ID not found");
190 return target->changeId(newId);
191 }
192 else{
193 if(reserveAtomId(newId)){
194 atoms.erase(oldId);
195 atoms.insert(pair<atomId_t,atom*>(newId,target));
196 return true;
197 }
198 else{
199 return false;
200 }
201 }
202}
203
204ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name,AtomDescriptor descr){
205 return new ManipulateAtomsProcess(op, descr,name,true);
206}
207
208ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name){
209 return manipulateAtoms(op,name,AllAtoms());
210}
211
212/********************* Internal Change methods for double Callback and Observer mechanism ********/
213
214void World::doManipulate(ManipulateAtomsProcess *proc){
215 proc->signOn(this);
216 {
217 OBSERVE;
218 proc->doManipulate(this);
219 }
220 proc->signOff(this);
221}
222/******************************* IDManagement *****************************/
223
224// Atoms
225
226atomId_t World::getNextAtomId(){
227 // try to find an Id in the pool;
228 if(!atomIdPool.empty()){
229 atomIdPool_t::iterator iter=atomIdPool.begin();
230 atomId_t id = iter->first;
231 pair<atomId_t,atomId_t> newRange = make_pair(id+1,iter->second);
232 // we wont use this iterator anymore, so we don't care about invalidating
233 atomIdPool.erase(iter);
234 if(newRange.first<newRange.second){
235 atomIdPool.insert(newRange);
236 }
237 return id;
238 }
239 // Nothing in the pool... we are out of luck
240 return currAtomId++;
241}
242
243void World::releaseAtomId(atomId_t id){
244 atomIdPool.insert(make_pair(id,id+1));
245 defragAtomIdPool();
246}
247
248bool World::reserveAtomId(atomId_t id){
249 if(id>=currAtomId ){
250 pair<atomId_t,atomId_t> newRange = make_pair(currAtomId,id);
251 if(newRange.first<newRange.second){
252 atomIdPool.insert(newRange);
253 }
254 currAtomId=id+1;
255 defragAtomIdPool();
256 return true;
257 }
258 // look for a range that matches the request
259 for(atomIdPool_t::iterator iter=atomIdPool.begin();iter!=atomIdPool.end();++iter){
260 if(iter->first>id){
261 // we have coverd all available ranges... nothing to be found here
262 break;
263 }
264 // no need to check first, since it has to be <=id, since otherwise we would have broken out
265 if(iter->second > id){
266 // we found a matching range... get the id from this range
267
268 // split up this range at the point of id
269 pair<atomId_t,atomId_t> bottomRange = make_pair(iter->first,id);
270 pair<atomId_t,atomId_t> topRange = make_pair(id+1,iter->second);
271 // remove this range
272 atomIdPool.erase(iter);
273 if(bottomRange.first<bottomRange.second){
274 atomIdPool.insert(bottomRange);
275 }
276 if(topRange.first<topRange.second){
277 atomIdPool.insert(topRange);
278 }
279 defragAtomIdPool();
280 return true;
281 }
282 }
283 // this ID could not be reserved
284 return false;
285}
286
287void World::defragAtomIdPool(){
288 // check if the situation is bad enough to make defragging neccessary
289 if((numAtomDefragSkips<MAX_FRAGMENTATION_SKIPS) &&
290 (atomIdPool.size()<lastAtomPoolSize+MAX_POOL_FRAGMENTATION)){
291 ++numAtomDefragSkips;
292 return;
293 }
294 for(atomIdPool_t::iterator iter = atomIdPool.begin();iter!=atomIdPool.end();){
295 // see if this range is adjacent to the next one
296 atomIdPool_t::iterator next = iter;
297 next++;
298 if(next!=atomIdPool.end() && (next->first==iter->second)){
299 // merge the two ranges
300 pair<atomId_t,atomId_t> newRange = make_pair(iter->first,next->second);
301 atomIdPool.erase(iter);
302 atomIdPool.erase(next);
303 pair<atomIdPool_t::iterator,bool> res = atomIdPool.insert(newRange);
304 ASSERT(res.second,"Id-Pool was confused");
305 iter=res.first;
306 continue;
307 }
308 ++iter;
309 }
310 if(!atomIdPool.empty()){
311 // check if the last range is at the border
312 atomIdPool_t::iterator iter = atomIdPool.end();
313 iter--;
314 if(iter->second==currAtomId){
315 currAtomId=iter->first;
316 atomIdPool.erase(iter);
317 }
318 }
319 lastAtomPoolSize=atomIdPool.size();
320 numAtomDefragSkips=0;
321}
322
323// Molecules
324
325moleculeId_t World::getNextMoleculeId(){
326 // try to find an Id in the pool;
327 if(!moleculeIdPool.empty()){
328 moleculeIdPool_t::iterator iter=moleculeIdPool.begin();
329 moleculeId_t id = iter->first;
330 pair<moleculeId_t,moleculeId_t> newRange = make_pair(id+1,iter->second);
331 // we wont use this iterator anymore, so we don't care about invalidating
332 moleculeIdPool.erase(iter);
333 if(newRange.first<newRange.second){
334 moleculeIdPool.insert(newRange);
335 }
336 return id;
337 }
338 // Nothing in the pool... we are out of luck
339 return currMoleculeId++;
340}
341
342void World::releaseMoleculeId(moleculeId_t id){
343 moleculeIdPool.insert(make_pair(id,id+1));
344 defragMoleculeIdPool();
345}
346
347bool World::reserveMoleculeId(moleculeId_t id){
348 if(id>=currMoleculeId ){
349 pair<moleculeId_t,moleculeId_t> newRange = make_pair(currMoleculeId,id);
350 if(newRange.first<newRange.second){
351 moleculeIdPool.insert(newRange);
352 }
353 currMoleculeId=id+1;
354 defragMoleculeIdPool();
355 return true;
356 }
357 // look for a range that matches the request
358 for(moleculeIdPool_t::iterator iter=moleculeIdPool.begin();iter!=moleculeIdPool.end();++iter){
359 if(iter->first>id){
360 // we have coverd all available ranges... nothing to be found here
361 break;
362 }
363 // no need to check first, since it has to be <=id, since otherwise we would have broken out
364 if(iter->second > id){
365 // we found a matching range... get the id from this range
366
367 // split up this range at the point of id
368 pair<moleculeId_t,moleculeId_t> bottomRange = make_pair(iter->first,id);
369 pair<moleculeId_t,moleculeId_t> topRange = make_pair(id+1,iter->second);
370 // remove this range
371 moleculeIdPool.erase(iter);
372 if(bottomRange.first<bottomRange.second){
373 moleculeIdPool.insert(bottomRange);
374 }
375 if(topRange.first<topRange.second){
376 moleculeIdPool.insert(topRange);
377 }
378 defragMoleculeIdPool();
379 return true;
380 }
381 }
382 // this ID could not be reserved
383 return false;
384}
385
386void World::defragMoleculeIdPool(){
387 // check if the situation is bad enough to make defragging neccessary
388 if((numMoleculeDefragSkips<MAX_FRAGMENTATION_SKIPS) &&
389 (moleculeIdPool.size()<lastMoleculePoolSize+MAX_POOL_FRAGMENTATION)){
390 ++numMoleculeDefragSkips;
391 return;
392 }
393 for(moleculeIdPool_t::iterator iter = moleculeIdPool.begin();iter!=moleculeIdPool.end();){
394 // see if this range is adjacent to the next one
395 moleculeIdPool_t::iterator next = iter;
396 next++;
397 if(next!=moleculeIdPool.end() && (next->first==iter->second)){
398 // merge the two ranges
399 pair<moleculeId_t,moleculeId_t> newRange = make_pair(iter->first,next->second);
400 moleculeIdPool.erase(iter);
401 moleculeIdPool.erase(next);
402 pair<moleculeIdPool_t::iterator,bool> res = moleculeIdPool.insert(newRange);
403 ASSERT(res.second,"Id-Pool was confused");
404 iter=res.first;
405 continue;
406 }
407 ++iter;
408 }
409 if(!moleculeIdPool.empty()){
410 // check if the last range is at the border
411 moleculeIdPool_t::iterator iter = moleculeIdPool.end();
412 iter--;
413 if(iter->second==currMoleculeId){
414 currMoleculeId=iter->first;
415 moleculeIdPool.erase(iter);
416 }
417 }
418 lastMoleculePoolSize=moleculeIdPool.size();
419 numMoleculeDefragSkips=0;
420}
421
422/******************************* Iterators ********************************/
423
424// external parts with observers
425
426CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet,AtomDescriptor);
427
428World::AtomIterator
429World::getAtomIter(AtomDescriptor descr){
430 return AtomIterator(descr,atoms);
431}
432
433World::AtomIterator
434World::getAtomIter(){
435 return AtomIterator(AllAtoms(),atoms);
436}
437
438World::AtomIterator
439World::atomEnd(){
440 return AtomIterator(AllAtoms(),atoms,atoms.end());
441}
442
443CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor);
444
445World::MoleculeIterator
446World::getMoleculeIter(MoleculeDescriptor descr){
447 return MoleculeIterator(descr,molecules);
448}
449
450World::MoleculeIterator
451World::getMoleculeIter(){
452 return MoleculeIterator(AllMolecules(),molecules);
453}
454
455World::MoleculeIterator
456World::moleculeEnd(){
457 return MoleculeIterator(AllMolecules(),molecules,molecules.end());
458}
459
460// Internal parts, without observers
461
462// Build the AtomIterator from template
463CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet::set_t,AtomDescriptor);
464
465
466World::internal_AtomIterator
467World::getAtomIter_internal(AtomDescriptor descr){
468 return internal_AtomIterator(descr,atoms.getContent());
469}
470
471World::internal_AtomIterator
472World::atomEnd_internal(){
473 return internal_AtomIterator(AllAtoms(),atoms.getContent(),atoms.end_internal());
474}
475
476// build the MoleculeIterator from template
477CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet::set_t,MoleculeDescriptor);
478
479World::internal_MoleculeIterator World::getMoleculeIter_internal(MoleculeDescriptor descr){
480 return internal_MoleculeIterator(descr,molecules.getContent());
481}
482
483World::internal_MoleculeIterator World::moleculeEnd_internal(){
484 return internal_MoleculeIterator(AllMolecules(),molecules.getContent(),molecules.end_internal());
485}
486
487/******************************* Singleton Stuff **************************/
488
489World::World() :
490 Observable("World"),
491 periode(new periodentafel),
492 configuration(new config),
493 Thermostats(new ThermoStatContainer),
494 ExitFlag(0),
495 atoms(this),
496 currAtomId(0),
497 lastAtomPoolSize(0),
498 numAtomDefragSkips(0),
499 molecules(this),
500 currMoleculeId(0),
501 molecules_deprecated(new MoleculeListClass(this))
502{
503 cell_size = new Box;
504 Matrix domain;
505 domain.at(0,0) = 20;
506 domain.at(1,1) = 20;
507 domain.at(2,2) = 20;
508 cell_size->setM(domain);
509 defaultName = "none";
510 molecules_deprecated->signOn(this);
511}
512
513World::~World()
514{
515 molecules_deprecated->signOff(this);
516 delete cell_size;
517 delete molecules_deprecated;
518 delete periode;
519 delete configuration;
520 delete Thermostats;
521 MoleculeSet::iterator molIter;
522 for(molIter=molecules.begin();molIter!=molecules.end();++molIter){
523 DeleteMolecule((*molIter).second);
524 }
525 molecules.clear();
526 AtomSet::iterator atIter;
527 for(atIter=atoms.begin();atIter!=atoms.end();++atIter){
528 DeleteAtom((*atIter).second);
529 }
530 atoms.clear();
531}
532
533// Explicit instantiation of the singleton mechanism at this point
534
535CONSTRUCT_SINGLETON(World)
536
537/******************************* deprecated Legacy Stuff ***********************/
538
539MoleculeListClass *&World::getMolecules() {
540 return molecules_deprecated;
541}
Note: See TracBrowser for help on using the repository browser.