#include "prey.h"
#include "errorhandler.h"
#include "readword.h"
#include "readaggregation.h"
#include "keeper.h"
#include "mathfunc.h"
#include "gadget.h"
#include "global.h"
Prey::Prey(CommentStream& infile, const IntVector& Areas,
const char* givenname, const TimeClass* const TimeInfo, Keeper* const keeper)
: HasName(givenname), LivesOnAreas(Areas), CI(0) {
char text[MaxStrLength];
strncpy(text, "", MaxStrLength);
int i;
//read the prey length group data
DoubleVector preylengths;
CharPtrVector preylenindex;
char aggfilename[MaxStrLength];
strncpy(aggfilename, "", MaxStrLength);
ifstream datafile;
CommentStream subdata(datafile);
readWordAndValue(infile, "preylengths", aggfilename);
datafile.open(aggfilename, ios::in);
handle.checkIfFailure(datafile, aggfilename);
handle.Open(aggfilename);
i = readLengthAggregation(subdata, preylengths, preylenindex);
handle.Close();
datafile.close();
datafile.clear();
LgrpDiv = new LengthGroupDivision(preylengths);
if (LgrpDiv->Error())
handle.logMessage(LOGFAIL, "Error in prey - failed to create length group");
//read the energy content of this prey
infile >> ws;
char c = infile.peek();
if ((c == 'e') || (c == 'E'))
readWordAndModelVariable(infile, "energycontent", energy, TimeInfo, keeper);
else
energy.setValue(1.0);
//read from file - initialise things
int numlen = LgrpDiv->numLengthGroups();
int numarea = areas.Size();
PopInfo nullpop;
preynumber.AddRows(numarea, numlen, nullpop);
biomass.AddRows(numarea, numlen, 0.0);
cons.AddRows(numarea, numlen, 0.0);
consumption.AddRows(numarea, numlen, 0.0);
isoverconsumption.resize(numarea, 0);
total.resize(numarea, 0.0);
ratio.AddRows(numarea, numlen, 0.0);
useratio.AddRows(numarea, numlen, 0.0);
consratio.AddRows(numarea, numlen, 0.0);
overconsumption.AddRows(numarea, numlen, 0.0);
//preylenindex is not required - free up memory
for (i = 0; i < preylenindex.Size(); i++)
delete[] preylenindex[i];
}
Prey::Prey(CommentStream& infile, const char* givenname,
const IntVector& Areas, const TimeClass* const TimeInfo, Keeper* const keeper)
: HasName(givenname), LivesOnAreas(Areas) {
char text[MaxStrLength];
strncpy(text, "", MaxStrLength);
//read the length information
DoubleVector lengths(2, 0.0);
infile >> text >> ws;
if (strcasecmp(text, "lengths") != 0)
handle.logFileUnexpected(LOGFAIL, "lengths", text);
infile >> lengths[0] >> lengths[1] >> ws;
LgrpDiv = new LengthGroupDivision(lengths);
if (LgrpDiv->Error())
handle.logMessage(LOGFAIL, "Error in prey - failed to create length group");
CI = new ConversionIndex(LgrpDiv, LgrpDiv);
if (CI->Error())
handle.logMessage(LOGFAIL, "Error in prey - error when checking length structure");
//read the energy content of this prey
infile >> ws;
char c = infile.peek();
if ((c == 'e') || (c == 'E'))
readWordAndModelVariable(infile, "energycontent", energy, TimeInfo, keeper);
else
energy.setValue(1.0);
int numlen = LgrpDiv->numLengthGroups();
int numarea = areas.Size();
PopInfo nullpop;
preynumber.AddRows(numarea, numlen, nullpop);
biomass.AddRows(numarea, numlen, 0.0);
cons.AddRows(numarea, numlen, 0.0);
consumption.AddRows(numarea, numlen, 0.0);
isoverconsumption.resize(numarea, 0);
total.resize(numarea, 0.0);
ratio.AddRows(numarea, numlen, 0.0);
useratio.AddRows(numarea, numlen, 0.0);
consratio.AddRows(numarea, numlen, 0.0);
overconsumption.AddRows(numarea, numlen, 0.0);
}
Prey::~Prey() {
delete CI;
delete LgrpDiv;
}
void Prey::setCI(const LengthGroupDivision* const GivenLDiv) {
if (!checkLengthGroupStructure(GivenLDiv, LgrpDiv))
handle.logMessage(LOGFAIL, "Error in prey - invalid length group structure for consumption of", this->getName());
if (GivenLDiv->minLength() < LgrpDiv->minLength())
handle.logMessage(LOGFAIL, "Error in prey - invalid minimum length group for consumption of", this->getName());
if (!isSmall(LgrpDiv->minLength() - GivenLDiv->minLength()))
handle.logMessage(LOGWARN, "Warning in prey - minimum lengths don't match for consumption of", this->getName());
if (GivenLDiv->maxLength() > LgrpDiv->maxLength())
handle.logMessage(LOGFAIL, "Error in prey - invalid maximum length group for consumption of", this->getName());
if (!isSmall(LgrpDiv->maxLength() - GivenLDiv->maxLength()))
handle.logMessage(LOGWARN, "Warning in prey - maximum lengths don't match for consumption of", this->getName());
CI = new ConversionIndex(GivenLDiv, LgrpDiv);
if (CI->Error())
handle.logMessage(LOGFAIL, "Error in prey - error when checking length structure for", this->getName());
}
void Prey::Print(ofstream& outfile) const {
int i, area;
outfile << "\nPrey\n\tName " << this->getName() << "\n\tEnergy content " << energy << "\n\t";
LgrpDiv->Print(outfile);
for (area = 0; area < areas.Size(); area++) {
outfile << "\tNumber of prey on internal area " << areas[area] << ":\n\t";
for (i = 0; i < LgrpDiv->numLengthGroups(); i++)
outfile << setw(smallwidth) << setprecision(smallprecision) << preynumber[area][i].N << sep;
outfile << "\n\tWeight of prey on internal area " << areas[area] << ":\n\t";
for (i = 0; i < LgrpDiv->numLengthGroups(); i++)
outfile << setw(smallwidth) << setprecision(smallprecision) << preynumber[area][i].W << sep;
outfile << "\n\tConsumption of prey on internal area " << areas[area] << ":\n\t";
for (i = 0; i < LgrpDiv->numLengthGroups(); i++)
outfile << setw(smallwidth) << setprecision(smallprecision) << consumption[area][i] << sep;
outfile << "\n\tOverconsumption of prey on internal area " << areas[area] << ":\n\t";
for (i = 0; i < LgrpDiv->numLengthGroups(); i++)
outfile << setw(smallwidth) << setprecision(smallprecision) << overconsumption[area][i] << sep;
outfile << endl;
}
}
//reduce the population of the stock by the consumption
void Prey::Subtract(AgeBandMatrix& Alkeys, int area) {
Alkeys.Subtract(consratio[this->areaNum(area)], *CI);
}
//adds the consumption by biomass
void Prey::addBiomassConsumption(int area, const DoubleVector& predcons) {
int i, inarea = this->areaNum(area);
if (predcons.Size() != cons[inarea].Size())
handle.logMessage(LOGFAIL, "Error in consumption - cannot add different size vectors");
for (i = 0; i < predcons.Size(); i++)
cons[inarea][i] += predcons[i];
}
//adds the consumption by numbers
void Prey::addNumbersConsumption(int area, const DoubleVector& predcons) {
int i, inarea = this->areaNum(area);
if (predcons.Size() != cons[inarea].Size())
handle.logMessage(LOGFAIL, "Error in consumption - cannot add different size vectors");
for (i = 0; i < predcons.Size(); i++)
cons[inarea][i] += (predcons[i] * preynumber[inarea][i].W);
}
//check if more is consumed of prey than was available. If this is
//the case a flag is set. Changed 22 - May 1997 so that only 95% of a prey
//in an area can be eaten in one timestep. This is to avoid problems
//with survey indices etc.
void Prey::checkConsumption(int area, const TimeClass* const TimeInfo) {
int i, over = 0;
int inarea = this->areaNum(area);
double timeratio = 1.0;
double maxRatio = TimeInfo->getMaxRatioConsumed();
if (TimeInfo->numSubSteps() != 1) {
timeratio = 1.0 / TimeInfo->getSubStep();
for (i = 0; i < LgrpDiv->numLengthGroups(); i++)
useratio[inarea][i] *= (1.0 - timeratio);
}
for (i = 0; i < LgrpDiv->numLengthGroups(); i++) {
if (isZero(biomass[inarea][i])) {
//no prey biomass available to consume
ratio[inarea][i] = 0.0;
consratio[inarea][i] = 0.0;
if (!(isZero(cons[inarea][i]))) {
//consumption required but no prey exists
over = 1;
overconsumption[inarea][i] += cons[inarea][i];
}
} else {
//prey available to consume so only need to check overconsumption
ratio[inarea][i] = cons[inarea][i] / biomass[inarea][i];
if (ratio[inarea][i] > maxRatio) {
over = 1;
overconsumption[inarea][i] += (ratio[inarea][i] - maxRatio) * biomass[inarea][i];
consratio[inarea][i] = 1.0 - maxRatio;
useratio[inarea][i] += (timeratio * maxRatio);
cons[inarea][i] = biomass[inarea][i] * maxRatio;
} else {
consratio[inarea][i] = 1.0 - ratio[inarea][i];
useratio[inarea][i] += (timeratio * ratio[inarea][i]);
}
//finally add the consumption
consumption[inarea][i] += cons[inarea][i];
}
}
//JMB changed to deal with substeps a little better
if (over)
isoverconsumption[inarea] = over;
}
void Prey::Reset(const TimeClass* const TimeInfo) {
consumption.setToZero();
overconsumption.setToZero();
useratio.setToZero();
isoverconsumption.setToZero();
energy.Update(TimeInfo);
if (isZero(energy))
handle.logMessage(LOGWARN, "Warning in prey - energy content should be non-zero");
if (handle.getLogLevel() >= LOGMESSAGE)
handle.logMessage(LOGMESSAGE, "Reset consumption data for prey", this->getName());
}
int Prey::isPreyArea(int area) {
if (this->isInArea(area) == 0)
return 0;
if (total[this->areaNum(area)] < 0.0)
handle.logMessage(LOGWARN, "Warning in prey - negative amount consumed for", this->getName());
if (isZero(total[this->areaNum(area)]))
return 0;
return 1;
}
int Prey::isOverConsumption(int area) {
if (this->isInArea(area) == 0)
return 0;
return isoverconsumption[this->areaNum(area)];
}
double Prey::getTotalOverConsumption(int area) const {
int inarea = this->areaNum(area);
if (inarea == -1)
return 0.0;
int i;
double total = 0.0;
for (i = 0; i < LgrpDiv->numLengthGroups(); i++)
total += overconsumption[inarea][i];
return total;
}