source: src/World.hpp@ e2c2b1

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 e2c2b1 was e2c2b1, checked in by Frederik Heber <heber@…>, 9 years ago

World's ObservedContainer no longer observe.

  • This requires CodePatterns 1.3.1 from now on.
  • I had misunderstood what Till had planed with these ObservedContainers for a long time: I though they would cause an OBSERVE signal for every iterator step but this is not the case. Rather they accumulate all OBSERVE signals to have them fire AFTER the loop is done. This is achieved through the depth count of the observer protectors.
  • Sadly, this runs against what we do with the lastchangedatom. We need the information right away as we the Observer/Observable stuff does not transport any information and always updating all is way too costly.
  • Hence, in CodePatterns we have implemented an UnobservedIterator which is used in ObservedContainer and does not cause any OBSERVE signals.
  • The source of the problem was createAtom() in a loop over selectedAtoms and these atoms not getting created (w.r.t QtInstanceBoard) before the molecule's got note of it (cause they are at depth 1).
  • Property mode set to 100644
File size: 18.7 KB
Line 
1/*
2 * World.hpp
3 *
4 * Created on: Feb 3, 2010
5 * Author: crueger
6 */
7
8#ifndef WORLD_HPP_
9#define WORLD_HPP_
10
11// include config.h
12#ifdef HAVE_CONFIG_H
13#include <config.h>
14#endif
15
16/*********************************************** includes ***********************************/
17
18#include <string>
19#include <map>
20#include <vector>
21#include <set>
22#include <stack>
23#include <boost/thread.hpp>
24#include <boost/shared_ptr.hpp>
25
26#include "Actions/ActionTrait.hpp"
27#include "Atom/AtomSet.hpp"
28#include "Descriptors/SelectiveConstIterator.hpp"
29#include "Descriptors/SelectiveIterator.hpp"
30#include "CodePatterns/Observer/Observable.hpp"
31#include "CodePatterns/Observer/Observer.hpp"
32#include "CodePatterns/Cacheable.hpp"
33#include "CodePatterns/Singleton.hpp"
34#include "CodePatterns/Observer/ObservedContainer.hpp"
35#include "CodePatterns/Range.hpp"
36#include "IdPool_policy.hpp"
37#include "IdPool.hpp"
38#include "LinkedCell/LinkedCell_View.hpp"
39#include "types.hpp"
40
41
42// forward declarations
43class atom;
44class AtomDescriptor;
45class AtomDescriptor_impl;
46class BondGraph;
47class Box;
48class config;
49class HomologyContainer;
50class RealSpaceMatrix;
51class molecule;
52class MoleculeDescriptor;
53class MoleculeDescriptor_impl;
54class MoleculeListClass;
55class periodentafel;
56class ThermoStatContainer;
57
58namespace LinkedCell {
59 class LinkedCell_Controller;
60}
61
62namespace MoleCuilder {
63 class ManipulateAtomsProcess;
64 template<typename T> class AtomsCalculation;
65}
66
67/****************************************** forward declarations *****************************/
68
69/********************************************** Class World *******************************/
70
71namespace detail {
72 template <class T> const T* lastChanged()
73 {
74 ASSERT(0, "detail::lastChanged() - only specializations may be used.");
75 return NULL;
76 }
77}
78
79class World : public Singleton<World>, public Observable
80{
81
82// Make access to constructor and destructor possible from inside the singleton
83friend class Singleton<World>;
84
85// necessary for coupling with descriptors
86friend class AtomDescriptor_impl;
87friend class AtomDescriptor;
88friend class MoleculeDescriptor_impl;
89friend class MoleculeDescriptor;
90// coupling with descriptors over selection
91friend class AtomSelectionDescriptor_impl;
92friend class AtomOfMoleculeSelectionDescriptor_impl;
93friend class AtomOrderDescriptor_impl;
94friend class MoleculeOfAtomSelectionDescriptor_impl;
95friend class MoleculeOrderDescriptor_impl;
96friend class MoleculeSelectionDescriptor_impl;
97
98// Actions, calculations etc associated with the World
99friend class MoleCuilder::ManipulateAtomsProcess;
100template<typename> friend class MoleCuilder::AtomsCalculation;
101public:
102 // some typedefs for the CONSTRUCT_... macros (no "," allows in a single parameter name)
103 typedef std::map<atomId_t,atom*> AtomSTLSet;
104 typedef std::map<moleculeId_t,molecule*> MoleculeSTLSet;
105
106 // Types for Atom and Molecule structures
107 typedef ObservedContainer< AtomSTLSet, UnobservedIterator<AtomSTLSet> > AtomSet;
108 typedef ObservedContainer< MoleculeSTLSet, UnobservedIterator<MoleculeSTLSet> > MoleculeSet;
109
110 typedef ATOMSET(std::vector) AtomComposite;
111 typedef CONSTATOMSET(std::vector) ConstAtomComposite;
112
113 /******* Notifications *******/
114
115 //!> enumeration of present notification types: only insertion/removal of atoms or molecules
116 enum NotificationType {
117 AtomInserted,
118 AtomRemoved,
119 MoleculeInserted,
120 MoleculeRemoved,
121 SelectionChanged,
122 NotificationType_MAX
123 };
124
125 //>! access to last changed element (atom or molecule)
126 template <class T> const T* lastChanged() const
127 { return detail::lastChanged<T>(); }
128
129 const atomId_t lastChangedAtomId() const
130 { return _lastchangedatomid; }
131
132 const moleculeId_t lastChangedMolId() const
133 { return _lastchangedmolid; }
134
135 /***** getter and setter *****/
136 // reference to pointer is used for legacy reason... reference will be removed latter to keep encapsulation of World object
137 /**
138 * returns the periodentafel for the world.
139 */
140 periodentafel *&getPeriode();
141
142 /** Returns the BondGraph for the World.
143 *
144 * @return reference to BondGraph
145 */
146 BondGraph *&getBondGraph();
147
148 /** Sets the World's BondGraph.
149 *
150 * @param _BG new BondGraph
151 */
152 void setBondGraph(BondGraph *_BG);
153
154 /** Getter for homology container.
155 *
156 * \return const reference to homology container.
157 */
158 HomologyContainer &getHomologies();
159
160 /** Setter for homology container.
161 *
162 * \param homologies reference to homologies, set to NULL
163 */
164 void resetHomologies(HomologyContainer *&homologies);
165
166 /**
167 * returns the configuration for the world.
168 */
169 config *&getConfig();
170
171 /** Returns a notification_ptr for a specific type.
172 *
173 * @param type request type
174 * @return reference to instance
175 */
176 Notification_ptr getNotification(enum NotificationType type) const;
177
178 /**
179 * returns the first atom that matches a given descriptor.
180 * Do not rely on ordering for descriptors that match more than one atom.
181 */
182 atom* getAtom(AtomDescriptor descriptor);
183
184 /**
185 * returns the first atom that matches a given descriptor.
186 * Do not rely on ordering for descriptors that match more than one atom.
187 */
188 const atom* getAtom(AtomDescriptor descriptor) const;
189
190 /**
191 * returns a vector containing all atoms that match a given descriptor
192 */
193 AtomComposite getAllAtoms(AtomDescriptor descriptor);
194
195 /**
196 * returns a vector containing all atoms that match a given descriptor
197 */
198 ConstAtomComposite getAllAtoms(AtomDescriptor descriptor) const;
199
200 /**
201 * returns a vector containing all atoms that match a given descriptor
202 */
203 AtomComposite getAllAtoms();
204
205 /**
206 * returns a vector containing all atoms that match a given descriptor
207 */
208 ConstAtomComposite getAllAtoms() const;
209
210 /**
211 * returns a calculation that calls a given function on all atoms matching a descriptor.
212 * the calculation is not called at this point and can be used as an action, i.e. be stored in
213 * menus, be kept around for later use etc.
214 */
215 template<typename T> MoleCuilder::AtomsCalculation<T>* calcOnAtoms(boost::function<T(atom*)>,const MoleCuilder::ActionTrait &_trait,AtomDescriptor);
216 template<typename T> MoleCuilder::AtomsCalculation<T>* calcOnAtoms(boost::function<T(atom*)>,const MoleCuilder::ActionTrait &_trait);
217
218 /**
219 * get the number of atoms in the World
220 */
221 int numAtoms() const;
222
223 /**
224 * returns the first molecule that matches a given descriptor.
225 * Do not rely on ordering for descriptors that match more than one molecule.
226 */
227 molecule *getMolecule(MoleculeDescriptor descriptor);
228
229 /**
230 * returns the first molecule that matches a given descriptor.
231 * Do not rely on ordering for descriptors that match more than one molecule.
232 */
233 const molecule *getMolecule(MoleculeDescriptor descriptor) const;
234
235 /**
236 * returns a vector containing all molecules that match a given descriptor
237 */
238 std::vector<molecule*> getAllMolecules(MoleculeDescriptor descriptor);
239
240 /**
241 * returns a vector containing all molecules that match a given descriptor
242 */
243 std::vector<const molecule*> getAllMolecules(MoleculeDescriptor descriptor) const;
244
245 /**
246 * returns a vector containing all molecules that match a given descriptor
247 */
248 std::vector<molecule*> getAllMolecules();
249 /**
250 * returns a vector containing all molecules that match a given descriptor
251 */
252 std::vector<const molecule*> getAllMolecules() const;
253
254 /**
255 * get the number of molecules in the World
256 */
257 int numMolecules() const;
258
259 /**
260 * get the domain size as a symmetric matrix (6 components)
261 */
262 Box& getDomain();
263
264 /**
265 * Set the domain size from a matrix object
266 *
267 * Matrix needs to be symmetric
268 */
269 void setDomain(const RealSpaceMatrix &mat);
270
271 /**
272 * set the domain size as a symmetric matrix (6 components)
273 */
274 void setDomain(double * matrix);
275
276 /** Returns a LinkedCell structure for obtaining neighbors quickly.
277 *
278 * @param distance desired linked cell edge length
279 * @return view of restricted underlying LinkedCell_Model
280 */
281 LinkedCell::LinkedCell_View getLinkedCell(const double distance);
282
283 /**
284 * set the current time of the world.
285 *
286 * @param _step time step to set to
287 */
288 void setTime(const unsigned int _step);
289
290 /**
291 * get the current time of the world.
292 *
293 * @return current time step
294 */
295 const unsigned getTime() const;
296
297 /**
298 * get the default name
299 */
300 std::string getDefaultName();
301
302 /**
303 * set the default name
304 */
305 void setDefaultName(std::string name);
306
307 /**
308 * get pointer to World's ThermoStatContainer
309 */
310 ThermoStatContainer * getThermostats();
311
312 /*
313 * get the ExitFlag
314 */
315 int getExitFlag();
316
317 /*
318 * set the ExitFlag
319 */
320 void setExitFlag(int flag);
321
322 /***** Methods to work with the World *****/
323
324 /**
325 * create a new molecule. This method should be used whenever any kind of molecule is needed. Assigns a unique
326 * ID to the molecule and stores it in the World for later retrieval. Do not create molecules directly.
327 */
328 molecule *createMolecule();
329
330 void destroyMolecule(molecule*);
331 void destroyMolecule(moleculeId_t);
332
333 /**
334 * Create a new atom. This method should be used whenever any atom is needed. Assigns a unique ID and stores
335 * the atom in the World. If the atom is not destroyed it will automatically be destroyed when the world ends.
336 */
337 atom *createAtom();
338
339 /**
340 * Registers a Atom unknown to world. Needed in some rare cases, e.g. when cloning atoms, or in some unittests.
341 * Do not re-register Atoms already known to the world since this will cause double-frees.
342 */
343 int registerAtom(atom*);
344
345 /**
346 * Delete some atom and erase it from the world. Use this whenever you need to destroy any atom. Do not call delete on
347 * atom directly since this will leave the pointer inside the world.
348 */
349 void destroyAtom(atom*);
350
351 /**
352 * Delete some atom and erase it from the world. Use this whenever you need to destroy any atom. Do not call delete on
353 * atom directly since this will leave the pointer inside the world.
354 */
355 void destroyAtom(atomId_t);
356
357 /**
358 * used when changing an atom Id.
359 * Unless you are calling this method from inside an atom don't fiddle with the third parameter.
360 *
361 * Return value indicates whether the change could be done or not.
362 */
363 bool changeAtomId(atomId_t oldId, atomId_t newId, atom* target=0);
364
365 /**
366 * used when changing an molecule Id.
367 * Unless you are calling this method from inside an molecule don't fiddle with the third parameter.
368 *
369 * Return value indicates whether the change could be done or not.
370 */
371 bool changeMoleculeId(moleculeId_t oldId, moleculeId_t newId, molecule* target=0);
372
373 /**
374 * Produces a process that calls a function on all Atoms matching a given descriptor. The process is not
375 * called at this time, so it can be passed around, stored inside menuItems etc.
376 */
377 MoleCuilder::ManipulateAtomsProcess* manipulateAtoms(boost::function<void(atom*)>,std::string,AtomDescriptor);
378 MoleCuilder::ManipulateAtomsProcess* manipulateAtoms(boost::function<void(atom*)>,std::string);
379
380 /****
381 * Iterators to use internal data structures
382 * All these iterators are observed to track changes.
383 * There is a corresponding protected section with unobserved iterators,
384 * which can be used internally when the extra speed is needed
385 */
386
387 typedef SelectiveIterator<atom*,AtomSet,AtomDescriptor> AtomIterator;
388 typedef SelectiveConstIterator<atom*,AtomSet,AtomDescriptor> AtomConstIterator;
389
390 /**
391 * returns an iterator over all Atoms matching a given descriptor.
392 * This iterator is observed, so don't keep it around unnecessary to
393 * avoid unintended blocking.
394 */
395 AtomIterator getAtomIter(AtomDescriptor descr);
396 AtomConstIterator getAtomIter(AtomDescriptor descr) const;
397 AtomIterator getAtomIter();
398 AtomConstIterator getAtomIter() const;
399
400 AtomIterator atomEnd();
401 AtomConstIterator atomEnd() const;
402
403 typedef SelectiveIterator<molecule*,MoleculeSet,MoleculeDescriptor> MoleculeIterator;
404 typedef SelectiveConstIterator<molecule*,MoleculeSet,MoleculeDescriptor> MoleculeConstIterator;
405
406 /**
407 * returns an iterator over all Molecules matching a given descriptor.
408 * This iterator is observed, so don't keep it around unnecessary to
409 * avoid unintended blocking.
410 */
411 MoleculeIterator getMoleculeIter(MoleculeDescriptor descr);
412 MoleculeConstIterator getMoleculeIter(MoleculeDescriptor descr) const;
413 MoleculeIterator getMoleculeIter();
414 MoleculeConstIterator getMoleculeIter() const;
415
416 MoleculeIterator moleculeEnd();
417 MoleculeConstIterator moleculeEnd() const;
418
419 /******** Selections of molecules and Atoms *************/
420 void clearAtomSelection();
421 void invertAtomSelection();
422 void popAtomSelection();
423 void pushAtomSelection();
424 void selectAtom(const atom*);
425 void selectAtom(const atomId_t);
426 void selectAllAtoms(AtomDescriptor);
427 void selectAtomsOfMolecule(const molecule*);
428 void selectAtomsOfMolecule(const moleculeId_t);
429 void unselectAtom(const atom*);
430 void unselectAtom(const atomId_t);
431 void unselectAllAtoms(AtomDescriptor);
432 void unselectAtomsOfMolecule(const molecule*);
433 void unselectAtomsOfMolecule(const moleculeId_t);
434 size_t countSelectedAtoms() const;
435 bool isSelected(const atom *_atom) const;
436 bool isAtomSelected(const atomId_t no) const;
437 std::vector<atom *> getSelectedAtoms();
438 std::vector<const atom *> getSelectedAtoms() const;
439 std::vector<atomId_t> getSelectedAtomIds() const;
440
441 void clearMoleculeSelection();
442 void invertMoleculeSelection();
443 void popMoleculeSelection();
444 void pushMoleculeSelection();
445 void selectMolecule(const molecule*);
446 void selectMolecule(const moleculeId_t);
447 void selectAllMolecules(MoleculeDescriptor);
448 void selectMoleculeOfAtom(const atom*);
449 void selectMoleculeOfAtom(const atomId_t);
450 void unselectMolecule(const molecule*);
451 void unselectMolecule(const moleculeId_t);
452 void unselectAllMolecules(MoleculeDescriptor);
453 void unselectMoleculeOfAtom(const atom*);
454 void unselectMoleculeOfAtom(const atomId_t);
455 size_t countSelectedMolecules() const;
456 bool isSelected(const molecule *_mol) const;
457 bool isMoleculeSelected(const moleculeId_t no) const;
458 std::vector<molecule *> getSelectedMolecules();
459 std::vector<const molecule *> getSelectedMolecules() const;
460 std::vector<moleculeId_t> getSelectedMoleculeIds() const;
461
462 /******************** Iterators to selections *****************/
463 typedef AtomSet::iterator AtomSelectionIterator;
464 AtomSelectionIterator beginAtomSelection();
465 AtomSelectionIterator endAtomSelection();
466 typedef AtomSet::const_iterator AtomSelectionConstIterator;
467 AtomSelectionConstIterator beginAtomSelection() const;
468 AtomSelectionConstIterator endAtomSelection() const;
469
470 typedef MoleculeSet::iterator MoleculeSelectionIterator;
471 MoleculeSelectionIterator beginMoleculeSelection();
472 MoleculeSelectionIterator endMoleculeSelection();
473 typedef MoleculeSet::const_iterator MoleculeSelectionConstIterator;
474 MoleculeSelectionConstIterator beginMoleculeSelection() const;
475 MoleculeSelectionConstIterator endMoleculeSelection() const;
476
477protected:
478 /****
479 * Iterators to use internal data structures
480 * All these iterators are unobserved for speed reasons.
481 * There is a corresponding public section to these methods,
482 * which produce observed iterators.*/
483
484 // Atoms
485 typedef SelectiveIterator<atom*,AtomSet::set_t,AtomDescriptor> internal_AtomIterator;
486
487 /**
488 * returns an iterator over all Atoms matching a given descriptor.
489 * used for internal purposes, like AtomProcesses and AtomCalculations.
490 */
491 internal_AtomIterator getAtomIter_internal(AtomDescriptor descr);
492
493 /**
494 * returns an iterator to the end of the AtomSet. Due to overloading this iterator
495 * can be compared to iterators produced by getAtomIter (see the mis-matching types).
496 * Thus it can be used to detect when such an iterator is at the end of the list.
497 * used for internal purposes, like AtomProcesses and AtomCalculations.
498 */
499 internal_AtomIterator atomEnd_internal();
500
501 // Molecules
502 typedef SelectiveIterator<molecule*,MoleculeSet::set_t,MoleculeDescriptor> internal_MoleculeIterator;
503
504
505 /**
506 * returns an iterator over all Molecules matching a given descriptor.
507 * used for internal purposes, like MoleculeProcesses and MoleculeCalculations.
508 */
509 internal_MoleculeIterator getMoleculeIter_internal(MoleculeDescriptor descr);
510
511 /**
512 * returns an iterator to the end of the MoleculeSet. Due to overloading this iterator
513 * can be compared to iterators produced by getMoleculeIter (see the mis-matching types).
514 * Thus it can be used to detect when such an iterator is at the end of the list.
515 * used for internal purposes, like MoleculeProcesses and MoleculeCalculations.
516 */
517 internal_MoleculeIterator moleculeEnd_internal();
518
519
520 /******* Internal manipulation routines for double callback and Observer mechanism ******/
521 void doManipulate(MoleCuilder::ManipulateAtomsProcess *);
522
523private:
524
525 friend const atom *detail::lastChanged<atom>();
526 friend const molecule *detail::lastChanged<molecule>();
527 static atom *_lastchangedatom;
528 static atomId_t _lastchangedatomid;
529 static molecule*_lastchangedmol;
530 static moleculeId_t _lastchangedmolid;
531
532 BondGraph *BG;
533 periodentafel *periode;
534 config *configuration;
535 HomologyContainer *homologies;
536 Box *cell_size;
537 LinkedCell::LinkedCell_Controller *LCcontroller;
538 std::string defaultName;
539 class ThermoStatContainer *Thermostats;
540 int ExitFlag;
541private:
542
543 AtomSet atoms;
544 AtomSet selectedAtoms;
545 typedef std::vector<atomId_t> atomIdsVector_t;
546 std::stack<atomIdsVector_t> selectedAtoms_Stack;
547 /**
548 * stores the pool for all available AtomIds below currAtomId
549 *
550 * The pool contains ranges of free ids in the form [bottom,top).
551 */
552 IdPool<atomId_t, uniqueId> atomIdPool;
553
554 MoleculeSet molecules;
555 MoleculeSet selectedMolecules;
556 typedef std::vector<moleculeId_t> moleculeIdsVector_t;
557 std::stack<moleculeIdsVector_t> selectedMolecules_Stack;
558 /**
559 * stores the pool for all available AtomIds below currAtomId
560 *
561 * The pool contains ranges of free ids in the form [bottom,top).
562 */
563 IdPool<moleculeId_t, continuousId> moleculeIdPool;
564
565private:
566 /**
567 * private constructor to ensure creation of the world using
568 * the singleton pattern.
569 */
570 World();
571
572 /**
573 * private destructor to ensure destruction of the world using the
574 * singleton pattern.
575 */
576 virtual ~World();
577
578 /*****
579 * some legacy stuff that is include for now but will be removed later
580 *****/
581public:
582 MoleculeListClass *&getMolecules();
583
584private:
585 MoleculeListClass *molecules_deprecated;
586};
587
588/** Externalized stuff as member functions cannot be specialized without
589 * specializing the class, too.
590 */
591namespace detail {
592 template <> inline const atom* lastChanged<atom>() { return World::_lastchangedatom; }
593 template <> inline const molecule* lastChanged<molecule>() { return World::_lastchangedmol; }
594}
595
596
597#endif /* WORLD_HPP_ */
Note: See TracBrowser for help on using the repository browser.