PetaVision  Alpha
PatchSize.cpp
1 /*
2  * PatchSize.cpp
3  *
4  * Created on: Jan 5, 2018
5  * Author: Pete Schultz
6  */
7 
8 #include "PatchSize.hpp"
9 #include "columns/HyPerCol.hpp"
10 #include "utils/MapLookupByType.hpp"
11 
12 namespace PV {
13 
14 PatchSize::PatchSize(char const *name, HyPerCol *hc) { initialize(name, hc); }
15 
16 PatchSize::~PatchSize() {}
17 
18 int PatchSize::initialize(char const *name, HyPerCol *hc) {
19  return BaseObject::initialize(name, hc);
20 }
21 
22 void PatchSize::setObjectType() { mObjectType = "PatchSize"; }
23 
24 int PatchSize::ioParamsFillGroup(enum ParamsIOFlag ioFlag) {
25  ioParam_nxp(ioFlag);
26  ioParam_nyp(ioFlag);
27  ioParam_nfp(ioFlag);
28  return PV_SUCCESS;
29 }
30 
31 void PatchSize::ioParam_nxp(enum ParamsIOFlag ioFlag) {
32  parent->parameters()->ioParamValue(ioFlag, name, "nxp", &mPatchSizeX, mPatchSizeX);
33 }
34 
35 void PatchSize::ioParam_nyp(enum ParamsIOFlag ioFlag) {
36  parent->parameters()->ioParamValue(ioFlag, name, "nyp", &mPatchSizeY, mPatchSizeY);
37 }
38 
39 void PatchSize::ioParam_nfp(enum ParamsIOFlag ioFlag) {
40  parent->parameters()->ioParamValue(ioFlag, name, "nfp", &mPatchSizeF, mPatchSizeF, false);
41  if (ioFlag == PARAMS_IO_READ && mPatchSizeF < 0 && !parent->parameters()->present(name, "nfp")
42  && parent->getCommunicator()->globalCommRank() == 0) {
43  InfoLog().printf(
44  "%s: nfp will be set in the communicateInitInfo() stage.\n", getDescription_c());
45  }
46 }
47 
48 Response::Status
49 PatchSize::communicateInitInfo(std::shared_ptr<CommunicateInitInfoMessage const> message) {
50  auto status = BaseObject::communicateInitInfo(message);
51  if (!Response::completed(status)) {
52  return status;
53  }
54  mConnectionData = mapLookupByType<ConnectionData>(message->mHierarchy, getDescription());
55  FatalIf(
56  mConnectionData == nullptr,
57  "%s received CommunicateInitInfo message without a ConnectionData component.\n",
58  getDescription_c());
59 
60  if (!mConnectionData->getInitInfoCommunicatedFlag()) {
61  if (parent->getCommunicator()->globalCommRank() == 0) {
62  InfoLog().printf(
63  "%s must wait until the ConnectionData component has finished its "
64  "communicateInitInfo stage.\n",
65  getDescription_c());
66  }
67  return Response::POSTPONE;
68  }
69 
70  HyPerLayer *post = mConnectionData->getPost();
71  int const nfPost = post->getLayerLoc()->nf;
72 
73  if (mPatchSizeF < 0) {
74  mPatchSizeF = nfPost;
75  if (mWarnDefaultNfp && parent->getCommunicator()->globalCommRank() == 0) {
76  InfoLog().printf(
77  "%s setting nfp to number of postsynaptic features = %d.\n",
78  getDescription_c(),
79  mPatchSizeF);
80  }
81  }
82  if (mPatchSizeF != nfPost) {
83  if (parent->getCommunicator()->globalCommRank() == 0) {
84  ErrorLog(errorMessage);
85  errorMessage.printf(
86  "Params file specifies %d features for %s,\n", mPatchSizeF, getDescription_c());
87  errorMessage.printf(
88  "but %d features for post-synaptic layer %s\n", nfPost, post->getName());
89  }
90  MPI_Barrier(parent->getCommunicator()->globalCommunicator());
91  exit(PV_FAILURE);
92  }
93  // Currently, the only acceptable number for mPatchSizeF is the number of post-synaptic features.
94  // However, we may add flexibility on this score in the future, e.g. MPI in feature space
95  // with each feature connecting to only a few nearby features.
96  // Accordingly, we still keep ioParam_nfp.
97 
98  return Response::SUCCESS;
99 }
100 
101 int PatchSize::calcPostPatchSize(int prePatchSize, int numNeuronsPre, int numNeuronsPost) {
102  if (numNeuronsPre == numNeuronsPost) {
103  return prePatchSize;
104  }
105  else if (numNeuronsPre > numNeuronsPost) {
106  std::div_t scaleDivision = div(numNeuronsPre, numNeuronsPost);
107  FatalIf(
108  scaleDivision.rem != 0,
109  "calcPostPatchSize called with numNeuronsPre (%d) greater than numNeuronsPost (%d), "
110  "but not an integer multiple.\n",
111  numNeuronsPre,
112  numNeuronsPost);
113  return prePatchSize * scaleDivision.quot;
114  }
115  else {
116  std::div_t const scaleDivision = div(numNeuronsPost, numNeuronsPre);
117  FatalIf(
118  scaleDivision.rem != 0,
119  "calcPostPatchSize called with numNeuronsPost (%d) greater than numNeuronsPre (%d), "
120  "but not an integer multiple.\n",
121  numNeuronsPost,
122  numNeuronsPre);
123  int const scaleFactor = scaleDivision.quot;
124  std::div_t const newPatchSize = div(prePatchSize, scaleFactor);
125  FatalIf(
126  newPatchSize.rem != 0,
127  "calcPostPatchSize called with scale factor of numNeuronsPost/numNeuronsPre = %d, "
128  "but prePatchSize (%d) is not an integer multiple of the scale factor.\n",
129  scaleFactor,
130  prePatchSize);
131  return prePatchSize / scaleFactor;
132  }
133 }
134 
135 } // namespace PV
virtual void ioParam_nyp(enum ParamsIOFlag ioFlag)
nyp: Specifies the y patch size
Definition: PatchSize.cpp:35
static bool completed(Status &a)
Definition: Response.hpp:49
virtual void ioParam_nxp(enum ParamsIOFlag ioFlag)
nxp: Specifies the x patch size
Definition: PatchSize.cpp:31
int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override
Definition: PatchSize.cpp:24
virtual void ioParam_nfp(enum ParamsIOFlag ioFlag)
nfp: Specifies the post feature patch size. If negative, it can be set during the CommunicateInitInfo...
Definition: PatchSize.cpp:39
HyPerLayer * getPost()
static int calcPostPatchSize(int prePatchSize, int numNeuronsPre, int numNeuronsPost)
Definition: PatchSize.cpp:101
bool getInitInfoCommunicatedFlag() const
Definition: BaseObject.hpp:95
virtual Response::Status communicateInitInfo(std::shared_ptr< CommunicateInitInfoMessage const > message) override
If nfp was set to a negative number in params, set it here to the postsynaptic layer&#39;s nf...
Definition: PatchSize.cpp:49