Log In | Get Help   
Home My Page Projects Code Snippets Project Openings Mareframe
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files
[mareframe] View of /trunk/gadget/renewal.cc
[mareframe] / trunk / gadget / renewal.cc Repository:
ViewVC logotype

View of /trunk/gadget/renewal.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (download) (annotate)
Mon Feb 10 17:09:07 2014 UTC (10 years, 4 months ago) by agomez
File size: 20177 byte(s)
Initial version based on Gadget 2.2.00
#include "renewal.h"
#include "errorhandler.h"
#include "readfunc.h"
#include "keeper.h"
#include "readword.h"
#include "gadget.h"
#include "global.h"

RenewalData::RenewalData(CommentStream& infile, const IntVector& Areas,
  const AreaClass* const Area, const TimeClass* const TimeInfo, Keeper* const keeper,
  const char* refWeightFile, const char* givenname, int minage, int maxage, double DL)
  : HasName(givenname), LivesOnAreas(Areas), CI(0), LgrpDiv(0) {

  keeper->addString("renewaldata");
  ifstream subfile;
  CommentStream subcomment(subfile);
  char text[MaxStrLength];
  strncpy(text, "", MaxStrLength);

  index = 0;
  int i, j;
  double minlength, maxlength, dl;
  readWordAndVariable(infile, "minlength", minlength);
  readWordAndVariable(infile, "maxlength", maxlength);

  //JMB - changed to make the reading of dl optional
  //if it isnt specifed here, it will default to the dl value of the stock
  infile >> ws;
  char c = infile.peek();
  if ((c == 'd') || (c == 'D'))
    readWordAndVariable(infile, "dl", dl);
  else
    dl = DL;

  LgrpDiv = new LengthGroupDivision(minlength, maxlength, dl);
  if (LgrpDiv->Error())
    handle.logMessage(LOGFAIL, "Error in renewal - failed to create length group");

  infile >> text >> ws;
  if ((strcasecmp(text, "normalcondfile") == 0)) {
    //read renewal data in mean length format, using the reference weight file
    readoption = 0;
    infile >> text >> ws;
    subfile.open(text, ios::in);
    handle.checkIfFailure(subfile, text);
    handle.Open(text);
    this->readNormalConditionData(subcomment, keeper, TimeInfo, Area, minage, maxage);
    handle.Close();
    subfile.close();
    subfile.clear();

    //read information on reference weights.
    DoubleMatrix tmpRefW;
    keeper->addString("referenceweights");
    subfile.open(refWeightFile, ios::in);
    handle.checkIfFailure(subfile, refWeightFile);
    handle.Open(refWeightFile);
    readRefWeights(subcomment, tmpRefW);
    handle.Close();
    subfile.close();
    subfile.clear();

    //Interpolate the reference weights. First there are some error checks.
    if (LgrpDiv->meanLength(0) < tmpRefW[0][0] ||
        LgrpDiv->meanLength(LgrpDiv->numLengthGroups() - 1) > tmpRefW[tmpRefW.Nrow() - 1][0])
      handle.logFileMessage(LOGFAIL, "lengths for reference weights must span the range of initial condition lengths");

    //Aggregate the reference weight data to be the same format
    double ratio, tmplen;
    refWeight.resize(LgrpDiv->numLengthGroups(), 0.0);
    int pos = 0;
    for (j = 0; j < LgrpDiv->numLengthGroups(); j++) {
      tmplen = LgrpDiv->meanLength(j);
      for (i = pos; i < tmpRefW.Nrow() - 1; i++) {
        if (((tmplen > tmpRefW[i][0]) || (isEqual(tmplen, tmpRefW[i][0]))) &&
            ((tmplen < tmpRefW[i + 1][0]) || (isEqual(tmplen, tmpRefW[i + 1][0])))) {

          ratio = (tmplen - tmpRefW[i][0]) / (tmpRefW[i + 1][0] - tmpRefW[i][0]);
          refWeight[j] = tmpRefW[i][1] + ratio * (tmpRefW[i + 1][1] - tmpRefW[i][1]);
          pos = i;
        }
      }
    }
    keeper->clearLast();

  } else if ((strcasecmp(text, "renewaldatafile") == 0) || (strcasecmp(text, "normalparamfile") == 0)) {
    //read renewal data in mean length format, using a length weight relationship
    readoption = 1;
    infile >> text >> ws;
    subfile.open(text, ios::in);
    handle.checkIfFailure(subfile, text);
    handle.Open(text);
    this->readNormalParameterData(subcomment, keeper, TimeInfo, Area, minage, maxage);
    handle.Close();
    subfile.close();
    subfile.clear();

  } else if ((strcasecmp(text, "numberfile") == 0)) {
    //read renewal data in number format
    readoption = 2;
    infile >> text >> ws;
    subfile.open(text, ios::in);
    handle.checkIfFailure(subfile, text);
    handle.Open(text);
    this->readNumberData(subcomment, keeper, TimeInfo, Area, minage, maxage);
    handle.Close();
    subfile.close();
    subfile.clear();

  } else
    handle.logFileMessage(LOGFAIL, "unrecognised renewal data format", text);

  keeper->clearLast();
}

void RenewalData::readNormalParameterData(CommentStream& infile, Keeper* const keeper,
  const TimeClass* const TimeInfo, const AreaClass* const Area, int minage, int maxage) {

  char c;
  int year, step, area, age, keepdata, count, reject;
  PopInfoIndexVector poptmp(LgrpDiv->numLengthGroups(), 0);

  //We now expect to find the renewal data in the following format
  //year, step, area, age, number, mean, sdev, alpha, beta
  infile >> ws;
  if (countColumns(infile) != 9)
    handle.logFileMessage(LOGFAIL, "wrong number of columns in inputfile - should be 9");

  year = step = area = age = count = reject = 0;
  while (!infile.eof()) {
    //crude check to see if something has gone wrong and avoid infinite loops
    if (!(isdigit(infile.peek())))
      handle.logFileMessage(LOGFAIL, "failed to read data from file");

    keepdata = 1;
    infile >> year >> step >> area >> age >> ws;

    if (!(TimeInfo->isWithinPeriod(year, step)))
      keepdata = 0;

    if (!(this->isInArea(Area->getInnerArea(area))))
      keepdata = 0;

    if ((age < minage) || (age > maxage))
      keepdata = 0;

    if (keepdata == 1) {
      //renewal data is required, so store it
      renewalTime.resize(1, TimeInfo->calcSteps(year, step));
      renewalArea.resize(1, Area->getInnerArea(area));
      renewalAge.resize(1, age);

      renewalMult.resize(1, keeper);
      meanLength.resize(1, keeper);
      sdevLength.resize(1, keeper);
      alpha.resize(1, keeper);
      beta.resize(1, keeper);
      renewalDistribution.resize(1, new AgeBandMatrix(age, poptmp));

      infile >> renewalMult[count] >> ws;
      infile >> meanLength[count] >> ws;
      infile >> sdevLength[count] >> ws;
      infile >> alpha[count] >> ws;
      infile >> beta[count] >> ws;

      renewalMult[count].Inform(keeper);
      meanLength[count].Inform(keeper);
      sdevLength[count].Inform(keeper);
      alpha[count].Inform(keeper);
      beta[count].Inform(keeper);
      count++;

    } else { //renewal data not required - skip rest of line
      reject++;
      infile.get(c);
      while (c != '\n' && !infile.eof())
        infile.get(c);
      infile >> ws;
    }
  }

  if (count == 0)
    handle.logMessage(LOGWARN, "Warning in renewal - found no data in the data file");
  if (reject != 0)
    handle.logMessage(LOGMESSAGE, "Discarded invalid renewal data - number of invalid entries", reject);
  handle.logMessage(LOGMESSAGE, "Read renewal data file - number of entries", count);
}

void RenewalData::readNormalConditionData(CommentStream& infile, Keeper* const keeper,
  const TimeClass* const TimeInfo, const AreaClass* const Area, int minage, int maxage) {

  char c;
  int year, step, area, age, keepdata, count, reject;
  PopInfoIndexVector poptmp(LgrpDiv->numLengthGroups(), 0);

  //We now expect to find the renewal data in the following format
  //year, step, area, age, number, mean, sdev, cond
  infile >> ws;
  if (countColumns(infile) != 8)
    handle.logFileMessage(LOGFAIL, "wrong number of columns in inputfile - should be 8");

  year = step = area = age = count = reject = 0;
  while (!infile.eof()) {
    //crude check to see if something has gone wrong and avoid infinite loops
    if (!(isdigit(infile.peek())))
      handle.logFileMessage(LOGFAIL, "failed to read data from file");

    keepdata = 1;
    infile >> year >> step >> area >> age >> ws;

    if (!(TimeInfo->isWithinPeriod(year, step)))
      keepdata = 0;

    if (!(this->isInArea(Area->getInnerArea(area))))
      keepdata = 0;

    if ((age < minage) || (age > maxage))
      keepdata = 0;

    if (keepdata == 1) {
      //renewal data is required, so store it
      renewalTime.resize(1, TimeInfo->calcSteps(year, step));
      renewalArea.resize(1, Area->getInnerArea(area));
      renewalAge.resize(1, age);

      renewalMult.resize(1, keeper);
      meanLength.resize(1, keeper);
      sdevLength.resize(1, keeper);
      relCond.resize(1, keeper);
      renewalDistribution.resize(1, new AgeBandMatrix(age, poptmp));

      infile >> renewalMult[count] >> ws;
      infile >> meanLength[count] >> ws;
      infile >> sdevLength[count] >> ws;
      infile >> relCond[count] >> ws;

      renewalMult[count].Inform(keeper);
      meanLength[count].Inform(keeper);
      sdevLength[count].Inform(keeper);
      relCond[count].Inform(keeper);
      count++;

    } else { //renewal data not required - skip rest of line
      reject++;
      infile.get(c);
      while (c != '\n' && !infile.eof())
        infile.get(c);
      infile >> ws;
    }
  }

  if (count == 0)
    handle.logMessage(LOGWARN, "Warning in renewal - found no data in the data file");
  if (reject != 0)
    handle.logMessage(LOGMESSAGE, "Discarded invalid renewal data - number of invalid entries", reject);
  handle.logMessage(LOGMESSAGE, "Read renewal data file - number of entries", count);
}

void RenewalData::readNumberData(CommentStream& infile, Keeper* const keeper,
  const TimeClass* const TimeInfo, const AreaClass* const Area, int minage, int maxage) {

  char c;
  double length;
  int i, year, step, area, age, keepdata, count, id, lengthid, reject;
  int numlen = LgrpDiv->numLengthGroups();
  PopInfoIndexVector poptmp(numlen, 0);

  //We now expect to find the renewal data in the following format
  //year, step, area, age, length, number, mean weight
  infile >> ws;
  if (countColumns(infile) != 7)
    handle.logFileMessage(LOGFAIL, "wrong number of columns in inputfile - should be 7");

  year = step = area = age = count = reject = 0;
  while (!infile.eof()) {
    //crude check to see if something has gone wrong and avoid infinite loops
    if (!(isdigit(infile.peek())))
      handle.logFileMessage(LOGFAIL, "failed to read data from file");

    keepdata = 1;
    infile >> year >> step >> area >> age >> length >> ws;

    if (!(TimeInfo->isWithinPeriod(year, step)))
      keepdata = 0;

    if (!(this->isInArea(Area->getInnerArea(area))))
      keepdata = 0;

    if ((age < minage) || (age > maxage))
      keepdata = 0;

    lengthid = -1;
    for (i = 0; i < numlen; i++)
      if (isEqual(length, LgrpDiv->minLength(i)))
        lengthid = i;

    //OK the length doesnt match a minimum length so find the length group it is in
    if ((lengthid == -1) && (length > LgrpDiv->minLength()) && (length < LgrpDiv->maxLength())) {
      for (i = 1; i < numlen; i++) {
        if (length < LgrpDiv->minLength(i)) {
          lengthid = i - 1;
          break;
        }
      }
      if (lengthid == -1)
        lengthid = numlen - 1;  //then this must be the last length group
    }

    if (lengthid == -1)
      keepdata = 0;

    if (keepdata == 1) {
      //renewal data is required, so store it
      id = -1;
      for (i = 0; i < renewalTime.Size(); i++)
        if ((renewalTime[i] == TimeInfo->calcSteps(year, step))
            && (renewalArea[i] == Area->getInnerArea(area))
            && (renewalAge[i] == age))
          id = i;

      if (id == -1) {
        //this is a new timestep/area combination
        renewalTime.resize(1, TimeInfo->calcSteps(year, step));
        renewalArea.resize(1, Area->getInnerArea(area));
        renewalAge.resize(1, age);
        id = renewalTime.Size() - 1;

        renewalDistribution.resize(1, new AgeBandMatrix(age, poptmp));
        renewalNumber.resize(new FormulaMatrix(maxage - minage + 1, numlen, 0.0));
      }

      renewalDistribution[id][age][lengthid].N = 0.0;
      infile >> (*renewalNumber[id])[age - minage][lengthid] >> ws;
      infile >> renewalDistribution[id][age][lengthid].W >> ws;
      count++;

    } else { //renewal data not required - skip rest of line
      reject++;
      infile.get(c);
      while (c != '\n' && !infile.eof())
        infile.get(c);
      infile >> ws;
    }
  }

  for (i = 0; i < renewalNumber.Size(); i++)
    (*renewalNumber[i]).Inform(keeper);

  if (count == 0)
    handle.logMessage(LOGWARN, "Warning in renewal - found no data in the data file");
  if (reject != 0)
    handle.logMessage(LOGMESSAGE, "Discarded invalid renewal data - number of invalid entries", reject);
  handle.logMessage(LOGMESSAGE, "Read renewal data file - number of entries", count);
}

RenewalData::~RenewalData() {
  int i;
  delete LgrpDiv;
  delete CI;
  for (i = 0; i < renewalNumber.Size(); i++)
    delete renewalNumber[i];
}

void RenewalData::setCI(const LengthGroupDivision* const GivenLDiv) {
  if (!checkLengthGroupStructure(GivenLDiv, LgrpDiv))
    handle.logMessage(LOGFAIL, "Error in renewal - invalid length group structure for stock", this->getName());
  //check minimum and maximum lengths
  if (LgrpDiv->minLength() < GivenLDiv->minLength())
    handle.logMessage(LOGWARN, "Warning in renewal - minimum length less than stock length for stock", this->getName());
  if (LgrpDiv->maxLength() > GivenLDiv->maxLength())
    handle.logMessage(LOGWARN, "Warning in renewal - maximum length greater than stock length for stock", this->getName());
  CI = new ConversionIndex(LgrpDiv, GivenLDiv);
  if (CI->Error())
    handle.logMessage(LOGFAIL, "Error in renewal - error when checking length structure");
}

void RenewalData::Print(ofstream& outfile) const {
  int i;
  outfile << "\nRenewal data\n\t";
  LgrpDiv->Print(outfile);
  //need to find all areas and ages for current index value ...
  for (i = 0; i < renewalTime.Size(); i++) {
    if (renewalTime[i] == renewalTime[index]) {
      outfile << "\tInternal area " << renewalArea[i] << " age " << renewalAge[i];

      if (readoption == 2)
        outfile << "\n\tNumbers\n";
      else
        outfile << " multiplier " << renewalMult[i] << "\n\tNumbers\n";

      renewalDistribution[i].printNumbers(outfile);
      outfile << "\tMean weights\n";
      renewalDistribution[i].printWeights(outfile);
    }
  }
  outfile.flush();
}

void RenewalData::Reset() {
  int i, age, l, minage;
  double sum, mult, dnorm;

  index = 0;
  if (readoption == 0) {
    for (i = 0; i < renewalTime.Size(); i++) {
      age = renewalAge[i];

      //JMB check that the length data is valid
      if (isZero(meanLength[i]) || sdevLength[i] < 0.04) {
        //JMB the limit has been set at 0.04 to keep the exponential calculation sane
        handle.logMessage(LOGWARN, "Warning in renewal - invalid length data");

        //JMB set the population to zero
        for (l = renewalDistribution[i].minLength(age); l < renewalDistribution[i].maxLength(age); l++)
          renewalDistribution[i][age][l].setToZero();

      } else {
        //JMB check that the mean length is within the length group range
        if (meanLength[i] < LgrpDiv->minLength())
          handle.logMessage(LOGWARN, "Warning in renewal - mean length is less than minimum length for stock", this->getName());
        if (meanLength[i] > LgrpDiv->maxLength())
          handle.logMessage(LOGWARN, "Warning in renewal - mean length is greater than maximum length for stock", this->getName());

        sum = 0.0;
        mult = 1.0 / sdevLength[i];
        for (l = renewalDistribution[i].minLength(age); l < renewalDistribution[i].maxLength(age); l++) {
          dnorm = (LgrpDiv->meanLength(l) - meanLength[i]) * mult;
          renewalDistribution[i][age][l].N = exp(-(dnorm * dnorm) * 0.5);
          sum += renewalDistribution[i][age][l].N;
        }

        if (isZero(sum)) {
          handle.logMessage(LOGWARN, "Warning in renewal - calculated zero recruits for stock", this->getName());
          for (l = renewalDistribution[i].minLength(age); l < renewalDistribution[i].maxLength(age); l++)
            renewalDistribution[i][age][l].setToZero();

        } else {
          sum = 10000.0 / sum;
          for (l = renewalDistribution[i].minLength(age); l < renewalDistribution[i].maxLength(age); l++) {
            renewalDistribution[i][age][l].N *= sum;
            renewalDistribution[i][age][l].W = refWeight[l] * relCond[i];
            if ((handle.getLogLevel() >= LOGWARN) && (isZero(renewalDistribution[i][age][l].W)) && (renewalDistribution[i][age][l].N > 0.0))
              handle.logMessage(LOGWARN, "Warning in renewal - zero mean weight for stock", this->getName());
          }
        }
      }
    }

  } else if (readoption == 1) {
    for (i = 0; i < renewalTime.Size(); i++) {
      age = renewalAge[i];

      //JMB check that the length data is valid
      if (isZero(meanLength[i]) || sdevLength[i] < 0.04) {
        //JMB the limit has been set at 0.04 to keep the exponential calculation sane
        handle.logMessage(LOGWARN, "Warning in renewal - invalid length data");

        //JMB set the population to zero
        for (l = renewalDistribution[i].minLength(age); l < renewalDistribution[i].maxLength(age); l++)
          renewalDistribution[i][age][l].setToZero();

      } else {
        //JMB check that the mean length is within the length group range
        if (meanLength[i] < LgrpDiv->minLength())
          handle.logMessage(LOGWARN, "Warning in renewal - mean length is less than minimum length for stock", this->getName());
        if (meanLength[i] > LgrpDiv->maxLength())
          handle.logMessage(LOGWARN, "Warning in renewal - mean length is greater than maximum length for stock", this->getName());

        sum = 0.0;
        mult = 1.0 / sdevLength[i];
        for (l = renewalDistribution[i].minLength(age); l < renewalDistribution[i].maxLength(age); l++) {
          dnorm = (LgrpDiv->meanLength(l) - meanLength[i]) * mult;
          renewalDistribution[i][age][l].N = exp(-(dnorm * dnorm) * 0.5);
          sum += renewalDistribution[i][age][l].N;
        }

        if (isZero(sum)) {
          handle.logMessage(LOGWARN, "Warning in renewal - calculated zero recruits for stock", this->getName());
          for (l = renewalDistribution[i].minLength(age); l < renewalDistribution[i].maxLength(age); l++)
            renewalDistribution[i][age][l].setToZero();

        } else {
          sum = 10000.0 / sum;
          for (l = renewalDistribution[i].minLength(age); l < renewalDistribution[i].maxLength(age); l++) {
            renewalDistribution[i][age][l].N *= sum;
            renewalDistribution[i][age][l].W = alpha[i] * pow(LgrpDiv->meanLength(l), beta[i]);
            if ((handle.getLogLevel() >= LOGWARN) && (isZero(renewalDistribution[i][age][l].W)) && (renewalDistribution[i][age][l].N > 0.0))
              handle.logMessage(LOGWARN, "Warning in renewal - zero mean weight for stock", this->getName());
          }
        }
      }
    }

  } else if (readoption == 2) {
    for (i = 0; i < renewalTime.Size(); i++) {
      age = renewalAge[i];
      minage = renewalDistribution[i].minAge();
      for (l = renewalDistribution[i].minLength(age); l < renewalDistribution[i].maxLength(age); l++) {
        renewalDistribution[i][age][l].N = (*renewalNumber[i])[age - minage][l];
        if (handle.getLogLevel() >= LOGWARN) {
          if (renewalDistribution[i][age][l].N < 0.0)
            handle.logMessage(LOGWARN, "Warning in renewal - negative number of recruits", renewalDistribution[i][age][l].N);
          if ((isZero(renewalDistribution[i][age][l].W)) && (renewalDistribution[i][age][l].N > 0.0))
            handle.logMessage(LOGWARN, "Warning in renewal - zero mean weight for stock", this->getName());
        }
      }
    }

  } else
    handle.logMessage(LOGFAIL, "Error in renewal - unrecognised data format");

  if (handle.getLogLevel() >= LOGMESSAGE)
    handle.logMessage(LOGMESSAGE, "Reset renewal data for stock", this->getName());
}

int RenewalData::isRenewalStepArea(int area, const TimeClass* const TimeInfo) {
  int i;
  for (i = 0; i < renewalTime.Size(); i++)
    if ((renewalTime[i] == TimeInfo->getTime()) && (renewalArea[i] == area))
      return 1;
  return 0;
}

void RenewalData::addRenewal(AgeBandMatrix& Alkeys, int area, const TimeClass* const TimeInfo) {
  int i;
  for (i = 0; i < renewalTime.Size(); i++) {
    if ((renewalTime[i] == TimeInfo->getTime()) && (renewalArea[i] == area)) {
      index = i;
      if (readoption == 2)
        Alkeys.Add(renewalDistribution[i], *CI);
      else if (renewalMult[i] > verysmall)
        Alkeys.Add(renewalDistribution[i], *CI, renewalMult[i]);
    }
  }
}

root@forge.cesga.es
ViewVC Help
Powered by ViewVC 1.0.0  

Powered By FusionForge