source: src/LinkedCell/LinkedCell_Model.cpp@ 143263

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 143263 was 94d5ac6, checked in by Frederik Heber <heber@…>, 12 years ago

FIX: As we use GSL internally, we are as of now required to use GPL v2 license.

  • GNU Scientific Library is used at every place in the code, especially the sub-package LinearAlgebra is based on it which in turn is used really everywhere in the remainder of MoleCuilder. Hence, we have to use the GPL license for the whole of MoleCuilder. In effect, GPL's COPYING was present all along and stated the terms of the GPL v2 license.
  • Hence, I added the default GPL v2 disclaimer to every source file and removed the note about a (actually missing) LICENSE file.
  • also, I added a help-redistribute action which again gives the disclaimer of the GPL v2.
  • also, I changed in the disclaimer that is printed at every program start in builder_init.cpp.
  • TEST: Added check on GPL statement present in every module to test CodeChecks project-disclaimer.
  • 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 ASSERT(iter != CellLookup.end(),
385 "LinkedCell_Model::deleteNode() - Walker not present in cell stored under CellLookup.");
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.