PetaVision  Alpha
ArborList.cpp
1 /*
2  * ArborList.cpp
3  *
4  * Created on: Jan 5, 2018
5  * Author: pschultz
6  */
7 
8 #include "ArborList.hpp"
9 #include "columns/HyPerCol.hpp"
10 #include "components/ConnectionData.hpp"
11 #include "layers/HyPerLayer.hpp"
12 #include "utils/MapLookupByType.hpp"
13 
14 namespace PV {
15 
16 ArborList::ArborList(char const *name, HyPerCol *hc) { initialize(name, hc); }
17 
18 ArborList::ArborList() {}
19 
20 ArborList::~ArborList() { free(mDelaysParams); }
21 
22 int ArborList::initialize(char const *name, HyPerCol *hc) {
23  return BaseObject::initialize(name, hc);
24 }
25 
26 void ArborList::setObjectType() { mObjectType = "ArborList"; }
27 
28 int ArborList::ioParamsFillGroup(enum ParamsIOFlag ioFlag) {
30  ioParam_delay(ioFlag);
31  return PV_SUCCESS;
32 }
33 
34 void ArborList::ioParam_numAxonalArbors(enum ParamsIOFlag ioFlag) {
35  parent->parameters()->ioParamValue(
36  ioFlag, this->getName(), "numAxonalArbors", &mNumAxonalArbors, mNumAxonalArbors);
37  if (ioFlag == PARAMS_IO_READ) {
38  if (getNumAxonalArbors() <= 0 && parent->getCommunicator()->globalCommRank() == 0) {
39  WarnLog().printf(
40  "Connection %s: Variable numAxonalArbors is set to 0. "
41  "No connections will be made.\n",
42  this->getName());
43  }
44  }
45 }
46 
47 void ArborList::ioParam_delay(enum ParamsIOFlag ioFlag) {
48  // Grab delays in ms and load into mDelaysParams.
49  // initializeDelays() will convert the delays to timesteps store into delays.
50  parent->parameters()->ioParamArray(ioFlag, getName(), "delay", &mDelaysParams, &mNumDelays);
51  if (ioFlag == PARAMS_IO_READ && mNumDelays == 0) {
52  assert(mDelaysParams == nullptr);
53  mDelaysParams = (double *)pvMallocError(
54  sizeof(double),
55  "%s: unable to set default delay: %s\n",
56  this->getDescription_c(),
57  strerror(errno));
58  *mDelaysParams = 0.0f; // Default delay
59  mNumDelays = 1;
60  if (parent->getCommunicator()->globalCommRank() == 0) {
61  InfoLog().printf("%s: Using default value of zero for delay.\n", this->getDescription_c());
62  }
63  }
64 }
65 
66 Response::Status
67 ArborList::communicateInitInfo(std::shared_ptr<CommunicateInitInfoMessage const> message) {
68  ConnectionData *connectionData =
69  mapLookupByType<ConnectionData>(message->mHierarchy, getDescription());
70  FatalIf(
71  connectionData == nullptr,
72  "%s received CommunicateInitInfo message without a ConnectionData component.\n",
73  getDescription_c());
74 
75  if (!connectionData->getInitInfoCommunicatedFlag()) {
76  if (parent->getCommunicator()->globalCommRank() == 0) {
77  InfoLog().printf(
78  "%s must wait until the ConnectionData component has finished its "
79  "communicateInitInfo stage.\n",
80  getDescription_c());
81  }
82  return Response::POSTPONE;
83  }
84  HyPerLayer *preLayer = connectionData->getPre();
85 
86  initializeDelays();
87  int maxDelay = maxDelaySteps();
88  int allowedDelay = preLayer->increaseDelayLevels(maxDelay);
89  if (allowedDelay < maxDelay) {
90  if (parent->getCommunicator()->globalCommRank() == 0) {
91  ErrorLog().printf(
92  "%s: attempt to set delay to %d, but the maximum "
93  "allowed delay is %d. Exiting\n",
94  getDescription_c(),
95  maxDelay,
96  allowedDelay);
97  }
98  MPI_Barrier(parent->getCommunicator()->globalCommunicator());
99  exit(EXIT_FAILURE);
100  }
101 
102  return Response::SUCCESS;
103 }
104 
105 void ArborList::initializeDelays() {
106  assert(!parent->parameters()->presentAndNotBeenRead(this->getName(), "numAxonalArbors"));
107  mDelay.resize(getNumAxonalArbors());
108 
109  // Initialize delays for each arbor
110  // Using setDelay to convert ms to timesteps
111  for (int arborId = 0; arborId < (int)mDelay.size(); arborId++) {
112  if (mNumDelays == 0) {
113  // No delay
114  setDelay(arborId, 0.0);
115  }
116  else if (mNumDelays == 1) {
117  setDelay(arborId, mDelaysParams[0]);
118  }
119  else if (mNumDelays == getNumAxonalArbors()) {
120  setDelay(arborId, mDelaysParams[arborId]);
121  }
122  else {
123  Fatal().printf(
124  "Delay must be either a single value or the same length "
125  "as the number of arbors\n");
126  }
127  }
128 }
129 
130 void ArborList::setDelay(int arborId, double delay) {
131  assert(arborId >= 0 && arborId < getNumAxonalArbors());
132  int intDelay = (int)std::nearbyint(delay / parent->getDeltaTime());
133  if (std::fmod(delay, parent->getDeltaTime()) != 0) {
134  double actualDelay = intDelay * parent->getDeltaTime();
135  WarnLog() << getName() << ": A delay of " << delay << " will be rounded to " << actualDelay
136  << "\n";
137  }
138  mDelay[arborId] = intDelay;
139 }
140 
141 int ArborList::maxDelaySteps() {
142  int maxDelay = 0;
143  int const numArbors = getNumAxonalArbors();
144  for (auto &d : mDelay) {
145  if (d > maxDelay) {
146  maxDelay = d;
147  }
148  }
149  return maxDelay;
150 }
151 
152 } // namespace PV
HyPerLayer * getPre()
virtual void ioParam_delay(enum ParamsIOFlag ioFlag)
delay: Specifies delay(s) which the post layer will receive data
Definition: ArborList.cpp:47
virtual void ioParam_numAxonalArbors(enum ParamsIOFlag ioFlag)
numAxonalArbors: Specifies the number of arbors to use in the connection
Definition: ArborList.cpp:34
int getNumAxonalArbors() const
Definition: ArborList.hpp:52
virtual int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override
Definition: ArborList.cpp:28
bool getInitInfoCommunicatedFlag() const
Definition: BaseObject.hpp:95