RepastHPC  2.3.1
RepastProcess.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  * RepastProcess.h
36  *
37  * Created on: Jan 5, 2009
38  * Author: nick
39  */
40 
41 #ifndef REPASTPROCESS_H_
42 #define REPASTPROCESS_H_
43 
44 #include <vector>
45 #include <map>
46 #include <set>
47 #include <list>
48 #include <iostream>
49 
50 #include <boost/mpi/communicator.hpp>
51 #include <boost/lexical_cast.hpp>
52 #include <boost/unordered_set.hpp>
53 #include <boost/noncopyable.hpp>
54 #include <boost/ptr_container/ptr_list.hpp>
55 #include <boost/serialization/utility.hpp>
56 #include <boost/serialization/map.hpp>
57 
58 #include "Schedule.h"
59 #include "AgentId.h"
60 #include "SharedContext.h"
61 #include "AgentRequest.h"
62 #include "AgentStatus.h"
63 #include "mpi_constants.h"
64 #include "SRManager.h"
65 #include "RepastErrors.h"
66 #include "AgentImporterExporter.h"
67 #include "CartesianTopology.h"
68 
69 // these are for the timings logging
70 #include "Utilities.h"
71 #include "logger.h"
72 
84 namespace repast {
85 
98 template<typename Content>
100 
101  friend class boost::serialization::access;
102 
103 public:
104  std::vector<Content>* agentContentPtr;
105  std::map<std::string, std::vector<ProjectionInfoPacket*> >* projectionInfoPtr;
106 
107  Request_Packet() :
108  agentContentPtr(0), projectionInfoPtr(0) {
109  }
110 
111  Request_Packet(std::vector<Content>* agentContent,
112  std::map<std::string, std::vector<ProjectionInfoPacket*> >* projectionInfo) :
113  agentContentPtr(agentContent), projectionInfoPtr(projectionInfo) {
114  }
115 
116  ~Request_Packet() {
117  delete agentContentPtr;
118  agentContentPtr = 0;
119 
120  if (projectionInfoPtr != 0) {
121  for (std::map<std::string, std::vector<ProjectionInfoPacket*> >::iterator
122  iter = projectionInfoPtr->begin(), iterEnd =
123  projectionInfoPtr->end(); iter != iterEnd; ++iter) {
124  for (std::vector<ProjectionInfoPacket*>::iterator PIPIter =
125  iter->second.begin(), PIPIterEnd = iter->second.end();
126  PIPIter != PIPIterEnd; ++PIPIter) {
127  delete *PIPIter;
128  }
129  }
130  }
131  delete projectionInfoPtr;
132  projectionInfoPtr = 0;
133 
134  }
135 
136  template<class Archive>
137  void serialize(Archive& ar, const unsigned int version) {
138  ar & agentContentPtr;
139  ar & projectionInfoPtr;
140  }
141 
142 };
143 
154 template<typename Content>
156 
157  friend class boost::serialization::access;
158 
159 public:
160  std::vector<Content>* agentContentPtr;
161  std::map<std::string, std::vector<ProjectionInfoPacket*> >* projectionInfoPtr;
162  std::set<AgentId>* secondaryIdsPtr;
163  AgentExporterInfo* exporterInfoPtr;
164 
166  agentContentPtr(0), projectionInfoPtr(0), secondaryIdsPtr(0), exporterInfoPtr(
167  0) {
168  }
169 
170  SyncStatus_Packet(std::vector<Content>* agentContent,
171  std::map<std::string, std::vector<ProjectionInfoPacket*> >* projectionInfo,
172  std::set<AgentId>* secondaryIds, AgentExporterInfo* exporterInfo) :
173  agentContentPtr(agentContent), projectionInfoPtr(projectionInfo), secondaryIdsPtr(
174  secondaryIds), exporterInfoPtr(exporterInfo) {
175  }
176 
177  ~SyncStatus_Packet() {
178  delete agentContentPtr;
179  agentContentPtr = 0;
180 
181  if (projectionInfoPtr != 0) {
182  for (std::map<std::string, std::vector<ProjectionInfoPacket*> >::iterator
183  iter = projectionInfoPtr->begin(), iterEnd =
184  projectionInfoPtr->end(); iter != iterEnd; ++iter) {
185  for (std::vector<ProjectionInfoPacket*>::iterator PIPIter =
186  iter->second.begin(), PIPIterEnd = iter->second.end();
187  PIPIter != PIPIterEnd; ++PIPIter) {
188  delete *PIPIter;
189  }
190  }
191  }
192  delete projectionInfoPtr;
193  projectionInfoPtr = 0;
194 
195  delete secondaryIdsPtr;
196  secondaryIdsPtr = 0;
197 
198  }
199 
212  delete exporterInfoPtr;
213  exporterInfoPtr = 0;
214  return this;
215  }
216 
217  template<class Archive>
218  void serialize(Archive& ar, const unsigned int version) {
219  ar & agentContentPtr;
220  ar & projectionInfoPtr;
221  ar & secondaryIdsPtr;
222  ar & exporterInfoPtr;
223  }
224 
225 };
226 
232 class RepastProcess: public boost::noncopyable {
233 
234 public:
235  enum EXCHANGE_PATTERN {
236  POLL, USE_CURRENT, USE_LAST_OR_POLL, USE_LAST_OR_USE_CURRENT
237  };
238 
239 private:
240 
241  typedef boost::unordered_set<AgentId, HashId> MovedAgentSetType;
242 
243  static RepastProcess* _instance;
244 
245  boost::mpi::communicator* world;
246  ScheduleRunner* runner;
247  int rank_;
248  int worldSize_;
249 
250 #ifndef SHARE_AGENTS_BY_SET
251  AbstractImporterExporter* importer_exporter;
252 #else
253  ImporterExporter_BY_SET* importer_exporter;
254 #endif
255 
256  // key is process and value are requests from importers
257  // that the key-process should now export to. Used when
258  // an agent moves from this process and we need
259  // to tell the process-it-moves-to where it should
260  // export agents to
261  std::map<int, std::vector<AgentRequest>*> importers;
262  MovedAgentSetType movedAgents;
263 
264  // called by request agents function to initiate the request
265 #ifndef SHARE_AGENTS_BY_SET
266  void initiateAgentRequest(AgentRequest& requests);
267 #else
268  void initiateAgentRequest(AgentRequest& requests, std::string setName =
269  DEFAULT_AGENT_REQUEST_SET, AGENT_IMPORTER_EXPORTER_TYPE setType =
270  DEFAULT_ENUM_SYMBOL);
271 #endif
272 
273  std::vector<int>* procsToSendProjInfoTo;
274  std::vector<int>* procsToRecvProjInfoFrom;
275 
276  std::vector<int>* procsToSendAgentStatusInfoTo;
277  std::vector<int>* procsToRecvAgentStatusInfoFrom;
278 
279  std::vector<CartesianTopology*> cartesianTopologies;
280 
281 protected:
282  RepastProcess(boost::mpi::communicator* comm = 0);
283 
284  void saveProjInfoSRProcs(std::vector<int>& sends, std::vector<int>& recvs) {
285  if (procsToSendProjInfoTo == NULL) {
286  procsToSendProjInfoTo = new std::vector<int>;
287  procsToRecvProjInfoFrom = new std::vector<int>;
288  } else {
289  procsToSendProjInfoTo->clear();
290  procsToRecvProjInfoFrom->clear();
291  }
292  procsToSendProjInfoTo->assign(sends.begin(), sends.end());
293  procsToRecvProjInfoFrom->assign(recvs.begin(), recvs.end());
294  }
295 
296  void saveAgentStatusInfoSRProcs(std::vector<int>& sends,
297  std::vector<int>& recvs) {
298  if (procsToSendAgentStatusInfoTo == NULL) {
299  procsToSendAgentStatusInfoTo = new std::vector<int>;
300  procsToRecvAgentStatusInfoFrom = new std::vector<int>;
301  } else {
302  procsToSendAgentStatusInfoTo->clear();
303  procsToRecvAgentStatusInfoFrom->clear();
304  }
305  procsToSendAgentStatusInfoTo->assign(sends.begin(), sends.end());
306  procsToRecvAgentStatusInfoFrom->assign(recvs.begin(), recvs.end());
307  }
308 
309 public:
310 
319  static RepastProcess* init(std::string propsfile,
320  boost::mpi::communicator* comm = 0, int maxConfigFileSize =
321  MAX_CONFIG_FILE_SIZE);
322 
328  static RepastProcess* instance();
329 
330  static boost::mpi::communicator* communicator();
331 
332  virtual ~RepastProcess();
333 
340  void agentRemoved(const AgentId& id);
341 
351  void moveAgent(const AgentId& id, int process);
352 
361  void addExportedAgent(int importingProcess, AgentId id);
362 
371  void addImportedAgent(AgentId id);
372 
378  int rank() const {
379  return rank_;
380  }
381 
385  int worldSize() const {
386  return worldSize_;
387  }
388 
393  void done();
394 
402  return *runner;
403  }
404 
405  boost::mpi::communicator* getCommunicator() {
406  return world;
407  }
408 
409 
410  CartesianTopology* getCartesianTopology(std::vector<int> processesPerDim, bool spaceIsPeriodic);
411 
412 
413 #ifdef SHARE_AGENTS_BY_SET
414  void dropImporterExporterSet(std::string setName) {
415  importer_exporter->dropSet(setName);
416  }
417 #endif
418 
419  std::string ImporterExporterVersion() {
420  return "" + importer_exporter->version();
421  }
422 
423  std::string ImporterExporterReport() {
424  return importer_exporter->getReport();
425  }
426 
427  // Repast Process should handle four specific tasks for controlling parallelization:
428  //
429  // 1. Requesting agents that are to be shared
430  // 2. Synchronizing the state values for shared agents
431  // 3. Synchronizing the Projection info for all shared agents
432  // 4. Synchronizing agent status values, including removing agents and moving them across processes
433  //
434  // At the end of all four of these operations, the simulation should be in a valid state
435  // (Though not necessarily a 'current' state: synchronizing state values does NOT update Projection
436  // information. This is a performance consideration: ideally we would always have the simulation in
437  // a 100% current state, but because the simulation is being parallelized, a choice must always be made
438  // about what information is updated.)
439 
443  template<typename T, typename Content, typename Provider, typename Updater,
444  typename AgentCreator>
445  void requestAgents(SharedContext<T>& context, AgentRequest& request,
446  Provider& provider, Updater& updater, AgentCreator& creator
447 #ifdef SHARE_AGENTS_BY_SET
448  , std::string setName = DEFAULT_AGENT_REQUEST_SET,
449  AGENT_IMPORTER_EXPORTER_TYPE setType = DEFAULT_ENUM_SYMBOL
450 #endif
451  );
452 
457  template<typename Content, typename Provider, typename Updater>
458  void synchronizeAgentStates(Provider& provider, Updater& updater
459 #ifdef SHARE_AGENTS_BY_SET
460  , std::string setName = REQUEST_AGENTS_ALL
461 #endif
462  );
463 
467  template<typename T, typename Content, typename Provider, typename Updater,
468  typename AgentCreator>
469  void synchronizeProjectionInfo(SharedContext<T>& context,
470  Provider& provider, Updater& updater, AgentCreator& creator,
471  EXCHANGE_PATTERN exchangePattern = POLL
472 #ifdef SHARE_AGENTS_BY_SET
473  , bool declareNoAgentsKeptOnAnyProcess = false
474 #endif
475  );
476 
493  template<typename T, typename Content, typename Provider,
494  typename AgentCreator, typename Updater>
495  void synchronizeAgentStatus(SharedContext<T>& context, Provider& provider,
496  Updater& updater, AgentCreator& creator,
497  EXCHANGE_PATTERN exchangePattern = POLL);
498 
499 };
500 
522 template<typename T, typename Content, typename Provider, typename Updater,
523  typename AgentCreator>
525  AgentRequest& request, Provider& provider, Updater& updater,
526  AgentCreator& creator
527 #ifdef SHARE_AGENTS_BY_SET
528  , std::string setName, AGENT_IMPORTER_EXPORTER_TYPE setType
529 #endif
530  ) {
531 
532  // Initiate the new requests
533 #ifdef SHARE_AGENTS_BY_SET
534  initiateAgentRequest(request, setName, setType);
535 #else
536  initiateAgentRequest(request);
537 #endif
538 
539  // Establish which processes are sending to/receiving from this one
540 #ifdef SHARE_AGENTS_BY_SET
541  const std::set<int>& exporters = importer_exporter->getExportingProcesses(
542  setName);
543  const std::map<int, AgentRequest>& agentsToExport =
544  importer_exporter->getAgentsToExport(setName);
545 #else
546  const std::set<int>& exporters = importer_exporter->getExportingProcesses();
547  const std::map<int, AgentRequest>& agentsToExport = importer_exporter->getAgentsToExport();
548 #endif
549 
550  // Construct MPI requests (Receives and Sends)
551  std::vector<boost::mpi::request> requests; // MPI Requests (receives and sends)
552 
553  // Construct Receives
554  std::vector<Request_Packet<Content>*> toReceive;
555 
556  for (std::set<int>::const_iterator iter = exporters.begin();
557  iter != exporters.end(); ++iter) {
558  Request_Packet<Content>* packet;
559  toReceive.push_back(packet = new Request_Packet<Content>());
560  requests.push_back(world->irecv(*iter, 23, *packet));
561  }
562 
563  // Construct Sends
564  boost::ptr_list<Request_Packet<Content> >* toSend = new boost::ptr_list<
566 
567  for (std::map<int, AgentRequest>::const_iterator iter =
568  agentsToExport.begin(); iter != agentsToExport.end(); ++iter) {
569 
570  // Agent Content
571  std::vector<Content>* content = new std::vector<Content>;
572  provider.provideContent(iter->second, *content);
573 
574  // Projection Info
575  std::map<std::string, std::vector<ProjectionInfoPacket*> >* projInfo =
576  new std::map<std::string,
577  std::vector<repast::ProjectionInfoPacket*> >;
578  context.getProjectionInfo(iter->second, *projInfo);
579 
580  Request_Packet<Content>* packet;
581  toSend->push_back(
582  packet = new Request_Packet<Content>(content, projInfo));
583  requests.push_back(world->isend(iter->first, 23, *packet));
584  }
585 
586  // Wait until all sends/receives complete
587  boost::mpi::wait_all(requests.begin(), requests.end());
588 
589  // Clear sent data
590  delete toSend;
591 
592  // Process (and delete) received data
593  for (typename std::vector<Request_Packet<Content>*>::iterator iter =
594  toReceive.begin(), iterEnd = toReceive.end(); iter != iterEnd;
595  ++iter) {
596  std::vector<Content>* content = (*iter)->agentContentPtr;
597  for (typename std::vector<Content>::const_iterator contentIter =
598  content->begin(), contentIterEnd = content->end();
599  contentIter != contentIterEnd; ++contentIter) {
600  T* out = creator.createAgent(*contentIter);
601  T* inContext = context.addAgent(out);
602  if (inContext != out) { // This agent was already on this process
603  updater.updateAgent(*contentIter);
604  delete out;
605  }
606  }
607  context.setProjectionInfo(*((*iter)->projectionInfoPtr));
608  delete *iter;
609  }
610 
611 }
612 
613 template<typename Content, typename Provider, typename Updater>
614 void RepastProcess::synchronizeAgentStates(Provider& provider, Updater& updater
615 #ifdef SHARE_AGENTS_BY_SET
616  , std::string setName
617 #endif
618  ) {
619 
620  // Establish which processes are sending/receiving from this one
621 #ifdef SHARE_AGENTS_BY_SET
622  const std::set<int>& processesToReceiveFrom =
623  importer_exporter->getExportingProcesses(setName);
624  const std::map<int, AgentRequest>& agentsToExport =
625  importer_exporter->getAgentsToExport(setName);
626 #else
627  const std::set<int>& processesToReceiveFrom = importer_exporter->getExportingProcesses();
628  const std::map<int, AgentRequest>& agentsToExport = importer_exporter->getAgentsToExport();
629 #endif
630 
631  // Construct MPI Requests (sends and receives)
632  std::vector<boost::mpi::request> requests;
633 
634  // Construct Receives
635  std::vector<std::vector<Content>*> received;
636  for (std::set<int>::const_iterator iter = processesToReceiveFrom.begin(),
637  iterEnd = processesToReceiveFrom.end(); iter != iterEnd; ++iter) {
638  std::vector<Content>* content = new std::vector<Content>();
639  requests.push_back(world->irecv(*iter, 47, *content));
640  received.push_back(content);
641  }
642 
643  // Construct Sends
644  boost::ptr_list<std::vector<Content> >* toSend = new boost::ptr_list<
645  std::vector<Content> >;
646  std::vector<Content>* content;
647 
648  for (std::map<int, AgentRequest>::const_iterator iter =
649  agentsToExport.begin(), iterEnd = agentsToExport.end();
650  iter != iterEnd; ++iter) {
651  toSend->push_back(content = new std::vector<Content>);
652  provider.provideContent(iter->second, *content);
653  requests.push_back(world->isend(iter->first, 47, *content));
654  }
655 
656  // Wait until all sends and receives are complete
657  boost::mpi::wait_all(requests.begin(), requests.end());
658 
659  // Clear sent data
660  delete toSend;
661 
662  // Process (and clear) received data
663  for (typename std::vector<std::vector<Content>*>::iterator iter =
664  received.begin(), iterEnd = received.end(); iter != iterEnd;
665  ++iter) {
666  content = *iter;
667  for (typename std::vector<Content>::const_iterator agentIter =
668  content->begin(), agentIterEnd = content->end();
669  agentIter != agentIterEnd; ++agentIter) {
670  updater.updateAgent(*agentIter);
671  }
672  delete content;
673  }
674 
675 }
676 
677 template<typename T, typename Content, typename Provider, typename Updater,
678  typename AgentCreator>
680  Provider& provider, Updater& updater, AgentCreator& creator,
681  EXCHANGE_PATTERN exchangePattern
682 #ifdef SHARE_AGENTS_BY_SET
683  , bool declareNoAgentsKeptOnAnyProcess
684 #endif
685  ) {
686 
687  // Generate sets of agents to delete or not delete
688  std::set<AgentId> agentsToKeep;
689 
690  bool agentsMayBeKept =
691 #ifdef SHARE_AGENTS_BY_SET
692  context.keepsAgentsOnSyncProj() || !declareNoAgentsKeptOnAnyProcess;
693 #else
694  context.keepsAgentsOnSyncProj();
695 #endif
696 
697  // If 'By Set': Construct 'Keep list' from all non-default I/E requests (agents being imported)
698 #ifdef SHARE_AGENTS_BY_SET
699  if (declareNoAgentsKeptOnAnyProcess) {
700  importer_exporter->clear();
701  } else {
702  importer_exporter->getSetOfAgentsBeingImported(agentsToKeep,
703  DEFAULT_AGENT_REQUEST_SET);
704  importer_exporter->clear(DEFAULT_AGENT_REQUEST_SET);
705  }
706 #else
707  importer_exporter->clear();
708 #endif
709 
710  // Determine all agents that the context doesn't need and are not on 'Keep' list, adding those that it needs to the 'Keep' list
711  std::set<AgentId> agentsToDrop;
712  context.getNonlocalAgentsToDrop(agentsToKeep, agentsToDrop);
713 
714  // Drop all of the agents that can be dropped
715  std::set<AgentId>::iterator dropIter = agentsToDrop.begin(), dropIterEnd =
716  agentsToDrop.end();
717  while (dropIter != dropIterEnd) {
718  context.removeAgent(*dropIter);
719  agentRemoved(*dropIter);
720  dropIter++;
721  }
722 
723  // And drop all unneeded projection information, even for the agents being kept
724  context.cleanProjectionInfo(agentsToKeep);
725 
726  // Initiate Agent Request (so that I/E will have agents needed by other processes)
727  if (agentsMayBeKept) {
728  AgentRequest req;
729  for (std::set<AgentId>::iterator iter = agentsToKeep.begin(), iterEnd =
730  agentsToKeep.end(); iter != iterEnd; ++iter) {
731  req.addRequest(*iter); // TO DO: Better optimized constructor
732  }
733  initiateAgentRequest(req); // Note: will use default I/E
734  }
735 
736  // Determine which agents will be 'pushed' to other processes
737  std::map<int, std::set<AgentId> > agentsToPush;
738  context.getAgentsToPushToOtherProcesses(agentsToPush);
739 
740  // Add these to I/E as exports
741  std::vector<AgentRequest> requests;
742  for (std::map<int, std::set<AgentId> >::iterator iter =
743  agentsToPush.begin(), iterEnd = agentsToPush.end(); iter != iterEnd;
744  ++iter) {
745  AgentRequest req(iter->first);
746  for (std::set<AgentId>::iterator i = iter->second.begin(), iEnd =
747  iter->second.end(); i != iEnd; i++)
748  req.addRequest(*i);
749  requests.push_back(req);
750  }
751 
752 #ifdef SHARE_AGENTS_BY_SET
753  importer_exporter->registerIncomingRequests(requests,
754  DEFAULT_AGENT_REQUEST_SET);
755 #else
756  importer_exporter->registerIncomingRequests(requests);
757 #endif
758 
759  // Exchange agent & projection information
760  // Establish which processes are sending to/receiving from this one
761 #ifdef SHARE_AGENTS_BY_SET
762  const std::map<int, AgentRequest>& tmpAgentsToExport =
763  importer_exporter->getAgentsToExport(DEFAULT_AGENT_REQUEST_SET);
764 #else
765  const std::map<int, AgentRequest>& tmpAgentsToExport = importer_exporter->getAgentsToExport();
766 #endif
767 
768  std::map<int, AgentRequest> agentsToExport = tmpAgentsToExport; // Copy?
769 
770  std::vector<int> psToSendTo;
771  std::vector<int> psToReceiveFrom;
772  if (exchangePattern == USE_CURRENT
773  || ((exchangePattern == USE_LAST_OR_USE_CURRENT)
774  && (procsToSendProjInfoTo == NULL))) {
775  std::set<int> sends, recvs;
776  context.getProjInfoExchangePartners(sends, recvs);
777  psToSendTo.assign(sends.begin(), sends.end());
778  psToReceiveFrom.assign(recvs.begin(), recvs.end());
779  // Add dummy requests to create empty sends
780  for (std::vector<int>::iterator iter = psToSendTo.begin(), iterEnd =
781  psToSendTo.end(); iter != iterEnd; ++iter) {
782  int dest = *iter;
783  if (agentsToExport.find(dest) == agentsToExport.end()) {
784  AgentRequest dummy(rank_, dest);
785  agentsToExport[dest] = dummy;
786  }
787  }
788  } else if (exchangePattern == POLL
789  || ((exchangePattern == USE_LAST_OR_POLL)
790  && (procsToSendProjInfoTo == NULL))) {
791  for (std::map<int, AgentRequest>::const_iterator iter =
792  agentsToExport.begin(), iterEnd = agentsToExport.end();
793  iter != iterEnd; ++iter) {
794  psToSendTo.push_back(iter->first);
795  }
796  SRManager manager(world);
797  manager.retrieveSources(psToSendTo, psToReceiveFrom,
798  AGENT_MOVED_SENDERS);
799  } else {
800  psToSendTo.assign(procsToSendProjInfoTo->begin(),
801  procsToSendProjInfoTo->end());
802  psToReceiveFrom.assign(procsToRecvProjInfoFrom->begin(),
803  procsToRecvProjInfoFrom->end());
804 
805  // Add dummy requests to create empty sends
806  for (std::vector<int>::iterator iter = psToSendTo.begin(), iterEnd =
807  psToSendTo.end(); iter != iterEnd; ++iter) {
808  int dest = *iter;
809  if (agentsToExport.find(dest) == agentsToExport.end()) {
810  AgentRequest dummy(rank_, dest);
811  agentsToExport[dest] = dummy;
812  }
813  }
814  }
815 
816  saveProjInfoSRProcs(psToSendTo, psToReceiveFrom);
817 
818  // Construct MPI requests (Receives and Sends)
819  std::vector<boost::mpi::request> MPIRequests; // MPI Requests (receives and sends)
820 
821  // Construct Receives
822  std::map<int, Request_Packet<Content>*> toReceive;
823 
824  for (std::vector<int>::iterator iter = psToReceiveFrom.begin(), iterEnd =
825  psToReceiveFrom.end(); iter != iterEnd; ++iter) {
826  Request_Packet<Content>* packet;
827  toReceive[*iter] = (packet = new Request_Packet<Content>());
828  MPIRequests.push_back(world->irecv(*iter, 23, *packet));
829  }
830 
831  // Construct Sends
832  boost::ptr_list<Request_Packet<Content> >* toSend = new boost::ptr_list<
834 
835  for (std::map<int, AgentRequest>::const_iterator iter =
836  agentsToExport.begin(), iterEnd = agentsToExport.end();
837  iter != iterEnd; ++iter) {
838  int dest = iter->first;
839  const AgentRequest& rq = iter->second;
840 
841  // Agent Content
842  std::vector<Content>* contentVector = new std::vector<Content>;
843  provider.provideContent(rq, *contentVector);
844 
845  // Projection Info
846  std::map<std::string, std::vector<ProjectionInfoPacket*> >* projInfo =
847  new std::map<std::string,
848  std::vector<repast::ProjectionInfoPacket*> >;
849  context.getProjectionInfo(rq, *projInfo, true, 0, dest); // Will collect the edges but not the secondary IDs
850 
851  Request_Packet<Content>* packet;
852  toSend->push_back(
853  packet = new Request_Packet<Content>(contentVector, projInfo));
854  MPIRequests.push_back(world->isend(dest, 23, *packet));
855  }
856 
857  // Wait until all sends/receives complete
858  boost::mpi::wait_all(MPIRequests.begin(), MPIRequests.end());
859 
860  // Clear sent data
861  delete toSend;
862 
863  // Process received data (and clear)
864  for (typename std::map<int, Request_Packet<Content>*>::iterator iter =
865  toReceive.begin(), iterEnd = toReceive.end(); iter != iterEnd;
866  ++iter) {
867  std::vector<Content>* contentVector = iter->second->agentContentPtr;
868  AgentRequest requestToRegister(iter->first);
869  for (typename std::vector<Content>::const_iterator contentIter =
870  contentVector->begin(), contentIterEnd = contentVector->end();
871  contentIter != contentIterEnd; ++contentIter) {
872  T* newAgent = creator.createAgent(*contentIter);
873  T* agentInContext = context.addAgent(newAgent);
874  if (agentInContext != newAgent) { // This agent was already on this process
875  updater.updateAgent(*contentIter);
876  delete newAgent;
877  } else {
878  // Add the agent to the agent request that will be processed as if it were an OUTGOING request
879  requestToRegister.addRequest(agentInContext->getId());
880  }
881  }
882 
883  context.setProjectionInfo(*(iter->second->projectionInfoPtr));
884  delete iter->second;
885  // Register these as requests, so that the importer/exporter will know these agents will be sent
886  importer_exporter->registerOutgoingRequests(requestToRegister);
887  }
888 }
889 
890 template<typename T, typename Content, typename Provider, typename AgentCreator,
891  typename Updater>
893  Provider& provider, Updater& updater, AgentCreator& creator,
894  EXCHANGE_PATTERN exchangePattern) {
895 
896  // Step 1: Exchange information about agents whose status will be updated.
897  //
898  // Status Updates have been added to the importer_exporter and can now be exchanged
899  // across processes. All processes will now know that an agent that has previously
900  // been managed by process A will either be eliminated from the simulation or
901  // moved to process B.
902  std::vector<std::vector<AgentStatus>*> statusUpdates;
903  importer_exporter->exchangeAgentStatusUpdates(*world, statusUpdates);
904 
905  for (size_t i = 0, n = statusUpdates.size(); i < n; i++) {
906  std::vector<AgentStatus>* vec = statusUpdates[i];
907  for (size_t j = 0, k = vec->size(); j < k; ++j) {
908  AgentStatus& status = (*vec)[j];
909  if (status.getStatus() == AgentStatus::REMOVED) {
910  importer_exporter->importedAgentIsRemoved(status.getOldId()); // Notify importer/exporter that this agent will not be imported anymore
911  context.importedAgentRemoved(status.getOldId()); // Remove from context; agent cannot exist on this process after removal from home process
912  } else if (status.getStatus() == AgentStatus::MOVED) {
913  if (rank_ != status.getNewId().currentRank()) {
914  // Notify importer that this agent will not be imported from the original
915  // process, but will instead be imported from its new home
916  importer_exporter->importedAgentIsMoved(status.getOldId(),
917  status.getNewId().currentRank());
918  } else {
919  // Notify importer that the agent will not be imported anymore because this is its home process now
920  importer_exporter->importedAgentIsNowLocal(
921  status.getOldId());
922  }
923  // If the agent's new rank is not this rank, then update it's current
924  // rank. We don't update all here so that we can properly update
925  // agent's who are currently ghosts on this rank, but now moved to here.
926  if (rank_ != status.getNewId().currentRank()) {
927  T* agent = context.getAgent(status.getOldId());
928  if (agent == (void*) 0)
929  throw Repast_Error_32<AgentId>(status.getOldId()); // Agent not found
930  agent->getId().currentRank(status.getNewId().currentRank());
931  }
932  }
933  }
934  delete vec;
935  }
936 
937  // Step 2: Send moving agents' information to new home processes
938  //
939  // First, some basic data structures must be created for some bookkeeping we will need later
940  std::set<AgentId> agentsToDrop; // A list of agents that will be removed from this process
941  std::set<int> psMovedTo; // A list of the processes that will be receiving moving agents
942  std::map<int, AgentRequest> agentRequests; // A map of these receiving processes and a list of the IDs of the agents going to them
943 
944  // This loop applies to all agents moving off of this process (from 'movedAgents'); it:
945  // Re-sets the 'current Process' ID values of the agents moving away from this process to their new values
946  // Adds the agents to the lists of agents to be removed from this process
947  // Creates the map of agent requests per receiving process and adds the agents to it
948  for (MovedAgentSetType::const_iterator iter = movedAgents.begin(), iterEnd =
949  movedAgents.end(); iter != iterEnd; ++iter) {
950  AgentId id = *iter;
951  context.getAgent(id)->getId().currentRank(id.currentRank());
952  agentsToDrop.insert(id);
953  int currentProc = id.currentRank();
954  if (psMovedTo.insert(currentProc).second) {
955  AgentRequest req = AgentRequest(currentProc, rank_);
956  req.addRequest(id);
957  agentRequests[currentProc] = req;
958  } else
959  agentRequests[currentProc].addRequest(id);
960  }
961  movedAgents.clear();
962 
963  // Next, coordinate the send/receive pairs (which processes send to which)
964  //
965  // Three different methods can be used:
966  // 1) POLL: Assume no knowledge of which processes will be sending to this one; do a full exchange
967  // where all processes inform all other processes of whether they need to send to them
968  // 2) USE_CURRENT: Assume that the context (and, by implication, all projections in the context)
969  // know which processes they need to send to and which they will receive from. For example, a grid
970  // projection will know its 8 neighbors; a graph projection _might_ know which processes own
971  // nodes to which it is connected
972  // 3) USE_LAST: Assume that the set of processes to which sends go and from which sends are received
973  // will be unchanged from the last time this loop was run; once established, just keep using
974  // the same set
975  //
976  // Variants 'USE_LAST_OR_POLL' and 'USE_LAST_OR_USE_CURRENT' allow for the case in which one method (either
977  // POLL or USE_CURRENT) is used for the initial pass through the loop and thereafter the sets are assumed
978  // unchanged.
979  std::vector<int> psToSendTo; // Convert set to vector
980  std::vector<int> psToReceiveFrom;
981 
982  if (exchangePattern == USE_CURRENT
983  || ((exchangePattern == USE_LAST_OR_USE_CURRENT)
984  && (procsToSendAgentStatusInfoTo == NULL))) {
985  std::set<int> sends, recvs;
986  context.getAgentStatusInfoExchangePartners(sends, recvs);
987  psToSendTo.assign(sends.begin(), sends.end());
988  psToReceiveFrom.assign(recvs.begin(), recvs.end());
989  // Add dummy requests to create empty sends
990  for (std::vector<int>::iterator iter = psToSendTo.begin(), iterEnd =
991  psToSendTo.end(); iter != iterEnd; ++iter) {
992  int dest = *iter;
993  if (agentRequests.find(dest) == agentRequests.end()) {
994  AgentRequest dummy(rank_, dest);
995  agentRequests[dest] = dummy;
996  }
997  }
998  } else if (exchangePattern == POLL
999  || ((exchangePattern == USE_LAST_OR_POLL)
1000  && (procsToSendAgentStatusInfoTo == NULL))) {
1001  for (std::map<int, AgentRequest>::const_iterator iter =
1002  agentRequests.begin(), iterEnd = agentRequests.end();
1003  iter != iterEnd; ++iter) {
1004  psToSendTo.push_back(iter->first);
1005  }
1006  SRManager manager(world);
1007  manager.retrieveSources(psToSendTo, psToReceiveFrom,
1008  AGENT_MOVED_SENDERS);
1009  } else {
1010  psToSendTo.assign(procsToSendAgentStatusInfoTo->begin(),
1011  procsToSendAgentStatusInfoTo->end());
1012  psToReceiveFrom.assign(procsToRecvAgentStatusInfoFrom->begin(),
1013  procsToRecvAgentStatusInfoFrom->end());
1014 
1015  // Add dummy requests to create empty sends
1016  for (std::vector<int>::iterator iter = psToSendTo.begin(), iterEnd =
1017  psToSendTo.end(); iter != iterEnd; ++iter) {
1018  int dest = *iter;
1019  if (agentRequests.find(dest) == agentRequests.end()) {
1020  AgentRequest dummy(rank_, dest);
1021  agentRequests[dest] = dummy;
1022  }
1023  }
1024  }
1025 
1026  saveAgentStatusInfoSRProcs(psToSendTo, psToReceiveFrom);
1027 
1028  // Determine if any projection in the context will need to send 'secondary' agent data:
1029  bool sendSecondaryData = context.sendsSecondaryDataOnStatusExchange();
1030 
1031  // Create MPI Sends and Receives
1032  std::vector<boost::mpi::request> requests;
1033 
1034  // STEP 5: Create the receives
1035  std::vector<SyncStatus_Packet<Content>*> packetsRecd;
1036 
1037  for (std::vector<int>::const_iterator iter = psToReceiveFrom.begin();
1038  iter != psToReceiveFrom.end(); ++iter) {
1039  int source = *iter;
1040  SyncStatus_Packet<Content>* packetToRecv =
1042  requests.push_back(
1043  world->irecv(source, AGENT_MOVED_AGENT, *packetToRecv));
1044  packetsRecd.push_back(packetToRecv);
1045  }
1046 
1047  // STEP 6: Assemble data to send
1048  boost::ptr_list<SyncStatus_Packet<Content> >* packetsToSend =
1049  new boost::ptr_list<SyncStatus_Packet<Content> >;
1050 
1051  for (std::map<int, repast::AgentRequest>::iterator iter =
1052  agentRequests.begin(); iter != agentRequests.end(); ++iter) {
1053  // Agent Content
1054  std::vector<Content>* content = new std::vector<Content>;
1055  provider.provideContent(iter->second, *content);
1056 
1057  // Projection Info and Secondary Ids
1058  std::map<std::string, std::vector<ProjectionInfoPacket*> >* projInfo =
1059  new std::map<std::string,
1060  std::vector<repast::ProjectionInfoPacket*> >;
1061  std::set<AgentId>* secondaryIds = (
1062  sendSecondaryData ? new std::set<AgentId> : 0);
1063  context.getProjectionInfo(iter->second, *projInfo, sendSecondaryData,
1064  secondaryIds);
1065 
1066  // Send the information for the secondary agents, too:
1067  if (secondaryIds != 0) { // use 'sendSecondaryData' instead? Should be equivalent...
1068  AgentRequest sidReq;
1069  for (std::set<AgentId>::iterator sidIter = secondaryIds->begin(),
1070  sidIterEnd = secondaryIds->end(); sidIter != sidIterEnd;
1071  ++sidIter)
1072  sidReq.addRequest(*sidIter);
1073  provider.provideContent(sidReq, *content); // Only their state data is needed, not any projection info
1074  }
1075 
1076  // Agent Exporter Info
1077  AgentExporterInfo* agentImporterInfoPtr =
1078  importer_exporter->getAgentExportInfo(iter->first);
1079 
1080  SyncStatus_Packet<Content>* packetToSend;
1081  packetsToSend->push_back(
1082  packetToSend = new SyncStatus_Packet<Content>(content, projInfo,
1083  secondaryIds, agentImporterInfoPtr));
1084 
1085  requests.push_back(
1086  world->isend(iter->first, AGENT_MOVED_AGENT, *packetToSend));
1087  }
1088  boost::mpi::wait_all(requests.begin(), requests.end());
1089  delete packetsToSend;
1090 
1091  importer_exporter->clearAgentExportInfo();
1092 
1093  // STEP 9: Remove the agents that are moving to other processes and are not needed here
1094  std::set<AgentId> agentsToKeep;
1095  context.getRequiredAgents(agentsToDrop, agentsToKeep,
1097 
1098  for (std::set<AgentId>::iterator idIter = agentsToDrop.begin(), idIterEnd =
1099  agentsToDrop.end(); idIter != idIterEnd; ++idIter)
1100  context.removeAgent(*idIter);
1101 
1102  // STEP 10: Insert the newly received agents that moved to this process and update exporters
1103  typename std::vector<SyncStatus_Packet<Content>*>::iterator packetIter;
1104  typename std::vector<SyncStatus_Packet<Content>*>::iterator packetIterEnd =
1105  packetsRecd.end();
1106  AgentRequest secondaryAgentsToRequest(rank_);
1107  for (packetIter = packetsRecd.begin(); packetIter != packetIterEnd;
1108  ++packetIter) {
1109  std::vector<Content>* content = (*packetIter)->agentContentPtr;
1110  typename std::vector<Content>::iterator contentIter = content->begin();
1111  while (contentIter != content->end()) {
1112  T* out = creator.createAgent(*contentIter);
1113  T* inContext = context.addAgent(out);
1114  if (inContext != out) { // Already contain the agent
1115  // If the agent is local on this rank, do nothing (the agent received must be a secondary agent)
1116  // If the agent is non-local on this rank
1117  if (inContext->getId().currentRank() != rank_) {
1118  // If the arriving agent has a current rank equal to this rank, this
1119  // is an incoming, newly arrived local agent that already existed on this
1120  // process as a secondary agent; it should be updated and its currentRank in
1121  // its ID set to the local rank
1122  if (out->getId().currentRank() == rank_) {
1123  updater.updateAgent(*contentIter);
1124  inContext->getId().currentRank(rank_);
1125  }
1126  // Otherwise, it's a secondary agent arriving from another process, when it
1127  // already exists as a non-local agent on this process; leave the original alone
1128  // and discard the new version.
1129  }
1130  delete out;
1131  } else { // Agent was not already on this rank and is not a new local agent; must process it as a new request
1132  if (out->getId().currentRank() != rank_)
1133  secondaryAgentsToRequest.addRequest(out->getId());
1134  }
1135  contentIter++;
1136  }
1137 
1138  // Update the importer/exporter to reflect the newly arrived local agents
1139  importer_exporter->incorporateAgentExporterInfo(
1140  *((*packetIter)->exporterInfoPtr));
1141  importer_exporter->clearExportToSpecificProc(rank_); // Export Info may include 'exports' to self; remove these
1142 
1143  }
1144 
1145  // STEP 11: Newly received secondary agents must be coordinated with current processes
1146  if (sendSecondaryData)
1147  initiateAgentRequest(secondaryAgentsToRequest);
1148 
1149  // STEP 12: Set all the Projection Info, including graph edges, and clear the received data
1150  for (packetIter = packetsRecd.begin(); packetIter != packetIterEnd;
1151  ++packetIter) {
1152  context.setProjectionInfo(*((*packetIter)->projectionInfoPtr));
1153  delete (*packetIter)->deleteExporterInfo(); // Exporter Info is only deleted from the received packets, not the sent ones...
1154  }
1155 
1156 }
1157 
1158 }
1159 
1160 #endif /* REPASTPROCESS_H_ */
repast::SharedContext::importedAgentRemoved
void importedAgentRemoved(const AgentId &id)
Notifies this context that the specified non-local agent has been removed and this context should the...
Definition: SharedContext.h:808
repast::SharedContext::removeAgent
void removeAgent(const AgentId id)
Removes the specified agent from this context.
Definition: SharedContext.h:796
repast::Context::addAgent
T * addAgent(T *agent)
Adds the agent to the context.
Definition: Context.h:886
repast::AgentStatus
Encapsulates the status (moved or removed) of agent in order to synchronize that status across proces...
Definition: AgentStatus.h:52
repast::RepastProcess::init
static RepastProcess * init(std::string propsfile, boost::mpi::communicator *comm=0, int maxConfigFileSize=MAX_CONFIG_FILE_SIZE)
Initialize this RepastProcess.
Definition: RepastProcess.cpp:105
repast::SyncStatus_Packet::deleteExporterInfo
SyncStatus_Packet * deleteExporterInfo()
This method includes a very odd construction that arises because the Packet must delete the exporter ...
Definition: RepastProcess.h:211
repast::RepastProcess::rank
int rank() const
Gets the rank of this process.
Definition: RepastProcess.h:378
repast::RepastProcess::agentRemoved
void agentRemoved(const AgentId &id)
NON USER API.
Definition: RepastProcess.cpp:148
repast::SyncStatus_Packet
Class that contains information sent in conjunction with synchronizing agent status (agents moving or...
Definition: RepastProcess.h:155
repast::ImporterExporter_BY_SET
Implementation of the AbstractImporterExporter class that wraps a collection of AbstractImporterExpor...
Definition: AgentImporterExporter.h:956
repast::ImporterExporter_BY_SET::getReport
virtual std::string getReport()
Gets a printable report of the state of this object.
Definition: AgentImporterExporter.h:1035
repast::SharedContext::getNonlocalAgentsToDrop
void getNonlocalAgentsToDrop(std::set< AgentId > &agentsToKeep, std::set< AgentId > &agentsToDrop, RADIUS radius=Projection< T >::PRIMARY)
Given an initial set of agents that must be kept a priori, add any agents that must be kept due to pr...
Definition: SharedContext.h:1060
repast::AgentId
Agent identity information.
Definition: AgentId.h:60
repast::Context::getAgent
T * getAgent(const AgentId &id)
Gets the specified agent.
Definition: Context.h:861
repast::AbstractImporterExporter::exchangeAgentStatusUpdates
virtual void exchangeAgentStatusUpdates(boost::mpi::communicator comm, std::vector< std::vector< AgentStatus > * > &statusUpdates)
Exchanges the contents of the 'statusMap' with the destination processes, updating the status (moved ...
Definition: AgentImporterExporter.cpp:1008
repast::AgentStatus::getOldId
const AgentId & getOldId() const
Gets the old id of the agent that this is the status for, if this contains an old and updated AgentId...
Definition: AgentStatus.h:114
SRManager::retrieveSources
void retrieveSources()
Performs the actual send operation, populating the receive array with values from the other processes...
Definition: SRManager.cpp:86
repast::AgentId::currentRank
int currentRank() const
Gets the current process rank of this AgentId.
Definition: AgentId.h:135
repast::Context::setProjectionInfo
void setProjectionInfo(std::map< std::string, std::vector< repast::ProjectionInfoPacket * > > &projInfo)
Sets the projection information as specified.
Definition: Context.h:1102
repast::RepastProcess
Encapsulates the process in which repast is running and manages interprocess communication etc.
Definition: RepastProcess.h:232
repast::RepastProcess::getScheduleRunner
ScheduleRunner & getScheduleRunner()
Gets the ScheduleRunner used by this RepastProcess.
Definition: RepastProcess.h:401
repast::Projection
Abstract base class for all Projections.
Definition: Projection.h:125
repast::Context::getProjectionInfo
void getProjectionInfo(AgentRequest req, std::map< std::string, std::vector< repast::ProjectionInfoPacket * > > &map, bool secondaryInfo=false, std::set< AgentId > *secondaryIds=0, int destProc=-1)
Gets the projection information for all projections in this context, for all agents whose IDs are lis...
Definition: Context.h:1091
repast::AgentStatus::getStatus
Status getStatus() const
Gets the status.
Definition: AgentStatus.h:94
repast::SharedContext
Context implementation specialized for the parallel distributed simulation.
Definition: SharedContext.h:115
repast::RepastProcess::worldSize
int worldSize() const
Gets the number of processes in the world.
Definition: RepastProcess.h:385
repast::SharedContext::keepsAgentsOnSyncProj
bool keepsAgentsOnSyncProj()
Returns true if any of the projections in this context will try to 'keep' non-local agents during a s...
Definition: SharedContext.h:1015
repast::RepastProcess::addImportedAgent
void addImportedAgent(AgentId id)
NON USER API.
Definition: RepastProcess.cpp:144
repast::SharedContext::getRequiredAgents
void getRequiredAgents(std::set< AgentId > &agentsToTest, std::set< AgentId > &agentsToKeep, RADIUS radius=Projection< T >::PRIMARY)
Given a set of agents to test, returns the set of those agents that must be kept in order to keep req...
Definition: SharedContext.h:1050
SRManager
Coordinates send and receive between processes by notifying processes to expect a send from X other p...
Definition: SRManager.h:52
repast::RepastProcess::moveAgent
void moveAgent(const AgentId &id, int process)
NON USER API.
Definition: RepastProcess.cpp:153
repast::AgentRequest
Encapsulates a request made by one process for agents in another.
Definition: AgentRequest.h:59
repast::AgentRequest::addRequest
void addRequest(const AgentId &id)
Adds the specified agent to the collection agents being requested.
Definition: AgentRequest.cpp:56
repast::RepastProcess::synchronizeProjectionInfo
void synchronizeProjectionInfo(SharedContext< T > &context, Provider &provider, Updater &updater, AgentCreator &creator, EXCHANGE_PATTERN exchangePattern=POLL, bool declareNoAgentsKeptOnAnyProcess=false)
Synchronizes the Projection information for shared projections.
Definition: RepastProcess.h:679
repast::Request_Packet
Contains information sent as agents are exchanged, either in response to requests or agent movement.
Definition: RepastProcess.h:99
repast::RepastProcess::synchronizeAgentStates
void synchronizeAgentStates(Provider &provider, Updater &updater, std::string setName=REQUEST_AGENTS_ALL)
Synchronizes the state values of shared agents.
Definition: RepastProcess.h:614
repast::RepastProcess::instance
static RepastProcess * instance()
Gets this RepastProcess.
Definition: RepastProcess.cpp:126
repast::AgentStatus::getNewId
const AgentId & getNewId() const
Gets the new updated id of the agent that this is the status for, if this contains an old and updated...
Definition: AgentStatus.h:125
repast::AbstractImporterExporter
Wraps and Importer and an Exporter so that both use commensurate semantics and all imports and export...
Definition: AgentImporterExporter.h:772
repast::RepastProcess::requestAgents
void requestAgents(SharedContext< T > &context, AgentRequest &request, Provider &provider, Updater &updater, AgentCreator &creator, std::string setName=DEFAULT_AGENT_REQUEST_SET, AGENT_IMPORTER_EXPORTER_TYPE setType=DEFAULT_ENUM_SYMBOL)
Request agents from other processes.
Definition: RepastProcess.h:524
repast::RepastProcess::synchronizeAgentStatus
void synchronizeAgentStatus(SharedContext< T > &context, Provider &provider, Updater &updater, AgentCreator &creator, EXCHANGE_PATTERN exchangePattern=POLL)
Synchronizes the status (moved or died) of all agents across processes.
Definition: RepastProcess.h:892
repast::ScheduleRunner
Runs the Schedule by popping events off of the Schedule and executing them; also provides methods for...
Definition: Schedule.h:239
repast::RepastProcess::done
void done()
Notifes this RepastProcess that simulation has completed.
Definition: RepastProcess.cpp:136
repast::ImporterExporter_BY_SET::version
virtual std::string version()
Returns the version of this AbstractImporterExporter.
Definition: AgentImporterExporter.cpp:1410
repast::RepastProcess::addExportedAgent
void addExportedAgent(int importingProcess, AgentId id)
NON USER API.
Definition: RepastProcess.cpp:140