PetaVision  Alpha
ColumnEnergyProbe.cpp
1 /*
2  * ColumnEnergyProbe.cpp
3  *
4  * Created on: Aug 12, 2015
5  * Author: pschultz
6  */
7 
8 #include "ColumnEnergyProbe.hpp"
9 #include "columns/HyPerCol.hpp"
10 #include <limits>
11 
12 namespace PV {
13 
15  : ColProbe() { // Default constructor to be called by derived classes.
16  // They should call ColumnEnergyProbe::initialize from their own
17  // initialization routine
18  // instead of calling a non-default constructor.
20 } // end ColumnEnergyProbe::ColumnEnergyProbe(const char *)
21 
22 ColumnEnergyProbe::ColumnEnergyProbe(const char *probename, HyPerCol *hc) : ColProbe() {
24  initializeColumnEnergyProbe(probename, hc);
25 } // end ColumnEnergyProbe::ColumnEnergyProbe(const char *, HyPerCol *)
26 
28  // Don't delete terms[k]; the BaseProbes belong to the layer or connection.
29  free(terms);
30 } // end ColumnEnergyProbe::~ColumnEnergyProbe()
31 
33  numTerms = 0;
34  terms = NULL;
35 
36  return PV_SUCCESS;
37 }
38 
39 int ColumnEnergyProbe::ioParamsFillGroup(enum ParamsIOFlag ioFlag) {
40  int status = ColProbe::ioParamsFillGroup(ioFlag);
41  ioParam_reductionInterval(ioFlag);
42  return status;
43 }
44 
45 void ColumnEnergyProbe::ioParam_reductionInterval(enum ParamsIOFlag ioFlag) {
46  parent->parameters()->ioParamValue(
47  ioFlag, name, "reductionInterval", &mSkipInterval, mSkipInterval, false /*warnIfAbsent*/);
48 }
49 
51  return ColProbe::initialize(probename, hc);
52 }
53 
55  if (isWritingToFile()) {
56  for (auto &s : mOutputStreams) {
57  *s << "time,index,energy\n";
58  }
59  }
60  else {
61  if (!mOutputStreams.empty()) {
62  *mOutputStreams[0] << "Probe_name,time,index,energy\n";
63  }
64  }
65 }
66 
68  if (probe == NULL) {
69  return PV_FAILURE;
70  }
71  int status = PV_SUCCESS;
72  if (numTerms == 0) {
73  int newNumValues = probe->getNumValues();
74  if (newNumValues < 0) {
75  status = PV_FAILURE;
76  if (parent->columnId() == 0) {
77  ErrorLog().printf(
78  "%s: %s cannot be used as a term of the energy "
79  "probe (getNumValue() returned a "
80  "negative number).\n",
81  getDescription_c(),
82  probe->getDescription_c());
83  }
84  MPI_Barrier(parent->getCommunicator()->communicator());
85  exit(EXIT_FAILURE);
86  }
87  if (newNumValues != this->getNumValues()) {
88  setNumValues(newNumValues);
89  }
90  }
91  else {
92  if (probe->getNumValues() != this->getNumValues()) {
93  if (this->parent->columnId() == 0) {
94  ErrorLog().printf(
95  "Failed to add terms to %s: new probe \"%s\" "
96  "returns %d values, but previous "
97  "probes return %d values\n",
98  getDescription_c(),
99  probe->getName(),
100  probe->getNumValues(),
101  this->getNumValues());
102  }
103  MPI_Barrier(this->parent->getCommunicator()->communicator());
104  exit(EXIT_FAILURE);
105  }
106  }
107  assert(probe->getNumValues() == getNumValues());
108  int newNumTerms = numTerms + (size_t)1;
109  if (newNumTerms <= numTerms) {
110  if (this->parent->columnId() == 0) {
111  ErrorLog().printf(
112  "How did you manage to add %zu terms to %s? "
113  "Unable to add any more!\n",
114  numTerms,
115  getDescription_c());
116  }
117  MPI_Barrier(this->parent->getCommunicator()->communicator());
118  exit(EXIT_FAILURE);
119  }
120  BaseProbe **newTermsArray =
121  (BaseProbe **)realloc(terms, (numTerms + (size_t)1) * sizeof(BaseProbe *));
122  if (newTermsArray == NULL) {
123  ErrorLog().printf(
124  "%s: unable to add term %zu (\"%s\"): %s\n",
125  getDescription_c(),
126  numTerms + (size_t)1,
127  probe->getName(),
128  strerror(errno));
129  exit(EXIT_FAILURE);
130  }
131  terms = newTermsArray;
132  terms[numTerms] = probe;
133  numTerms = newNumTerms;
134  return PV_SUCCESS;
135 } // end ColumnEnergyProbe::addTerm(BaseProbe *, double)
136 
137 bool ColumnEnergyProbe::needRecalc(double timevalue) { return true; }
138 
139 double ColumnEnergyProbe::referenceUpdateTime() const { return parent->simulationTime(); }
140 
141 void ColumnEnergyProbe::calcValues(double timevalue) {
142  if (mLastTimeValue == timevalue || --mSkipTimer > 0) {
143  mLastTimeValue = timevalue;
144  return;
145  }
146  mSkipTimer = mSkipInterval + 1;
147  double *valuesBuffer = getValuesBuffer();
148  int numValues = this->getNumValues();
149  memset(valuesBuffer, 0, numValues * sizeof(*valuesBuffer));
150  double energy1[numValues];
151  for (int n = 0; n < numTerms; n++) {
152  BaseProbe *p = terms[n];
153  p->getValues(timevalue, energy1);
154  double coeff = p->getCoefficient();
155  for (int b = 0; b < numValues; b++) {
156  valuesBuffer[b] += coeff * energy1[b];
157  }
158  }
159 }
160 
161 Response::Status ColumnEnergyProbe::outputState(double timevalue) {
162  getValues(timevalue);
163  if (mOutputStreams.empty()) {
164  return Response::SUCCESS;
165  }
166 
167  double *valuesBuffer = getValuesBuffer();
168  int nbatch = this->getNumValues();
169  pvAssert(nbatch == (int)mOutputStreams.size());
170  char const *probeOutputFilename = getProbeOutputFilename();
171  for (int b = 0; b < nbatch; b++) {
172  auto stream = *mOutputStreams[b];
173  if (!isWritingToFile()) {
174  stream << "\"" << name << "\","; // lack of \n is deliberate
175  }
176  stream.printf("%10f, %d, %10.9f\n", timevalue, b, valuesBuffer[b]);
177  stream.flush();
178  }
179  return Response::SUCCESS;
180 } // end ColumnEnergyProbe::outputState(double)
181 
182 } // end namespace PV
virtual bool needRecalc(double timevalue) override
void setNumValues(int n)
Definition: BaseProbe.cpp:221
int addTerm(BaseProbe *probe)
Adds a probe to the energy calculation.
char const * getProbeOutputFilename()
Definition: BaseProbe.hpp:314
int initializeColumnEnergyProbe(const char *probename, HyPerCol *hc)
double getCoefficient()
Definition: BaseProbe.hpp:95
virtual double referenceUpdateTime() const override
virtual Response::Status outputState(double timevalue) override
int initialize(const char *name, HyPerCol *hc)
Definition: ColProbe.cpp:31
double * getValuesBuffer()
Definition: BaseProbe.hpp:319
bool isWritingToFile() const
Definition: BaseProbe.hpp:330
virtual void outputHeader() override
virtual void calcValues(double timevalue) override
void getValues(double timevalue, double *valuesVector)
Definition: BaseProbe.cpp:336
int getNumValues()
Definition: BaseProbe.hpp:61
virtual int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override
Definition: ColProbe.cpp:36
virtual int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override