RepastHPC  2.3.1
SharedBaseGrid.h
1 /*
2  * Repast for High Performance Computing (Repast HPC)
3  *
4  * Copyright (c) 2010 Argonne National Laboratory
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with
8  * or without modification, are permitted provided that the following
9  * conditions are met:
10  *
11  * Redistributions of source code must retain the above copyright notice,
12  * this list of conditions and the following disclaimer.
13  *
14  * Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * Neither the name of the Argonne National Laboratory nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TRUSTEES OR
26  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  *
35  * SharedBaseGrid.h
36  *
37  * Created on: Sep 10, 2009
38  * Author: nick
39  */
40 
41 #ifndef SHAREDBASEGRID_H_
42 #define SHAREDBASEGRID_H_
43 
44 #include <cmath>
45 #include <mpi.h>
46 #include <iostream>
47 #include <algorithm>
48 #include <sstream>
49 
50 #include "BaseGrid.h"
51 #include "GridComponents.h"
52 #include "MultipleOccupancy.h"
53 #include "RepastProcess.h"
54 #include "logger.h"
55 #include "SRManager.h"
56 #include "RepastErrors.h"
57 #include "RelativeLocation.h"
58 #include "CartesianTopology.h"
59 
60 namespace repast {
61 
62 
68 class Neighbor {
69 
70 private:
71  int _rank;
72  GridDimensions _bounds;
73 
74 public:
75  Neighbor(int rank, GridDimensions bounds);
76 
77  int rank() const { return _rank; }
78  GridDimensions bounds() const { return _bounds; }
79 
80 };
81 
82 
87 class Neighbors {
88 
89  friend std::ostream& operator<<(std::ostream& os, const Neighbors& nghs);
90 
91 private:
92 
93  std::vector<Neighbor*> nghs;
94 
95 
96 public:
97 
98  Neighbors(int numberOfNeighbors);
99  virtual ~Neighbors();
100 
105  void addNeighbor(Neighbor* ngh, RelativeLocation relLoc);
106 
113 
119  Neighbor* findNeighbor(const std::vector<int>& pt);
120 
126  Neighbor* findNeighbor(const std::vector<double>& pt);
127 
128  void getNeighborRanks(std::set<int>& ranks) {
129  for(std::vector<Neighbor*>::iterator iter = nghs.begin(), iterEnd=nghs.end(); iter != iterEnd; ++iter) {
130  Neighbor* ngh = *iter;
131  if (ngh != 0) {
132  ranks.insert((*iter)->rank());
133  }
134  }
135  }
136 
137  Neighbor* getNeighborByIndex(int index){
138  if(index < 0|| index >= nghs.size()) return 0;
139  return nghs[index];
140  }
141 
142 };
143 
144 std::ostream& operator<<(std::ostream& os, const Neighbors& nghs);
145 
146 
147 
167 template<typename T, typename GPTransformer, typename Adder, typename GPType>
168 class SharedBaseGrid: public BaseGrid<T, MultipleOccupancy<T, GPType> , GPTransformer, Adder, GPType> {
169 
170 private:
171  CartesianTopology* cartTopology;
172 
173 protected:
174  int _buffer;
175  GridDimensions localBounds;
176  GridDimensions globalBounds;
177  Neighbors* nghs;
178  // vector of ids of agents in this spaces buffer
179  std::vector<AgentId> buffered;
180 // GridDimensions createSendBufferBounds(std::vector<int> relativeLocation);
181 
182  virtual void synchMoveTo(const AgentId& id, const Point<GPType>& pt) = 0;
183 
184  int rank;
185  typedef typename repast::BaseGrid<T, MultipleOccupancy<T, GPType> , GPTransformer, Adder, GPType> GridBaseType;
186  boost::mpi::communicator* comm;
187 
188 public:
189  void balance();
190 
191  // overriding moveTo that takes newLocation hides the moveTo in the
192  // Grid base class that takes a Point. This using directive
193  // makes the Point arg moveTo available.
194  using GridBaseType::moveTo;
195 
206  SharedBaseGrid(std::string name, GridDimensions gridDims, std::vector<int> processDims, int buffer, boost::mpi::communicator* communicator);
207  virtual ~SharedBaseGrid();
208 
214  virtual GridDimensions const bounds() const {
215  return globalBounds;
216  }
217 
218 
226  virtual const GridDimensions dimensions() const {
227  return localBounds;
228  }
229 
230  // doc inherited from BaseGrid.h
231  virtual bool moveTo(const AgentId& id, const std::vector<GPType>& newLocation);
232 
233  // doc inherited from BaseGrid.h
234  virtual bool moveTo(const AgentId& id, const Point<GPType>& pt);
235 
236  virtual void removeAgent(T* agent);
237 
238  // doc inherited from Projection.h
239 
240  virtual void getRequiredAgents(std::set<AgentId>& agentsToTest, std::set<AgentId>& agentsRequired){ } // Grids don't keep agents
241 
242  virtual void getAgentsToPush(std::set<AgentId>& agentsToTest, std::map<int, std::set<AgentId> >& agentsToPush);
243 
244 
245  virtual void getInfoExchangePartners(std::set<int>& psToSendTo, std::set<int>& psToReceiveFrom){
246  nghs->getNeighborRanks(psToSendTo);
247  nghs->getNeighborRanks(psToReceiveFrom);
248  }
249 
250  virtual void getAgentStatusExchangePartners(std::set<int>& psToSendTo, std::set<int>& psToReceiveFrom){
251  nghs->getNeighborRanks(psToSendTo);
252  nghs->getNeighborRanks(psToReceiveFrom);
253  }
254 
255  virtual void updateProjectionInfo(ProjectionInfoPacket* pip, Context<T>* context);
256 
257 };
258 
259 template<typename T, typename GPTransformer, typename Adder, typename GPType>
261  int> processDims, int buffer, boost::mpi::communicator* communicator) :
262  GridBaseType(name, gridDims), _buffer(buffer), comm(communicator), globalBounds(gridDims) {
263 
264  int dimCount = gridDims.dimensionCount();
265  if (processDims.size() != dimCount)
266  throw Repast_Error_50<GridDimensions>(dimCount, gridDims, processDims.size()); // Number of grid dimensions must be equal to number of process dimensions
267 
268  rank = comm->rank();
269  bool periodic = GridBaseType::gpTransformer.isPeriodic();
270 
271  cartTopology = RepastProcess::instance()->getCartesianTopology(processDims, periodic);
272 
273  std::vector<int> coords;
274  cartTopology->getCoordinates(rank, coords);
275 
276  localBounds = cartTopology->getDimensions(rank, gridDims);
277  GridBaseType::adder.init(localBounds, this);
278 
279  RelativeLocation relLocUntrimmed(dimCount);
280  RelativeLocation relLoc = cartTopology->trim(rank, relLocUntrimmed);
281 
282  nghs = new Neighbors(relLoc.getMaxIndex() + 1);
283 
284  do{
285  vector<int> currentVal = relLoc.getCurrentValue();
286  int rankOfNeighbor = cartTopology->getRank(coords, currentVal);
287  if(rankOfNeighbor != rank && rankOfNeighbor != MPI_PROC_NULL){ // Note: the test for MPI_PROC_NULL is vestigial; by trimming the Relative Location, there should never be any
288  Neighbor* ngh = new Neighbor(rankOfNeighbor, cartTopology->getDimensions(rankOfNeighbor, gridDims));
289  nghs->addNeighbor(ngh, relLoc);
290  }
291  }while(relLoc.increment());
292 
293 }
294 
295 template<typename T, typename GPTransformer, typename Adder, typename GPType>
297  delete nghs;
298 }
299 
300 
301 //template<typename T, typename GPTransformer, typename Adder, typename GPType>
302 //GridDimensions SharedBaseGrid<T, GPTransformer, Adder, GPType>::createSendBufferBounds(std::vector<int> relativeLocation) {
303 // Point<double> localOrigin = localBounds.origin();
304 // Point<double> localExtent = localBounds.extents();
305 //
338 //
339 // return GridDimensions();
340 //}
341 
342 
343 template<typename T, typename GPTransformer, typename Adder, typename GPType>
344 void SharedBaseGrid<T, GPTransformer, Adder, GPType>::balance() {
345  int r = comm->rank();
346  typename GridBaseType::LocationMapConstIter iterEnd = GridBaseType::locationsEnd();
347  for (typename GridBaseType::LocationMapConstIter iter = GridBaseType::locationsBegin(); iter != iterEnd; ++iter) {
348  AgentId id = iter->second->ptr->getId();
349  if(id.currentRank() == r){ // Local agents only
350  Point<GPType> loc = iter->second->point;
351  if(!localBounds.contains(loc)){ // If inside bounds, ignore
352  Neighbor* ngh = nghs->findNeighbor(loc.coords());
353  RepastProcess::instance()->moveAgent(id, ngh->rank());
354  }
355  }
356  }
357 }
358 
359 template<typename T, typename GPTransformer, typename Adder, typename GPType>
362 }
363 
364 template<typename T, typename GPTransformer, typename Adder, typename GPType>
365 bool SharedBaseGrid<T, GPTransformer, Adder, GPType>::moveTo(const AgentId& id, const std::vector<GPType>& newLocation) {
366  return GridBaseType::moveTo(id, newLocation);
367 }
368 
369 template<typename T, typename GPTransformer, typename Adder, typename GPType>
371  GridBaseType::removeAgent(agent);
372 }
373 
374 
375 // Beta
376 
377 template<typename T, typename GPTransformer, typename Adder, typename GPType>
378 void SharedBaseGrid<T, GPTransformer, Adder, GPType>::getAgentsToPush(std::set<AgentId>& agentsToTest, std::map<int, std::set<AgentId> >& agentsToPush){
379 
380  if(_buffer == 0) return; // A buffer zone of zero means that no agents will be pushed.
381 
382  int numDims = localBounds.dimensionCount();
383  RelativeLocation relLocOrig(numDims);
384 
385  RelativeLocation relLoc = cartTopology->trim(comm->rank(), relLocOrig);
386 
387  // First, create a zone around the center of this process, inside all of
388  // of the buffer zones
389  std::vector<double> unbufferedOrigin;
390  std::vector<double> unbufferedExtents;
391 
392  for(int i = 0; i < numDims; i++){
393  bool hasLeft = relLoc.getMinimumAt(i) < 0;
394  bool hasRight = relLoc.getMaximumAt(i) > 0;
395  unbufferedOrigin.push_back(localBounds.origin(i) + (hasLeft ? _buffer : 0));
396  unbufferedExtents.push_back(localBounds.extents(i) - (hasLeft ? _buffer : 0) - (hasRight ? _buffer : 0));
397  }
398 
399  Point<double> ubO(unbufferedOrigin);
400  Point<double> ubE(unbufferedExtents);
401  GridDimensions unbuffered(ubO, ubE);
402 
403  // And create grid boundaries for all the buffer zones
404  int numOutgoing = relLoc.getMaxIndex() + 1;
405 
406  GridDimensions** outgoing = new GridDimensions*[numOutgoing];
407  int* outRanks = new int[numOutgoing];
408 
409  do{
410  std::vector<double> bufferOrigin;
411  std::vector<double> bufferExtents;
412 
413  bool isEgo = true;
414  for(int i = 0; i < numDims; i++){
415  int rel = relLoc[i];
416 
417  if(rel == 0){
418  bufferOrigin.push_back(localBounds.origin(i));
419  bufferExtents.push_back(localBounds.extents(i));
420  }
421  else{
422  if(rel < 0){
423  bufferOrigin.push_back(localBounds.origin(i));
424  }
425  else{
426  bufferOrigin.push_back(localBounds.origin(i) + localBounds.extents(i) - _buffer);
427  }
428  bufferExtents.push_back(_buffer);
429  isEgo = false;
430  }
431  }
432 
433  // Should not add self!
434  int index = relLoc.getIndex();
435  if(!isEgo){
436  outgoing[index] = new GridDimensions(Point<double>(bufferOrigin), Point<double> (bufferExtents));
437  outRanks[index] =nghs->getNeighborByIndex(index)->rank();
438  }
439  else{
440  outgoing[index] = 0;
441  outRanks[index] = 0;
442  }
443 
444  }while(relLoc.increment());
445 
446 
447  // Local agents that are in other processes' 'buffer zones' must be exported to those other processes.
448  int r = comm->rank();
449  std::set<AgentId>::iterator idIter = agentsToTest.begin();
450  while(idIter != agentsToTest.end()){
451  AgentId id = *idIter;
452  bool found = false;
453  if(id.currentRank() == r){ // Local agents only
454  std::vector<GPType> locationVector;
455  GridBaseType::getLocation(id, locationVector);
456  Point<GPType> loc(locationVector);
457  if(!unbuffered.contains(loc)){
458  for(int i = 0; i < numOutgoing; i++){
459  if ((outgoing[i] != NULL) && (outgoing[i]->contains(loc))) {
460  agentsToPush[outRanks[i]].insert(id);
461  found = true;
462  }
463  }
464  }
465  }
466  if(found){
467  std::set<AgentId>::iterator tmp = idIter;
468  idIter++;
469  agentsToTest.erase(tmp);
470  }
471  else{
472  idIter++;
473  }
474  }
475 // if(NW_set.size() > 0) agentsToPush[NW_rank].insert(NW_set.begin(), NW_set.end());
476  delete[] outgoing;
477  delete[] outRanks;
478 }
479 
480 template<typename T, typename GPTransformer, typename Adder, typename GPType>
483  synchMoveTo(spip->id, spip->data);
484 }
485 
486 }
487 
488 #endif /* SHAREDBASEGRID_H_ */
repast::Neighbors
Provides lookup of grid topology process neighbors given a point in the pan process grid.
Definition: SharedBaseGrid.h:87
repast::SharedBaseGrid::getAgentsToPush
virtual void getAgentsToPush(std::set< AgentId > &agentsToTest, std::map< int, std::set< AgentId > > &agentsToPush)
Given a set of agents, gets the agents that this projection implementation must 'push' to other proce...
Definition: SharedBaseGrid.h:378
repast::CartesianTopology
Definition: CartesianTopology.h:55
repast::SharedBaseGrid
Grid / Space implementation specialized for the distributed context.
Definition: SharedBaseGrid.h:168
repast::Context
Collection of agents of type T with set semantics.
Definition: Context.h:82
repast::ProjectionInfoPacket
Serializable packet that can contain projection information regardless of the type of projection (net...
Definition: Projection.h:64
repast::RelativeLocation::getMaxIndex
int getMaxIndex()
Gets the maximum index value; this will be one less than the total number of values.
Definition: RelativeLocation.cpp:185
repast::Neighbors::neighbor
Neighbor * neighbor(RelativeLocation) const
Gets the neighbor at the specified location.
Definition: SharedBaseGrid.cpp:64
repast::AgentId
Agent identity information.
Definition: AgentId.h:60
repast::SharedBaseGrid::getAgentStatusExchangePartners
virtual void getAgentStatusExchangePartners(std::set< int > &psToSendTo, std::set< int > &psToReceiveFrom)
Gets the set of processes with which this Projection exchanges agent status info- that is,...
Definition: SharedBaseGrid.h:250
repast::RelativeLocation::getCurrentValue
vector< int > getCurrentValue()
Gets the array of current values.
Definition: RelativeLocation.cpp:173
repast::BaseGrid< T, MultipleOccupancy< T, GPType >, GPTransformer, Adder, GPType >::moveTo
virtual bool moveTo(const T *agent, const std::vector< GPType > &newLocation)
Moves the specified agent to the specified location.
Definition: BaseGrid.h:346
repast::RelativeLocation::trim
RelativeLocation trim(RelativeLocation toBeTrimmed)
Returns a new RelativeLocation object based on the one passed, but trimmed so that it fits within the...
Definition: RelativeLocation.cpp:232
repast::SharedBaseGrid::bounds
virtual const GridDimensions bounds() const
Gets the global bounds for this grid.
Definition: SharedBaseGrid.h:214
repast::RelativeLocation::getMaximumAt
int getMaximumAt(int index)
Gets the upper bound in the specified dimension.
Definition: RelativeLocation.cpp:228
repast::Neighbor
Contains the rank and boundaries of a semantically adjacent process (that is, a process that manages ...
Definition: SharedBaseGrid.h:68
repast::SharedBaseGrid::moveTo
virtual bool moveTo(const AgentId &id, const std::vector< GPType > &newLocation)
Moves the specified agent to the specified location.
Definition: SharedBaseGrid.h:365
repast::RelativeLocation::getIndex
int getIndex(vector< int > value)
Gets the index value associated with the specified position.
Definition: RelativeLocation.cpp:197
repast::GridDimensions
Basic structure for specifying grid dimenions.
Definition: GridDimensions.h:58
repast::SharedBaseGrid::dimensions
virtual const GridDimensions dimensions() const
Gets the local bounds of this SharedGrid.
Definition: SharedBaseGrid.h:226
repast::Neighbors::addNeighbor
void addNeighbor(Neighbor *ngh, RelativeLocation relLoc)
Adds a neighbor at the specified location.
Definition: SharedBaseGrid.cpp:60
repast::SpecializedProjectionInfoPacket
Serializable packet that can contain projection information of a specific kind using the template par...
Definition: Projection.h:90
repast::BaseGrid
Base grid implementation, implementing elements common to both Grids and ContinuousSpaces.
Definition: BaseGrid.h:104
repast::Point::coords
const std::vector< T > & coords() const
Gets the coordinates of this point as a vector.
Definition: Point.h:229
repast::SharedBaseGrid::getInfoExchangePartners
virtual void getInfoExchangePartners(std::set< int > &psToSendTo, std::set< int > &psToReceiveFrom)
Gets the set of processes with which this Projection exchanges projection info.
Definition: SharedBaseGrid.h:245
repast::Point< GPType >
repast::RelativeLocation::getMinimumAt
int getMinimumAt(int index)
Gets the lower bound in the specified dimension.
Definition: RelativeLocation.cpp:224
repast::Projection::name
const std::string name() const
Gets the name of this projection.
Definition: Projection.h:164
repast::RelativeLocation
A RelativeLocation is a vector of integers that express a relative location in a coordinate system; t...
Definition: RelativeLocation.h:103
repast::SharedBaseGrid::SharedBaseGrid
SharedBaseGrid(std::string name, GridDimensions gridDims, std::vector< int > processDims, int buffer, boost::mpi::communicator *communicator)
Creates a SharedGrid with the specified name.
Definition: SharedBaseGrid.h:260
repast::Neighbors::findNeighbor
Neighbor * findNeighbor(const std::vector< int > &pt)
Finds the neighbor that contains the specified point.
Definition: SharedBaseGrid.cpp:68