#include "transition.h"
#include "errorhandler.h"
#include "keeper.h"
#include "readword.h"
#include "gadget.h"
#include "global.h"
Transition::Transition(CommentStream& infile, const IntVector& areas, int Age,
const LengthGroupDivision* const lgrpdiv, const char* givenname,
const TimeClass* const TimeInfo, Keeper* const keeper)
: HasName(givenname), LivesOnAreas(areas), age(Age) {
int i = 0;
istagged = 0;
ratioscale = 1.0; //JMB used to scale the ratios to ensure that they sum to 1
char text[MaxStrLength];
strncpy(text, "", MaxStrLength);
keeper->addString("transition");
LgrpDiv = new LengthGroupDivision(*lgrpdiv);
if (LgrpDiv->Error())
handle.logMessage(LOGFAIL, "Error in transition - failed to create length group");
infile >> text >> ws;
if (strcasecmp(text, "transitionstocksandratios") != 0)
handle.logFileUnexpected(LOGFAIL, "transitionstocksandratios", text);
infile >> text >> ws;
while (strcasecmp(text, "transitionstep") != 0 && !infile.eof()) {
transitionStockNames.resize(new char[strlen(text) + 1]);
strcpy(transitionStockNames[i], text);
transitionRatio.resize(1, keeper);
if (!(infile >> transitionRatio[i]))
handle.logFileMessage(LOGFAIL, "invalid format for transition ratio");
transitionRatio[i].Inform(keeper);
infile >> text >> ws;
i++;
}
if (infile.eof())
handle.logFileEOFMessage(LOGFAIL);
infile >> transitionStep >> ws;
if (transitionStep < 1 || transitionStep > TimeInfo->numSteps())
handle.logFileMessage(LOGFAIL, "invalid transition step", transitionStep);
keeper->clearLast();
}
Transition::~Transition() {
int i;
for (i = 0; i < transitionStockNames.Size(); i++)
delete[] transitionStockNames[i];
for (i = 0; i < CI.Size(); i++)
delete CI[i];
delete LgrpDiv;
}
void Transition::setStock(StockPtrVector& stockvec) {
int i, j, index;
for (i = 0; i < transitionStockNames.Size(); i++)
for (j = 0; j < transitionStockNames.Size(); j++)
if ((strcasecmp(transitionStockNames[i], transitionStockNames[j]) == 0) && (i != j))
handle.logMessage(LOGFAIL, "Error in transition - repeated stock", transitionStockNames[i]);
for (i = 0; i < stockvec.Size(); i++)
for (j = 0; j < transitionStockNames.Size(); j++)
if (strcasecmp(stockvec[i]->getName(), transitionStockNames[j]) == 0)
transitionStocks.resize(stockvec[i]);
if (transitionStocks.Size() != transitionStockNames.Size()) {
handle.logMessage(LOGWARN, "Error in transition - failed to match transition stocks");
for (i = 0; i < stockvec.Size(); i++)
handle.logMessage(LOGWARN, "Error in transition - found stock", stockvec[i]->getName());
for (i = 0; i < transitionStockNames.Size(); i++)
handle.logMessage(LOGWARN, "Error in transition - looking for stock", transitionStockNames[i]);
handle.logMessage(LOGFAIL, ""); //JMB this will exit gadget
}
//JMB ensure that the ratio vector is indexed in the right order
ratioindex.resize(transitionStocks.Size(), 0);
for (i = 0; i < transitionStocks.Size(); i++)
for (j = 0; j < transitionStockNames.Size(); j++)
if (strcasecmp(transitionStocks[i]->getName(), transitionStockNames[j]) == 0)
ratioindex[i] = j;
double mlength = 9999.0;
for (i = 0; i < transitionStocks.Size(); i++) {
CI.resize(new ConversionIndex(LgrpDiv, transitionStocks[i]->getLengthGroupDiv()));
if (CI[i]->Error())
handle.logMessage(LOGFAIL, "Error in transition - error when checking length structure");
index = 0;
for (j = 0; j < areas.Size(); j++)
if (!transitionStocks[i]->isInArea(areas[j]))
index++;
if (index != 0)
handle.logMessage(LOGWARN, "Warning in transition - transition stock isnt defined on all areas");
if (transitionStocks[i]->getLengthGroupDiv()->minLength() < mlength)
mlength = transitionStocks[i]->getLengthGroupDiv()->minLength();
}
minTransitionLength = LgrpDiv->numLengthGroup(mlength);
IntVector minlv(2, 0);
IntVector sizev(2, LgrpDiv->numLengthGroups());
Storage.resize(areas.Size(), age, minlv, sizev);
for (i = 0; i < Storage.Size(); i++)
Storage[i].setToZero();
}
void Transition::Print(ofstream& outfile) const {
int i;
outfile << "\nTransition\n\tNames of transition stocks:";
for (i = 0; i < transitionStockNames.Size(); i++)
outfile << sep << transitionStockNames[i];
outfile << "\n\tRatio moving into each stock:";
for (i = 0; i < transitionRatio.Size(); i++)
outfile << sep << (transitionRatio[ratioindex[i]] * ratioscale);
outfile << "\n\tTransition step " << transitionStep << endl;
}
void Transition::storeTransitionStock(int area, AgeBandMatrix& Alkeys, const TimeClass* const TimeInfo) {
int len, inarea = this->areaNum(area);
for (len = Storage[inarea].minLength(age); len < Storage[inarea].maxLength(age); len++) {
Storage[inarea][age][len].N = Alkeys[age][len].N;
Storage[inarea][age][len].W = Alkeys[age][len].W;
if (len >= minTransitionLength)
Alkeys[age][len].setToZero();
}
}
void Transition::storeTransitionStock(int area, AgeBandMatrix& Alkeys,
AgeBandMatrixRatio& TagAlkeys, const TimeClass* const TimeInfo) {
if (!istagged)
handle.logMessage(LOGFAIL, "Error in transition - invalid tagging experiment");
int len, tag;
int inarea = this->areaNum(area);
double tagnumber;
for (len = Storage[inarea].minLength(age); len < Storage[inarea].maxLength(age); len++) {
Storage[inarea][age][len].N = Alkeys[age][len].N;
Storage[inarea][age][len].W = Alkeys[age][len].W;
if (len >= minTransitionLength)
Alkeys[age][len].setToZero();
for (tag = 0; tag < TagAlkeys.numTagExperiments(); tag++) {
tagnumber = *(TagAlkeys[age][len][tag].N);
if (tagnumber < verysmall)
*(tagStorage[inarea][age][len][tag].N) = 0.0;
else
*(tagStorage[inarea][age][len][tag].N) = tagnumber;
if (len >= minTransitionLength) {
*(TagAlkeys[age][len][tag].N) = 0.0;
TagAlkeys[age][len][tag].R = 0.0;
}
}
}
}
//area in the call to this routine is not in the local area numbering of the stock.
void Transition::Move(int area, const TimeClass* const TimeInfo) {
int i, inarea = this->areaNum(area);
double ratio;
for (i = 0; i < transitionStocks.Size(); i++) {
if (!transitionStocks[i]->isInArea(area))
handle.logMessage(LOGFAIL, "Error in transition - transition stock doesnt live on area", area);
if (transitionStocks[i]->isBirthday(TimeInfo)) {
Storage[inarea].IncrementAge();
if (istagged && tagStorage.numTagExperiments() > 0)
tagStorage[inarea].IncrementAge(Storage[inarea]);
}
ratio = transitionRatio[ratioindex[i]] * ratioscale;
transitionStocks[i]->Add(Storage[inarea], CI[i], area, ratio);
if (istagged && tagStorage.numTagExperiments() > 0)
transitionStocks[i]->Add(tagStorage, CI[i], area, ratio);
}
Storage[inarea].setToZero();
if (istagged && tagStorage.numTagExperiments() > 0)
tagStorage[inarea].setToZero();
}
void Transition::Reset() {
int i;
//JMB check that the sum of the ratios is 1
ratioscale = 0.0;
for (i = 0; i < transitionRatio.Size(); i++ )
ratioscale += transitionRatio[i];
if (isZero(ratioscale)) {
handle.logMessage(LOGWARN, "Warning in transition - specified ratios are zero");
ratioscale = 1.0;
} else if (isEqual(ratioscale, 1.0)) {
// do nothing
} else {
handle.logMessage(LOGWARN, "Warning in transition - scaling ratios using", ratioscale);
ratioscale = 1.0 / ratioscale;
}
if (handle.getLogLevel() >= LOGMESSAGE)
handle.logMessage(LOGMESSAGE, "Reset transition data for stock", this->getName());
}
const StockPtrVector& Transition::getTransitionStocks() {
return transitionStocks;
}
void Transition::setTagged() {
istagged = 1;
//resize tagStorage to be the same size as Storage
int i;
IntVector lower(2, 0);
IntVector size(2, LgrpDiv->numLengthGroups());
tagStorage.resize(areas.Size(), age, lower, size);
for (i = 0; i < tagStorage.Size(); i++)
tagStorage[i].setToZero();
}
void Transition::addTransitionTag(const char* tagname) {
if (!istagged)
handle.logMessage(LOGFAIL, "Error in transition - invalid tagging experiment", tagname);
tagStorage.addTag(tagname);
}
void Transition::deleteTransitionTag(const char* tagname) {
if (!istagged)
handle.logMessage(LOGFAIL, "Error in transition - invalid tagging experiment", tagname);
int minage, maxage, age, len, a;
int id = tagStorage.getTagID(tagname);
if (id >= 0) {
minage = tagStorage[0].minAge();
maxage = tagStorage[0].maxAge();
//free memory allocated for tagging experiment
for (a = 0; a < tagStorage.Size(); a++) {
for (age = minage; age <= maxage; age++) {
for (len = tagStorage[a].minLength(age); len < tagStorage[a].maxLength(age); len++) {
delete[] (tagStorage[a][age][len][id].N);
(tagStorage[a][age][len][id].N) = NULL;
}
}
}
tagStorage.deleteTag(tagname);
} else
handle.logMessage(LOGWARN, "Warning in transition - failed to delete tagging experiment", tagname);
}
int Transition::isTransitionStep(const TimeClass* const TimeInfo) {
if (TimeInfo->getStep() == transitionStep)
return 1;
return 0;
}