source: src/LinkedCell/LinkedCell_Model.cpp@ ac9dc8

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes
Last change on this file since ac9dc8 was 9eb71b3, checked in by Frederik Heber <frederik.heber@…>, 8 years ago

Commented out MemDebug include and Memory::ignore.

  • MemDebug clashes with various allocation operators that use a specific placement in memory. It is so far not possible to wrap new/delete fully. Hence, we stop this effort which so far has forced us to put ever more includes (with clashes) into MemDebug and thereby bloat compilation time.
  • MemDebug does not add that much usefulness which is not also provided by valgrind.
  • Property mode set to 100644
File size: 20.2 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2012 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * LinkedCell_Model.cpp
25 *
26 * Created on: Nov 15, 2011
27 * Author: heber
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35//#include "CodePatterns/MemDebug.hpp"
36
37#include "LinkedCell_Model.hpp"
38
39#include <algorithm>
40#include <boost/bind.hpp>
41#include <boost/multi_array.hpp>
42#include <limits>
43
44#include "Atom/AtomObserver.hpp"
45#include "Atom/TesselPoint.hpp"
46#include "Box.hpp"
47#include "CodePatterns/Assert.hpp"
48#include "CodePatterns/Info.hpp"
49#include "CodePatterns/Log.hpp"
50#include "CodePatterns/Observer/Observer.hpp"
51#include "CodePatterns/Observer/Notification.hpp"
52#include "CodePatterns/toString.hpp"
53#include "LinearAlgebra/RealSpaceMatrix.hpp"
54#include "LinearAlgebra/Vector.hpp"
55#include "LinkedCell/IPointCloud.hpp"
56#include "LinkedCell/LinkedCell.hpp"
57#include "LinkedCell/LinkedCell_Model_changeModel.hpp"
58#include "LinkedCell/LinkedCell_Model_LinkedCellArrayCache.hpp"
59#include "World.hpp"
60
61// initialize static entities
62LinkedCell::tripleIndex LinkedCell::LinkedCell_Model::NearestNeighbors;
63
64
65/** Constructor of LinkedCell_Model.
66 *
67 * @param radius desired maximum neighborhood distance
68 * @param _domain Box instance with domain size and boundary conditions
69 */
70LinkedCell::LinkedCell_Model::LinkedCell_Model(const double radius, const Box &_domain) :
71 ::Observer(std::string("LinkedCell_Model")+std::string("_")+toString(radius)),
72 Changes( new changeModel(radius) ),
73 internal_Sizes(NULL),
74 N(new LinkedCellArrayCache(Changes, boost::bind(&changeModel::performUpdates, Changes), std::string("N_cached"))),
75 domain(_domain)
76{
77 // set default argument
78 NearestNeighbors[0] = NearestNeighbors[1] = NearestNeighbors[2] = 1;
79
80 // get the partition of the domain
81 setPartition(radius);
82
83 // allocate linked cell structure
84 AllocateCells();
85
86 // sign in to AtomObserver
87 startListening();
88}
89
90/** Constructor of LinkedCell_Model.
91 *
92 * @oaram set set of points to place into the linked cell structure
93 * @param radius desired maximum neighborhood distance
94 * @param _domain Box instance with domain size and boundary conditions
95 */
96LinkedCell::LinkedCell_Model::LinkedCell_Model(IPointCloud &set, const double radius, const Box &_domain) :
97 ::Observer(std::string("LinkedCell_Model")+std::string("_")+toString(radius)),
98 Changes( new changeModel(radius) ),
99 internal_Sizes(NULL),
100 N(new LinkedCellArrayCache(Changes, boost::bind(&changeModel::performUpdates, Changes), std::string("N_cached"))),
101 domain(_domain)
102{
103 Info info(__func__);
104
105 // get the partition of the domain
106 setPartition(radius);
107
108 // allocate linked cell structure
109 AllocateCells();
110
111 insertPointCloud(set);
112
113 // sign in to AtomObserver
114 startListening();
115}
116
117/** Destructor of class LinkedCell_Model.
118 *
119 */
120LinkedCell::LinkedCell_Model::~LinkedCell_Model()
121{
122 // sign off from observables
123 stopListening();
124
125 // reset linked cell structure
126 Reset();
127 delete N;
128
129 // delete change queue
130 delete Changes;
131}
132
133/** Signs in to AtomObserver and World to known about all changes.
134 *
135 */
136void LinkedCell::LinkedCell_Model::startListening()
137{
138 World::getInstance().signOn(this, World::AtomInserted);
139 World::getInstance().signOn(this, World::AtomRemoved);
140 AtomObserver::getInstance().signOn(this, AtomObservable::PositionChanged);
141}
142
143/** Signs off from AtomObserver and World.
144 *
145 */
146void LinkedCell::LinkedCell_Model::stopListening()
147{
148 World::getInstance().signOff(this, World::AtomInserted);
149 World::getInstance().signOff(this, World::AtomRemoved);
150 AtomObserver::getInstance().signOff(this, AtomObservable::PositionChanged);
151}
152
153
154/** Allocates as much cells per axis as required by
155 * LinkedCell_Model::BoxPartition.
156 *
157 */
158void LinkedCell::LinkedCell_Model::AllocateCells()
159{
160 // resize array
161 tripleIndex index;
162 for (int i=0;i<NDIM;i++)
163 index[i] = static_cast<LinkedCellArray::index>(Dimensions.at(i,i));
164 N->setN().resize(index);
165 ASSERT(getSize(0)*getSize(1)*getSize(2) < MAX_LINKEDCELLNODES,
166 "LinkedCell_Model::AllocateCells() - Number linked of linked cell nodes exceeded hard-coded limit, use greater edge length!");
167 LOG(1, "INFO: Allocating array ("
168 << getSize(0) << ","
169 << getSize(1) << ","
170 << getSize(2) << ") for a new LinkedCell_Model.");
171
172 // allocate LinkedCell instances
173 for(index[0] = 0; index[0] != static_cast<LinkedCellArray::index>(Dimensions.at(0,0)); ++index[0]) {
174 for(index[1] = 0; index[1] != static_cast<LinkedCellArray::index>(Dimensions.at(1,1)); ++index[1]) {
175 for(index[2] = 0; index[2] != static_cast<LinkedCellArray::index>(Dimensions.at(2,2)); ++index[2]) {
176 LOG(5, "INFO: Creating cell at " << index[0] << " " << index[1] << " " << index[2] << ".");
177 N->setN()(index) = new LinkedCell(index);
178 }
179 }
180 }
181}
182
183/** Frees all Linked Cell instances and sets array dimensions to (0,0,0).
184 *
185 */
186void LinkedCell::LinkedCell_Model::Reset()
187{
188 // free all LinkedCell instances
189 for(iterator3 iter3 = N->setN().begin(); iter3 != N->setN().end(); ++iter3) {
190 for(iterator2 iter2 = (*iter3).begin(); iter2 != (*iter3).end(); ++iter2) {
191 for(iterator1 iter1 = (*iter2).begin(); iter1 != (*iter2).end(); ++iter1) {
192 delete *iter1;
193 }
194 }
195 }
196 // set dimensions to zero
197 N->setN().resize(boost::extents[0][0][0]);
198}
199
200/** Inserts all points contained in \a set.
201 *
202 * @param set set with points to insert into linked cell structure
203 */
204void LinkedCell::LinkedCell_Model::insertPointCloud(IPointCloud &set)
205{
206 if (set.IsEmpty()) {
207 ELOG(1, "set is NULL or contains no linked cell nodes!");
208 return;
209 }
210
211 // put each atom into its respective cell
212 set.GoToFirst();
213 while (!set.IsEnd()) {
214 TesselPoint *Walker = set.GetPoint();
215 addNode(Walker);
216 set.GoToNext();
217 }
218}
219
220/** Calculates the required edge length for the given desired distance.
221 *
222 * We need to make some matrix transformations in order to obtain the required
223 * edge lengths per axis. Goal is guarantee that whatever the shape of the
224 * domain that always all points at least up to \a distance away are contained
225 * in the nearest neighboring cells.
226 *
227 * @param distance distance of this linked cell array
228 */
229void LinkedCell::LinkedCell_Model::setPartition(double distance)
230{
231 // generate box matrix of desired edge length
232 RealSpaceMatrix neighborhood;
233 neighborhood.setIdentity();
234 neighborhood *= distance;
235
236 // obtain refs to both domain matrix transformations
237 //const RealSpaceMatrix &M = domain.getM();
238 const RealSpaceMatrix &Minv = domain.getMinv();
239
240 RealSpaceMatrix output = Minv * neighborhood;
241 std::cout << Minv << " * " << neighborhood << " = " << output << std::endl;
242
243 Dimensions = output.invert();
244 std::cout << "Dimensions are then " << Dimensions << std::endl;
245
246 // now dimensions is floating-point, but we need it to be integer (for allocation)
247 for (size_t col = 0; col < NDIM; ++col) {
248 for (size_t row = 0; row < NDIM; ++row) {
249 ASSERT(fabs(Dimensions.at(row,col) - Dimensions.at(col,row)) < 1.e+3*std::numeric_limits<double>::epsilon(),
250 "LinkedCell_Model::setPartition() - Dimensions is not symmetric by "
251 +toString(fabs(Dimensions.at(row,col) - Dimensions.at(col,row)))+ ".");
252 if (col != row) {
253 ASSERT(fabs(Dimensions.at(row,col)) < 1.e+3*std::numeric_limits<double>::epsilon(),
254 "LinkedCell_Model::setPartition() - Dimensions is not diagonal by "
255 +toString(fabs(Dimensions.at(row,col)))+".");
256 } else {
257 Dimensions.set(row,col, ceil(Dimensions.at(row,col)));
258 }
259 }
260 }
261
262
263 Partition = Minv*Dimensions; //
264
265 std::cout << "Partition matrix is then " << Partition << std::endl;
266}
267
268/** Returns the number of required neighbor-shells to get all neighboring points
269 * in the given \a distance.
270 *
271 * @param distance radius of neighborhood sphere
272 * @return number of LinkedCell's per dimension to get all neighbors
273 */
274const LinkedCell::tripleIndex LinkedCell::LinkedCell_Model::getStep(const double distance) const
275{
276 tripleIndex index;
277 index[0] = index[1] = index[2] = 0;
278
279 if (fabs(distance) < std::numeric_limits<double>::min())
280 return index;
281 // generate box matrix of desired edge length
282 RealSpaceMatrix neighborhood;
283 neighborhood.setIdentity();
284 neighborhood *= distance;
285
286 const RealSpaceMatrix output = Partition * neighborhood;
287
288 //std::cout << "GetSteps: " << Partition << " * " << neighborhood << " = " << output << std::endl;
289
290 const RealSpaceMatrix steps = output;
291 for (size_t i =0; i<NDIM; ++i)
292 index[i] = ceil(steps.at(i,i));
293 LOG(2, "INFO: number of shells are ("+toString(index[0])+","+toString(index[1])+","+toString(index[2])+").");
294
295 return index;
296}
297
298/** Calculates the index of the cell \a position would belong to.
299 *
300 * @param position position whose associated cell to calculate
301 * @return index of the cell
302 */
303const LinkedCell::tripleIndex LinkedCell::LinkedCell_Model::getIndexToVector(const Vector &position) const
304{
305 ASSERT(domain.isValid(position),
306 "LinkedCell::LinkedCell_Model::getIndexToVector() - specified position "+toString(position)
307 +"is not valid in the current domain.");
308 tripleIndex index;
309 Vector x(Partition*domain.enforceBoundaryConditions(position));
310 LOG(2, "INFO: Transformed position is " << x << ".");
311 for (int i=0;i<NDIM;i++) {
312 index[i] = static_cast<LinkedCellArray::index>(floor(x[i]));
313 }
314 return index;
315}
316
317/** Adds an update to the list of lazy changes to add a node.
318 *
319 * @param Walker node to add
320 */
321void LinkedCell::LinkedCell_Model::addNode(const TesselPoint *Walker)
322{
323 LOG(2, "INFO: Requesting update to add node " << *Walker << ".");
324 Changes->addUpdate(Walker, 0, boost::bind(&LinkedCell_Model::addNode_internal, this, _1));
325}
326
327/** Adds an update to the list of lazy changes to add remove a node.
328 *
329 * We do nothing of Walker is not found
330 *
331 * @param Walker node to remove
332 */
333void LinkedCell::LinkedCell_Model::deleteNode(const TesselPoint *Walker)
334{
335 LOG(2, "INFO: Requesting update to delete node " << *Walker << ".");
336 Changes->addUpdate(Walker, 0, boost::bind(&LinkedCell_Model::deleteNode_internal, this, _1));
337}
338
339/** Adds an update to the list of lazy changes to move a node.
340 *
341 * @param Walker node who has moved.
342 */
343void LinkedCell::LinkedCell_Model::moveNode(const TesselPoint *Walker)
344{
345 LOG(2, "INFO: Requesting update to move node " << *Walker << " to position "
346 << Walker->getPosition() << ".");
347 Changes->addUpdate(Walker, 10, boost::bind(&LinkedCell_Model::moveNode_internal, this, _1));
348}
349
350/** Internal function to add a node to the linked cell structure
351 *
352 * @param Walker node to add
353 */
354void LinkedCell::LinkedCell_Model::addNode_internal(const TesselPoint *Walker)
355{
356 // find index
357 tripleIndex index = getIndexToVector(Walker->getPosition());
358 LOG(2, "INFO: " << *Walker << " goes into cell " << index[0] << ", " << index[1] << ", " << index[2] << ".");
359 LOG(2, "INFO: Cell's indices are "
360 << (N->getN())(index)->getIndex(0) << " "
361 << (N->getN())(index)->getIndex(1) << " "
362 << (N->getN())(index)->getIndex(2) << ".");
363 // add to cell
364 (N->setN())(index)->addPoint(Walker);
365 // add to index with check for presence
366 std::pair<MapPointToCell::iterator, bool> inserter = CellLookup.insert( std::make_pair(Walker, (N->setN())(index)) );
367 ASSERT( inserter.second,
368 "LinkedCell_Model::addNode() - Walker "
369 +toString(*Walker)+" is already present in cell "
370 +toString((inserter.first)->second->getIndex(0))+" "
371 +toString((inserter.first)->second->getIndex(1))+" "
372 +toString((inserter.first)->second->getIndex(2))+".");
373}
374
375/** Internal function to remove a node to the linked cell structure
376 *
377 * We do nothing of Walker is not found
378 *
379 * @param Walker node to remove
380 */
381void LinkedCell::LinkedCell_Model::deleteNode_internal(const TesselPoint *Walker)
382{
383 MapPointToCell::iterator iter = CellLookup.find(Walker);
384 // must not ASSERT presence as addNode might have been overrided by this
385 // deleteNode update and hence the node will not be present
386 if (iter != CellLookup.end()) {
387 // remove from lookup
388 CellLookup.erase(iter);
389 // remove from cell
390 iter->second->deletePoint(Walker);
391 }
392}
393
394/** Internal function to move node from current cell to another on position change.
395 *
396 * @param Walker node who has moved.
397 */
398void LinkedCell::LinkedCell_Model::moveNode_internal(const TesselPoint *Walker)
399{
400 MapPointToCell::iterator iter = CellLookup.find(Walker);
401 ASSERT(iter != CellLookup.end(),
402 "LinkedCell_Model::deleteNode() - Walker not present in cell stored under CellLookup.");
403 if (iter != CellLookup.end()) {
404 tripleIndex index = getIndexToVector(Walker->getPosition());
405 if (index != iter->second->getIndices()) {
406 // remove in old cell
407 iter->second->deletePoint(Walker);
408 // add to new cell
409 N->setN()(index)->addPoint(Walker);
410 // update lookup
411 iter->second = N->setN()(index);
412 }
413 }
414}
415
416/** Checks whether cell indicated by \a relative relative to LinkedCell_Model::internal_index
417 * is out of bounds.
418 *
419 * \note We do not check for boundary conditions of LinkedCell_Model::domain,
420 * we only look at the array sizes
421 *
422 * @param relative index relative to LinkedCell_Model::internal_index.
423 * @return true - relative index is still inside bounds, false - outside
424 */
425bool LinkedCell::LinkedCell_Model::checkArrayBounds(const tripleIndex &index) const
426{
427 bool status = true;
428 for (size_t i=0;i<NDIM;++i) {
429 status = status && (
430 (index[i] >= 0) &&
431 (index[i] < getSize(i))
432 );
433 }
434 return status;
435}
436
437/** Corrects \a index according to boundary conditions of LinkedCell_Model::domain .
438 *
439 * @param index index to correct according to boundary conditions
440 */
441void LinkedCell::LinkedCell_Model::applyBoundaryConditions(tripleIndex &index) const
442{
443 for (size_t i=0;i<NDIM;++i) {
444 switch (domain.getConditions()[i]) {
445 case BoundaryConditions::Wrap:
446 if ((index[i] < 0) || (index[i] >= getSize(i)))
447 index[i] = (index[i] % getSize(i));
448 break;
449 case BoundaryConditions::Bounce:
450 if (index[i] < 0)
451 index[i] = 0;
452 if (index[i] >= getSize(i))
453 index[i] = getSize(i)-1;
454 break;
455 case BoundaryConditions::Ignore:
456 if (index[i] < 0)
457 index[i] = 0;
458 if (index[i] >= getSize(i))
459 index[i] = getSize(i)-1;
460 break;
461 default:
462 ASSERT(0, "LinkedCell_Model::checkBounds() - unknown boundary conditions.");
463 break;
464 }
465 }
466}
467
468/** Calculates the interval bounds of the linked cell grid.
469 *
470 * The neighborhood bounds works as follows: We give the lower, left, front
471 * corner of the box and the number of boxes to go in each direction (i.e. the
472 * relative upper, right, behind corner). We assure that the first corner is
473 * within LinkedCell_Model::N, whether the relative second corner is within the
474 * domain must be assured via applying its boundary conditions, see
475 * LinkedCell_Model::applyBoundaryConditions()
476 *
477 * \note we check whether \a index is valid, i.e. within the range of LinkedCell_Model::N.
478 *
479 * \param index index to give relative bounds to
480 * \param step how deep to check the neighbouring cells (i.e. number of layers to check)
481 * \return pair of tripleIndex indicating lower and upper bounds
482 */
483const LinkedCell::LinkedCell_Model::LinkedCellNeighborhoodBounds LinkedCell::LinkedCell_Model::getNeighborhoodBounds(
484 const tripleIndex &index,
485 const tripleIndex &step
486 ) const
487{
488 LinkedCellNeighborhoodBounds neighbors;
489
490 // calculate bounds
491 for (size_t i=0;i<NDIM;++i) {
492 ASSERT(index[i] >= 0,
493 "LinkedCell_Model::getNeighborhoodBounds() - index "
494 +toString(index)+" out of lower bounds.");
495 ASSERT (index[i] < getSize(i),
496 "LinkedCell_Model::getNeighborhoodBounds() - index "
497 +toString(index)+" out of upper bounds.");
498 switch (domain.getConditions()[i]) {
499 case BoundaryConditions::Wrap:
500 if ((index[i] - step[i]) < 0)
501 neighbors.first[i] = getSize(i) + (index[i] - step[i]);
502 else if ((index[i] - step[i]) >= getSize(i))
503 neighbors.first[i] = (index[i] - step[i]) - getSize(i);
504 else
505 neighbors.first[i] = index[i] - step[i];
506 neighbors.second[i] = 2*step[i]+1;
507 break;
508 case BoundaryConditions::Bounce:
509 neighbors.second[i] = 2*step[i]+1;
510 if (index[i] - step[i] >= 0) {
511 neighbors.first[i] = index[i] - step[i];
512 } else {
513 neighbors.first[i] = 0;
514 neighbors.second[i] = index[i] + step[i]+1;
515 }
516 if (index[i] + step[i] >= getSize(i)) {
517 neighbors.second[i] = getSize(i) - (index[i] - step[i]);
518 }
519 break;
520 case BoundaryConditions::Ignore:
521 if (index[i] - step[i] < 0)
522 neighbors.first[i] = 0;
523 else
524 neighbors.first[i] = index[i] - step[i];
525 if ((neighbors.first[i] + 2*step[i]+1) >= getSize(i))
526 neighbors.second[i] = getSize(i) - neighbors.first[i];
527 else
528 neighbors.second[i] = 2*step[i]+1;
529 break;
530 default:
531 ASSERT(0, "LinkedCell_Model::getNeighborhoodBounds() - unknown boundary conditions.");
532 break;
533 }
534 // check afterwards whether we now have correct
535 ASSERT((neighbors.first[i] >= 0) && (neighbors.first[i] < getSize(i)),
536 "LinkedCell_Model::getNeighborhoodBounds() - lower border "
537 +toString(neighbors.first)+" is out of bounds.");
538 }
539 LOG(3, "INFO: Resulting neighborhood bounds are [" << neighbors.first << "]<->[" << neighbors.second << "].");
540
541 return neighbors;
542}
543
544/** Returns a reference to the cell indicated by LinkedCell_Model::internal_index.
545 *
546 * \return LinkedCell ref to current cell
547 */
548const LinkedCell::LinkedCell& LinkedCell::LinkedCell_Model::getCell(const tripleIndex &index) const
549{
550 return *(N->getN()(index));
551}
552
553
554/** Returns size of array for given \a dim.
555 *
556 * @param dim desired dimension
557 * @return size of array along dimension
558 */
559LinkedCell::LinkedCellArray::index LinkedCell::LinkedCell_Model::getSize(const size_t dim) const
560{
561 ASSERT((dim >= 0) && (dim < NDIM),
562 "LinkedCell_Model::getSize() - dimension "
563 +toString(dim)+" is out of bounds.");
564 return N->getN().shape()[dim];
565}
566
567/** Callback function for Observer mechanism.
568 *
569 * @param publisher reference to the Observable that calls
570 */
571void LinkedCell::LinkedCell_Model::update(Observable *publisher)
572{
573 ELOG(2, "LinkedCell_Model received inconclusive general update from "
574 << publisher << ".");
575}
576
577/** Callback function for the Notifications mechanism.
578 *
579 * @param publisher reference to the Observable that calls
580 * @param notification specific notification as cause of the call
581 */
582void LinkedCell::LinkedCell_Model::recieveNotification(Observable *publisher, Notification_ptr notification)
583{
584 // either it's the World or from the atom (through relay) itself
585 if (publisher == World::getPointer()) {
586 switch(notification->getChannelNo()) {
587 case World::AtomInserted:
588 addNode(World::getInstance().lastChanged<atom>());
589 break;
590 case World::AtomRemoved:
591 deleteNode(World::getInstance().lastChanged<atom>());
592 break;
593 }
594 } else {
595 switch(notification->getChannelNo()) {
596 case AtomObservable::PositionChanged:
597 {
598 moveNode(dynamic_cast<const TesselPoint *>(publisher));
599 break;
600 }
601 default:
602 LOG(2, "LinkedCell_Model received unwanted notification from AtomObserver's channel "
603 << notification->getChannelNo() << ".");
604 break;
605 }
606 }
607}
608
609/** Callback function when an Observer dies.
610 *
611 * @param publisher reference to the Observable that calls
612 */
613void LinkedCell::LinkedCell_Model::subjectKilled(Observable *publisher)
614{}
615
Note: See TracBrowser for help on using the repository browser.