////////////////////////////////////////////////////////////////////////////
// DoSetup
////////////////////////////////////////////////////////////////////////////
void clSizeEffectPowerFunction::DoSetup(clTreePopulation *p_oPop, clBehaviorBase *p_oNCI, xercesc::DOMElement *p_oElement) {
  doubleVal * p_fTempValues; //for getting species-specific values
  int iNumBehaviorSpecies = p_oNCI->GetNumBehaviorSpecies(),
      iNumTotalSpecies = p_oPop->GetNumberOfSpecies(), i;

  mp_fA = new double[iNumTotalSpecies];
  mp_fB = new double[iNumTotalSpecies];

  //Set up our doubleVal array that will extract values only for the species
  //assigned to this behavior
  p_fTempValues = new doubleVal[iNumBehaviorSpecies];
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    p_fTempValues[i].code = p_oNCI->GetBehaviorSpecies(i);

  //Size effect a
  FillSpeciesSpecificValue( p_oElement, "nciSizeEffectA", "nseaVal",
      p_fTempValues, iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fA[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Size effect b
  FillSpeciesSpecificValue( p_oElement, "nciSizeEffectB", "nsebVal",
      p_fTempValues, iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fB[p_fTempValues[i].code] = p_fTempValues[i].val;

  delete[] p_fTempValues;
}
//////////////////////////////////////////////////////////////////////////////
// DoSetup
//////////////////////////////////////////////////////////////////////////////
void clCrowdingEffectTempDep::DoSetup(clTreePopulation *p_oPop, clBehaviorBase *p_oNCI, clNCIBehaviorBase *p_oNCIBase, xercesc::DOMElement *p_oElement) {
  doubleVal * p_fTempValues; //for getting species-specific values
  int iNumBehaviorSpecies = p_oNCI->GetNumBehaviorSpecies(),
      iNumTotalSpecies = p_oPop->GetNumberOfSpecies(), i;

  //Find out how many NCI terms
  clNCITermBase *p_oNCITerm = p_oNCIBase->GetNCITerm();
  if (p_oNCITerm->GetNumberNCIs() == 2) m_b2ValNCI = true;

  //Get a pointer to the plot object
  mp_oPlot = p_oNCI->GetSimManager()->GetPlotObject();

  mp_fC = new double[iNumTotalSpecies];
  mp_fX0 = new double[iNumTotalSpecies];
  mp_fXb = new double[iNumTotalSpecies];
  mp_fD = new double[iNumTotalSpecies];
  mp_fGamma = new double[iNumTotalSpecies];

  //Set up our doubleVal array that will extract values only for the species
  //assigned to this behavior
  p_fTempValues = new doubleVal[iNumBehaviorSpecies];
  for ( i = 0; i < iNumBehaviorSpecies; i++ ) p_fTempValues[i].code = p_oNCI->GetBehaviorSpecies(i);

  //Size sensitivity to NCI parameter (gamma)
  FillSpeciesSpecificValue( p_oElement, "nciCrowdingGamma", "ncgVal", p_fTempValues,
      iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fGamma[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Crowding Slope (C)
  FillSpeciesSpecificValue( p_oElement, "nciCrowdingC", "nccVal", p_fTempValues,
      iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fC[p_fTempValues[i].code] = p_fTempValues[i].val;

  //X0
  FillSpeciesSpecificValue( p_oElement, "nciCrowdingCX0", "nccx0Val", p_fTempValues,
      iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fX0[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Xb
  FillSpeciesSpecificValue( p_oElement, "nciCrowdingCXb", "nccxbVal", p_fTempValues,
      iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fXb[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Crowding Steepness (D)
  FillSpeciesSpecificValue( p_oElement, "nciCrowdingD", "ncdVal", p_fTempValues,
      iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fD[p_fTempValues[i].code] = p_fTempValues[i].val;

  delete[] p_fTempValues;
}
////////////////////////////////////////////////////////////////////////////
// ReadParameterFileData()
////////////////////////////////////////////////////////////////////////////
void clResourceMortality::ReadParameterFileData( xercesc::DOMDocument * p_oDoc )
{
  clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
  DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
  floatVal * p_fTempValues; //for getting species-specific values
  short int i; //loop counter

  //Declare the temp array and populate it with the species to which this
  //behavior applies
  p_fTempValues = new floatVal[m_iNumBehaviorSpecies];
  for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
    p_fTempValues[i].code = mp_iWhatSpecies[i];

  //Declare the index array and populate it
  mp_iIndexes = new short int[p_oPop->GetNumberOfSpecies()];

  //Make the list of indexes
  for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
    mp_iIndexes[mp_iWhatSpecies[i]] = i;

  //Declare the arrays for holding the variables
  mp_fRho = new float[m_iNumBehaviorSpecies];
  mp_fMu = new float[m_iNumBehaviorSpecies];
  mp_fDelta = new float[m_iNumBehaviorSpecies];
  mp_fSigma = new float[m_iNumBehaviorSpecies];

  //Capture the values from the parameter file

  //Scaling factor (rho)
  FillSpeciesSpecificValue( p_oElement, "mo_resMortScalingFactor", "mo_rmsfVal", p_fTempValues,
       m_iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
    mp_fRho[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

  //Function mode (mu)
  FillSpeciesSpecificValue( p_oElement, "mo_resMortMode", "mo_rmmVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
    mp_fMu[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

  //Growth increase in survival (delta)
  FillSpeciesSpecificValue( p_oElement, "mo_resMortGrowthIncSurv", "mo_rmgisVal", p_fTempValues,
       m_iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
    mp_fDelta[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

  //Low growth function shape (sigma)
  FillSpeciesSpecificValue( p_oElement, "mo_resMortLoGrowthShape", "mo_rmlgsVal", p_fTempValues,
       m_iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
    mp_fSigma[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;


  delete[] p_fTempValues; p_fTempValues = NULL;
}
////////////////////////////////////////////////////////////////////////////
// DoSetup
////////////////////////////////////////////////////////////////////////////
void clSizeEffectLowerBounded::DoSetup(clTreePopulation *p_oPop, clBehaviorBase *p_oNCI, xercesc::DOMElement *p_oElement) {
  doubleVal * p_dTempValues; //for getting species-specific values
  int iNumBehaviorSpecies = p_oNCI->GetNumBehaviorSpecies(),
      iNumTotalSpecies = p_oPop->GetNumberOfSpecies(), i;

  mp_fX0 = new double[iNumTotalSpecies];
  mp_fXb = new double[iNumTotalSpecies];
  mp_fMinDiam = new double[iNumTotalSpecies];

  //Set up our doubleVal array that will extract values only for the species
  //assigned to this behavior
  p_dTempValues = new doubleVal[iNumBehaviorSpecies];
  for ( i = 0; i < iNumBehaviorSpecies; i++ ) p_dTempValues[i].code = p_oNCI->GetBehaviorSpecies(i);

  //Size effect mode (X0)
  FillSpeciesSpecificValue( p_oElement, "nciSizeEffectX0", "nsex0Val",
      p_dTempValues, iNumBehaviorSpecies, p_oPop, true);
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fX0[p_dTempValues[i].code] = p_dTempValues[i].val;

  //Size effect variance (Xb)
  FillSpeciesSpecificValue(p_oElement, "nciSizeEffectXb", "nsexbVal",
      p_dTempValues, iNumBehaviorSpecies, p_oPop, true);
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++)
    mp_fXb[p_dTempValues[i].code] = p_dTempValues[i].val;

  //Size effect lower bound
  FillSpeciesSpecificValue(p_oElement, "nciSizeEffectLowerBound", "nselbVal",
      p_dTempValues, iNumBehaviorSpecies, p_oPop, true);
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++)
    mp_fMinDiam[p_dTempValues[i].code] = p_dTempValues[i].val;

  delete[] p_dTempValues;

  //Make sure that the size effect mode is not 0
  for ( i = 0; i < iNumBehaviorSpecies; i++) {
    if (0 >= mp_fX0[p_oNCI->GetBehaviorSpecies(i)]) {
      modelErr stcErr;
      stcErr.iErrorCode = BAD_DATA;
      stcErr.sFunction = "clSizeEffectLowerBounded::DoSetup";
      stcErr.sMoreInfo = "NCI size effect mode (X0) values must be greater than 0.";
      throw( stcErr );
    }

    //Make sure that the size effect variance is not 0
    if (0 == mp_fXb[p_oNCI->GetBehaviorSpecies(i)]) {
      modelErr stcErr;
      stcErr.iErrorCode = BAD_DATA;
      stcErr.sFunction = "clSizeEffectLowerBounded::DoSetup";
      stcErr.sMoreInfo = "NCI size effect variance (Xb) values cannot be 0.";
      throw( stcErr );
    }
  }
}
//////////////////////////////////////////////////////////////////////////////
// DoSetup
//////////////////////////////////////////////////////////////////////////////
void clNCILargerNeighbors::DoSetup(clTreePopulation *p_oPop, clBehaviorBase *p_oNCI, xercesc::DOMElement *p_oElement) {
  doubleVal * p_fTempValues; //for getting species-specific values
  int iNumBehaviorSpecies = p_oNCI->GetNumBehaviorSpecies(),
      iNumTotalSpecies = p_oPop->GetNumberOfSpecies(), i;

  mp_fMinimumNeighborDBH = new double[iNumTotalSpecies];
  mp_fMaxCrowdingRadius = new double[iNumTotalSpecies];

  m_fMinSaplingHeight = 50;

  p_fTempValues = new doubleVal[iNumBehaviorSpecies];
  for ( i = 0; i < iNumBehaviorSpecies; i++ ) {
    p_fTempValues[i].code = p_oNCI->GetBehaviorSpecies(i);
  }

  //Get the minimum sapling height
  for (i = 0; i < iNumTotalSpecies; i++) {
    if (p_oPop->GetMaxSeedlingHeight( i ) < m_fMinSaplingHeight ) {
      m_fMinSaplingHeight = p_oPop->GetMaxSeedlingHeight( i );
    }
  }

  //Max crowding radius
  FillSpeciesSpecificValue( p_oElement, "nciMaxCrowdingRadius", "nmcrVal", p_fTempValues,
      iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fMaxCrowdingRadius[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Minimum neighbor DBH
  FillSpeciesSpecificValue( p_oElement, "nciMinNeighborDBH", "nmndVal",
      mp_fMinimumNeighborDBH, p_oPop, true);

  delete[] p_fTempValues;

  //Make sure that the max radius of neighbor effects is > 0
  for ( i = 0; i < iNumBehaviorSpecies; i++) {
    if (mp_fMaxCrowdingRadius[p_oNCI->GetBehaviorSpecies(i)] < 0) {
      modelErr stcErr;
      stcErr.iErrorCode = BAD_DATA;
      stcErr.sFunction = "clNCILargerNeighbors::DoSetup";
      stcErr.sMoreInfo = "All values for NCI max crowding radius must be greater than 0.";
      throw( stcErr );
    }
  }
  for (i = 0; i < iNumTotalSpecies; i++) {
    //Make sure that the minimum neighbor DBH is not negative
    if (0 > mp_fMinimumNeighborDBH[i]) {
      modelErr stcErr;
      stcErr.iErrorCode = BAD_DATA;
      stcErr.sFunction = "clNCILargerNeighbors::DoSetup";
      stcErr.sMoreInfo = "Minimum neighbor DBH for NCI cannot be less than 0.";
      throw( stcErr );
    }
  }
}
//////////////////////////////////////////////////////////////////////////////
// DoSetup
//////////////////////////////////////////////////////////////////////////////
void clInfectionEffect::DoSetup(clTreePopulation *p_oPop, clBehaviorBase *p_oNCI, xercesc::DOMElement *p_oElement) {

  floatVal * p_fTempValues; //for getting species-specific values
  stcSpeciesTypeCombo c;
  int iNumBehaviorSpecies = p_oNCI->GetNumBehaviorSpecies(),
      iNumTypes = p_oPop->GetNumberOfTypes(), i, j;

  m_iTotalNumSpecies = p_oPop->GetNumberOfSpecies();

  mp_fA = new float[m_iTotalNumSpecies];
  mp_fB = new float[m_iTotalNumSpecies];

  p_fTempValues = new floatVal[iNumBehaviorSpecies];
  for ( i = 0; i < iNumBehaviorSpecies; i++ ) {
    p_fTempValues[i].code = p_oNCI->GetBehaviorSpecies(i);
  }

  //a
  FillSpeciesSpecificValue( p_oElement, "nciInfectionEffectA", "nieaVal", p_fTempValues,
      iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fA[p_fTempValues[i].code] = p_fTempValues[i].val;

  //b
  FillSpeciesSpecificValue( p_oElement, "nciInfectionEffectB", "niebVal", p_fTempValues,
      iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fB[p_fTempValues[i].code] = p_fTempValues[i].val;

  delete[] p_fTempValues;

  //Get the "Years Infested" data member
  mp_iYearsInfestedCodes = new short int * [m_iTotalNumSpecies];
  for ( i = 0; i < m_iTotalNumSpecies; i++ ) {
    mp_iYearsInfestedCodes[i] = new short int[iNumTypes];
    for (j = 0; j < iNumTypes; j++) {
      mp_iYearsInfestedCodes[i][j] = -1;
    }
  }
  for (i = 0; i < p_oNCI->GetNumSpeciesTypeCombos(); i++) {
    c = p_oNCI->GetSpeciesTypeCombo(i);
    mp_iYearsInfestedCodes[c.iSpecies][c.iType] =
        p_oPop->GetIntDataCode("YearsInfested", c.iSpecies, c.iType);
    if (-1 == mp_iYearsInfestedCodes[c.iSpecies][c.iType]) {
      modelErr stcErr;
      stcErr.iErrorCode = BAD_DATA;
      stcErr.sFunction = "clInfectionEffect::DoSetup";
      stcErr.sMoreInfo = "An infestation behavior must be applied to all trees to which NCI infection effect is applied.";
      throw( stcErr );
    }
  }
}
//---------------------------------------------------------------------------
// PowerHeightGrowth.cpp
//---------------------------------------------------------------------------
#include "PowerHeightGrowth.h"
#include "TreePopulation.h"
#include "SimManager.h"
#include "ParsingFunctions.h"
#include "GrowthOrg.h"
#include <math.h>

//////////////////////////////////////////////////////////////////////////////
// Constructor
/////////////////////////////////////////////////////////////////////////////*/
clPowerHeightGrowth::clPowerHeightGrowth(clSimManager * p_oSimManager) :
  clWorkerBase(p_oSimManager), clBehaviorBase(p_oSimManager), clGrowthBase(
      p_oSimManager) {

  try {
    mp_fN = NULL;
    mp_fB = NULL;

    m_iGrowthMethod = height_only;
    m_iNumberYearsPerTimestep = 0;

    m_sNameString = "powergrowthshell";
    m_sXMLRoot = "PowerGrowth";

  } catch (modelErr& err) {
    throw(err);
  } catch (modelMsg & msg) {
    throw(msg);
  } //non-fatal error
  catch (...) {
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clPowerHeightGrowth::clPowerHeightGrowth";
    throw(stcErr);
  }
}

//////////////////////////////////////////////////////////////////////////////
// Destructor
/////////////////////////////////////////////////////////////////////////////*/
clPowerHeightGrowth::~clPowerHeightGrowth() {

  delete[] mp_fN;
  delete[] mp_fB;
}

//////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
/////////////////////////////////////////////////////////////////////////////*/
void clPowerHeightGrowth::DoShellSetup(DOMDocument * p_oDoc) {
  doubleVal * p_fTempValues = NULL; //for getting species-specific values
  try {
    clTreePopulation * p_oPop =
        (clTreePopulation *) mp_oSimManager->GetPopulationObject(
            "treepopulation");
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    short int iNumSpecies = p_oPop->GetNumberOfSpecies(), i;

    //Declare the arrays we'd like read
    mp_fB = new double[iNumSpecies];
    mp_fN = new double[iNumSpecies];

    //Declare the species-specific temp array and pre-load with the species that
    //this behavior affects
    p_fTempValues = new doubleVal[m_iNumBehaviorSpecies];
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    //N
    FillSpeciesSpecificValue(p_oElement, "gr_powerHeightN", "gr_phnVal",
        p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true);

    //Transfer values to our permanent array
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_fN[p_fTempValues[i].code] = p_fTempValues[i].val;

    //B
    FillSpeciesSpecificValue(p_oElement, "gr_powerHeightExp", "gr_pheVal",
        p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true);

    //Transfer values to our permanent array
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_fB[p_fTempValues[i].code] = p_fTempValues[i].val;

    m_iNumberYearsPerTimestep = mp_oSimManager->GetNumberOfYearsPerTimestep();

    delete[] p_fTempValues;
  } catch (modelErr& err) {
    delete[] p_fTempValues;
    throw(err);
  } catch (modelMsg & msg) {
    delete[] p_fTempValues;
    throw(msg);
  } //non-fatal error
  catch (...) {
    delete[] p_fTempValues;
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clPowerHeightGrowth::GetNameData";
    throw(stcErr);
  }
}
//////////////////////////////////////////////////////////////////////////////
// DoSetup
//////////////////////////////////////////////////////////////////////////////
void clShadingEffectDefault::DoSetup(clTreePopulation *p_oPop, clBehaviorBase *p_oNCI, xercesc::DOMElement *p_oElement) {
  stcSpeciesTypeCombo c;
  doubleVal * p_fTempValues; //for getting species-specific values
  int iNumBehaviorSpecies = p_oNCI->GetNumBehaviorSpecies(),
      iNumTypes = p_oPop->GetNumberOfTypes(),
      i, j;

  m_iNumberTotalSpecies = p_oPop->GetNumberOfSpecies();
  mp_fShadingCoefficient = new double[m_iNumberTotalSpecies];
  mp_fShadingExponent = new double[m_iNumberTotalSpecies];

  //Set up our doubleVal array that will extract values only for the species
  //assigned to this behavior
  p_fTempValues = new doubleVal[iNumBehaviorSpecies];
  for ( i = 0; i < iNumBehaviorSpecies; i++ ) p_fTempValues[i].code = p_oNCI->GetBehaviorSpecies(i);

  //Shading coefficient (m)
  FillSpeciesSpecificValue( p_oElement, "nciShadingCoefficient", "nscVal", p_fTempValues,
      iNumBehaviorSpecies, p_oPop, true);
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fShadingCoefficient[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Shading exponent (n)
  FillSpeciesSpecificValue( p_oElement, "nciShadingExponent", "nseVal", p_fTempValues,
      iNumBehaviorSpecies, p_oPop, true);
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fShadingExponent[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Declare the light codes array
  mp_iLightCodes = new short int *[m_iNumberTotalSpecies];
  for (i = 0; i < m_iNumberTotalSpecies; i++) {
    mp_iLightCodes[i] = new short int[iNumTypes];
    for (j = 0; j < iNumTypes; j++) mp_iLightCodes[i][j] = -1;
  }

  delete[] p_fTempValues;

  //Make sure all species/type combos that use shading have "Light" registered
  for (i = 0; i < p_oNCI->GetNumSpeciesTypeCombos(); i++) {
    c = p_oNCI->GetSpeciesTypeCombo(i);
    mp_iLightCodes[c.iSpecies][c.iType] = p_oPop->GetFloatDataCode("Light", c.iSpecies, c.iType);

    if ( -1 == mp_iLightCodes[c.iSpecies][c.iType]) {
      modelErr stcErr;
      stcErr.sFunction = "clShadingEffectDefault::DoSetup";
      stcErr.sMoreInfo = "All trees to which the shading effect of NCI is used must have a light behavior applied.";
      stcErr.iErrorCode = BAD_DATA;
      throw( stcErr );
    }
  }
}
////////////////////////////////////////////////////////////////////////////
// DoSetup
////////////////////////////////////////////////////////////////////////////
void clTemperatureEffectWeibull::DoSetup(clTreePopulation *p_oPop, clBehaviorBase *p_oNCI, xercesc::DOMElement *p_oElement) {
  doubleVal * p_fTempValues; //for getting species-specific values
  int iNumBehaviorSpecies = p_oNCI->GetNumBehaviorSpecies(),
      iNumTotalSpecies = p_oPop->GetNumberOfSpecies(), i;

  mp_fTempA = new double[iNumTotalSpecies];
  mp_fTempB = new double[iNumTotalSpecies];
  mp_fTempC = new double[iNumTotalSpecies];

  //Set up our doubleVal array that will extract values only for the species
  //assigned to this behavior
  p_fTempValues = new doubleVal[iNumBehaviorSpecies];
  for ( i = 0; i < iNumBehaviorSpecies; i++ ) p_fTempValues[i].code = p_oNCI->GetBehaviorSpecies(i);

  //Temperature effect a
  FillSpeciesSpecificValue( p_oElement, "nciWeibTempEffA",
      "nwteaVal", p_fTempValues, iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fTempA[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Temperature effect b
  FillSpeciesSpecificValue( p_oElement, "nciWeibTempEffB",
      "nwtebVal", p_fTempValues, iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fTempB[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Temperature effect c
  FillSpeciesSpecificValue( p_oElement, "nciWeibTempEffC",
      "nwtecVal", p_fTempValues, iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fTempC[p_fTempValues[i].code] = p_fTempValues[i].val;

  delete[] p_fTempValues;

  //Make sure that the a value is not 0
  for ( i = 0; i < iNumBehaviorSpecies; i++) {
    if (0 == mp_fTempA[p_oNCI->GetBehaviorSpecies(i)]) {
      modelErr stcErr;
      stcErr.iErrorCode = BAD_DATA;
      stcErr.sFunction = "clTemperatureEffectWeibull::DoSetup";
      stcErr.sMoreInfo = "NCI temperature effect \"a\" values cannot be 0.";
      throw( stcErr );
    }
  }
}
/////////////////////////////////////////////////////////////////////////////
// GetParameterFileData()
/////////////////////////////////////////////////////////////////////////////
void clCarbonValueCalculator::GetParameterFileData( xercesc::DOMDocument * p_oDoc, clTreePopulation *p_oPop )
{
  doubleVal * p_fTempValues = NULL; //for getting species-specific values
  try {
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    int i;

    //Set up our doubleVal array that will extract values only for the species
    //assigned to this behavior
    p_fTempValues = new doubleVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    //Declare our array
    mp_fCPercentBiomass = new double[m_iNumTotalSpecies];

    //Get the parameter file values

    //Percent of biomass that is carbon
    FillSpeciesSpecificValue( p_oElement, "an_carbonPercentBiomassCarbon", "an_cpbcVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets, and
    //convert to proportion; check to make sure it's between 0 and 1
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      mp_fCPercentBiomass[p_fTempValues[i].code] = p_fTempValues[i].val / 100.0;
      if (mp_fCPercentBiomass[p_fTempValues[i].code] > 1 ||
          mp_fCPercentBiomass[p_fTempValues[i].code] < 0) {
        modelErr stcErr;
        stcErr.sFunction = "clCarbonValueCalculator::GetParameterFileData" ;
        stcErr.sMoreInfo = "Percent of biomass that is carbon must be between 0 and 100.";
        stcErr.iErrorCode = BAD_DATA;
        throw( stcErr );
      }
    }

    FillSingleValue( p_oElement, "an_carbonPricePerMetricTonCarbon", & m_fPricePerTonCarbon, true );

    delete[] p_fTempValues;
  }
  catch ( modelErr & err )
  {
    delete[] p_fTempValues;
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    delete[] p_fTempValues;
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    delete[] p_fTempValues;
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clCarbonValueCalculator::GetParameterFileData" ;
    throw( stcErr );
  }
}
//////////////////////////////////////////////////////////////////////////////
// DoSetup
//////////////////////////////////////////////////////////////////////////////
void clNitrogenEffectGaussian::DoSetup(clTreePopulation *p_oPop, clBehaviorBase *p_oNCI, xercesc::DOMElement *p_oElement) {
  doubleVal * p_fTempValues; //for getting species-specific values
  int iNumBehaviorSpecies = p_oNCI->GetNumBehaviorSpecies(),
      iNumTotalSpecies = p_oPop->GetNumberOfSpecies(), i;

  mp_fX0 = new double[iNumTotalSpecies];
  mp_fXb = new double[iNumTotalSpecies];

  p_fTempValues = new doubleVal[iNumBehaviorSpecies];
  for ( i = 0; i < iNumBehaviorSpecies; i++ ) {
    p_fTempValues[i].code = p_oNCI->GetBehaviorSpecies(i);
  }

  //X0
  FillSpeciesSpecificValue( p_oElement, "nciNitrogenX0", "nnx0Val", p_fTempValues,
      iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fX0[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Xb
  FillSpeciesSpecificValue( p_oElement, "nciNitrogenXb", "nnxbVal", p_fTempValues,
      iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fXb[p_fTempValues[i].code] = p_fTempValues[i].val;

  delete[] p_fTempValues;

  //Make sure that the size effect variance is not 0
  for ( i = 0; i < iNumBehaviorSpecies; i++ ) {
    if (0 == mp_fXb[p_oNCI->GetBehaviorSpecies(i)]) {
      modelErr stcErr;
      stcErr.iErrorCode = BAD_DATA;
      stcErr.sFunction = "clGaussianNitrogenEffect::DoSetup";
      stcErr.sMoreInfo = "NCI Nitrogen Xb values cannot be 0.";
      throw( stcErr );
    }
  }
}
////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
////////////////////////////////////////////////////////////////////////////
void clStochasticMort::DoShellSetup(xercesc::DOMDocument *p_oDoc) {
 try {
   clTreePopulation *p_oPop = (clTreePopulation*) mp_oSimManager->GetPopulationObject("treepopulation");
   DOMElement *p_oElement = GetParentParametersElement(p_oDoc);
   floatVal *p_fTempValues;  //for getting species-specific values
   float fNumberYearsPerTimestep = mp_oSimManager->GetNumberOfYearsPerTimestep();
   short int iNumSpecies = mp_oMortalityOrg->GetNumberOfSpecies(),
             i; //loop counter

   //Declare the temp array and populate it with the species to which this
   //behavior applies
   p_fTempValues = new floatVal[m_iNumBehaviorSpecies];
   for (i = 0; i < m_iNumBehaviorSpecies; i++)
     p_fTempValues[i].code = mp_iWhatSpecies[i];

   //Declare the arrays for holding the variables
   mp_fRandomMort = new float[iNumSpecies];

   //Capture the values from the parameter file

   //Random mortality
   FillSpeciesSpecificValue(p_oElement, "mo_stochasticMortRate",
               "mo_smrVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true);
   //Transfer to the appropriate array buckets and compound by the number
   //of years per timestep
   for (i = 0; i < m_iNumBehaviorSpecies; i++) {
     mp_fRandomMort[p_fTempValues[i].code] = 1 - pow(1 - p_fTempValues[i].val, fNumberYearsPerTimestep);
   }

   delete[] p_fTempValues;
 }
 catch (modelErr&err) {throw(err);}
 catch (modelMsg &msg) {throw(msg);} //non-fatal error
 catch (...) {
   modelErr stcErr;
   stcErr.iErrorCode = UNKNOWN;
   stcErr.sFunction = "clStochasticMort::DoShellSetup";
   throw(stcErr);
 }
}
////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
////////////////////////////////////////////////////////////////////////////
void clBrowsedStochasticMortality::DoShellSetup( xercesc::DOMDocument * p_oDoc )
{
  floatVal * p_fTempValues = NULL; //for getting species-specific values
  try
  {
    clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    float fYearsPerTimestep = mp_oSimManager->GetNumberOfYearsPerTimestep();
    short int i, j, iNumTypes = p_oPop->GetNumberOfTypes();

    m_iNumSpecies = p_oPop->GetNumberOfSpecies();

    //Declare the arrays we'd like read
    mp_fBrowsedMortProb = new float[m_iNumSpecies];
    mp_fUnbrowsedMortProb = new float[m_iNumSpecies];

    //Declare the species-specific temp array and pre-load with the species
    //that this behavior affects
    p_fTempValues = new floatVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    //Browsed mortality probability
    FillSpeciesSpecificValue( p_oElement, "mo_browsedRandomMortality", "mo_brmVal", p_fTempValues,
        m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array, making sure all values are
    //between 0 and 1 and translating to a timestep probability
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
    {
      if ( 0 > p_fTempValues[i].val || 1 < p_fTempValues[i].val )
      {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clBrowsedStochasticMortality::DoShellSetup" ;
        stcErr.sMoreInfo = "All values for probability of mortality must be between 0 and 1.";
        throw( stcErr );
      }
      mp_fBrowsedMortProb[p_fTempValues[i].code] = 1 - pow( 1 - p_fTempValues[i].val, fYearsPerTimestep );
    }

    //Unbrowsed mortality probability
    FillSpeciesSpecificValue( p_oElement, "mo_stochasticMortRate", "mo_smrVal", p_fTempValues,
        m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array, making sure all values are
    //between 0 and 1 and translating to a timestep probability
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
    {
      if ( 0 > p_fTempValues[i].val || 1 < p_fTempValues[i].val )
      {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clBrowsedStochasticMortality::DoShellSetup" ;
        stcErr.sMoreInfo = "All values for probability of mortality must be between 0 and 1.";
        throw( stcErr );
      }
      mp_fUnbrowsedMortProb[p_fTempValues[i].code] = 1 - pow( 1 - p_fTempValues[i].val, fYearsPerTimestep );
    }

    //Collect the "Browsed" codes
    mp_iBrowsedCodes = new short int *[m_iNumSpecies];
    for (i = 0; i < m_iNumSpecies; i++) {
      mp_iBrowsedCodes[i] = new short int[iNumTypes];
      for (j = 0; j < iNumTypes; j++) {
        mp_iBrowsedCodes[i][j] = -1;
      }
    }
    for (i = 0; i < m_iNumSpeciesTypeCombos; i++ )
    {
      mp_iBrowsedCodes[mp_whatSpeciesTypeCombos[i].iSpecies]
                       [mp_whatSpeciesTypeCombos[i].iType] =
                           p_oPop->GetBoolDataCode("Browsed",
                               mp_whatSpeciesTypeCombos[i].iSpecies,
                               mp_whatSpeciesTypeCombos[i].iType );
      if (-1 == mp_iBrowsedCodes[mp_whatSpeciesTypeCombos[i].iSpecies]
                                 [mp_whatSpeciesTypeCombos[i].iType] )
      {
        modelErr stcErr;
        stcErr.sFunction = "clBrowsedStochasticMortality::DoShellSetup" ;
        std::stringstream s;
        s << "Type/species combo species="
            << mp_whatSpeciesTypeCombos[i].iSpecies << " type="
            << mp_whatSpeciesTypeCombos[i].iType
            << " does not have the browse behavior.";
        stcErr.sMoreInfo = s.str();
        stcErr.iErrorCode = BAD_DATA;
        throw( stcErr );
      }
    }

    delete[] p_fTempValues;
  }
  catch ( modelErr & err )
  {
    delete[] p_fTempValues;
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    delete[] p_fTempValues;
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    delete[] p_fTempValues;
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clBrowsedStochasticMortality::DoShellSetup" ;
    throw( stcErr );
  }
}
//---------------------------------------------------------------------------
// LogBiLevelGrowth.cpp
//---------------------------------------------------------------------------
#include "LogBiLevelGrowth.h"
#include "TreePopulation.h"
#include "SimManager.h"
#include "ParsingFunctions.h"
#include "Grid.h"
#include <math.h>

//////////////////////////////////////////////////////////////////////////////
// Constructor
/////////////////////////////////////////////////////////////////////////////*/
clLogBiLevelGrowth::clLogBiLevelGrowth( clSimManager * p_oSimManager ) :
  clWorkerBase( p_oSimManager ), clBehaviorBase( p_oSimManager ), clGrowthBase( p_oSimManager )
{

  try
  {

    m_iGrowthMethod = height_only;

    mp_oStormLight = NULL;
    mp_fLoLightMaxGrowth = NULL;
    mp_fLoLightX0 = NULL;
    mp_fLoLightXb = NULL;
    mp_fHiLightMaxGrowth = NULL;
    mp_fHiLightX0 = NULL;
    mp_fHiLightXb = NULL;
    mp_fHiLightThreshold = NULL;
    mp_iIndexes = NULL;

    m_iYearsPerTimestep = 0;
    m_iLightCode = -1;

    m_sNameString = "logbilevelgrowthshell";
    m_sXMLRoot = "LogBilevelGrowth";
  }
  catch ( modelErr & err )
  {
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clLogBiLevelGrowth::clLogBiLevelGrowth" ;
    throw( stcErr );
  }
}

//////////////////////////////////////////////////////////////////////////////
// Destructor
/////////////////////////////////////////////////////////////////////////////*/
clLogBiLevelGrowth::~clLogBiLevelGrowth()
{
  delete[] mp_fLoLightMaxGrowth;
  delete[] mp_fLoLightX0;
  delete[] mp_fLoLightXb;
  delete[] mp_fHiLightMaxGrowth;
  delete[] mp_fHiLightX0;
  delete[] mp_fHiLightXb;
  delete[] mp_fHiLightThreshold;
  delete[] mp_iIndexes;
}

//////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
/////////////////////////////////////////////////////////////////////////////*/
void clLogBiLevelGrowth::DoShellSetup( DOMDocument * p_oDoc )
{
  doubleVal * p_fTempValues = NULL; //for getting species-specific values
  try
  {
    clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    short int iNumSpecies = p_oPop->GetNumberOfSpecies(), i;

    //Get number of years per timestep
    m_iYearsPerTimestep = mp_oSimManager->GetNumberOfYearsPerTimestep();

    //Declare the arrays we'd like read
    mp_fLoLightMaxGrowth = new double[m_iNumBehaviorSpecies];
    mp_fLoLightX0 = new double[m_iNumBehaviorSpecies];
    mp_fLoLightXb = new double[m_iNumBehaviorSpecies];
    mp_fHiLightMaxGrowth = new double[m_iNumBehaviorSpecies];
    mp_fHiLightX0 = new double[m_iNumBehaviorSpecies];
    mp_fHiLightXb = new double[m_iNumBehaviorSpecies];
    mp_fHiLightThreshold = new double[m_iNumBehaviorSpecies];
    mp_iIndexes = new int[iNumSpecies];

    //Set up the array indexes
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_iIndexes[mp_iWhatSpecies[i]] = i;

    //See if we can find the storm light grid
    mp_oStormLight = mp_oSimManager->GetGridObject("Storm Light");
    if (NULL != mp_oStormLight) {
      m_iLightCode = mp_oStormLight->GetFloatDataCode("Light");
    }

    //Declare the species-specific temp array and pre-load with the species that
    //this behavior affects
    p_fTempValues = new doubleVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    //Low-light X0
    FillSpeciesSpecificValue( p_oElement, "gr_lognormalBilevLoLiteX0",
        "gr_lbllx0Val", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array while making sure none of them
    //are 0
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if (p_fTempValues[i].val == 0) {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clLogBiLevelGrowth::DoShellSetup";
        stcErr.sMoreInfo = "X0 values cannot equal 0.";
        throw(stcErr);
      }
      mp_fLoLightX0[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }

    //Low-light Xb
    FillSpeciesSpecificValue( p_oElement, "gr_lognormalBilevLoLiteXb",
        "gr_lbllxbVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array while making sure none of them
    //are 0
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if (p_fTempValues[i].val == 0) {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clLogBiLevelGrowth::DoShellSetup";
        stcErr.sMoreInfo = "Xb values cannot equal 0.";
        throw(stcErr);
      }
      mp_fLoLightXb[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }


    //Low-light max growth
    FillSpeciesSpecificValue( p_oElement, "gr_lognormalBilevLoLiteMaxGrowth",
        "gr_lbllmgVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array while making sure none of them
    //are 0
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if (p_fTempValues[i].val < 0) {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clLogBiLevelGrowth::DoShellSetup";
        stcErr.sMoreInfo = "Max growth values must be greater than 0.";
        throw(stcErr);
      }
      mp_fLoLightMaxGrowth[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }

    //Get high-light parameters if we have a storm light grid
    if (NULL != mp_oStormLight) {

      //High-light threshold
      FillSpeciesSpecificValue( p_oElement, "gr_lognormalBilevHiLiteThreshold",
        "gr_lobhltVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
      //Transfer values to our permanent array, making sure all values are
      //between 0 and 100
      for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
        if (p_fTempValues[i].val < 0 || p_fTempValues[i].val > 100) {
          modelErr stcErr;
          stcErr.iErrorCode = BAD_DATA;
          stcErr.sFunction = "clLogBiLevelGrowth::DoShellSetup";
          stcErr.sMoreInfo = "All values in high-light growth threshold must be between 0 and 100.";
          throw(stcErr);
        }
        mp_fHiLightThreshold[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
      }

      //High-light X0
      FillSpeciesSpecificValue( p_oElement, "gr_lognormalBilevHiLiteX0",
          "gr_lbhlx0Val", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
      //Transfer values to our permanent array while making sure none of them
      //are 0
      for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
        if (p_fTempValues[i].val == 0) {
          modelErr stcErr;
          stcErr.iErrorCode = BAD_DATA;
          stcErr.sFunction = "clLogBiLevelGrowth::DoShellSetup";
          stcErr.sMoreInfo = "X0 values cannot equal 0.";
          throw(stcErr);
        }
        mp_fHiLightX0[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
      }

      //High-light Xb
      FillSpeciesSpecificValue( p_oElement, "gr_lognormalBilevHiLiteXb",
          "gr_lbhlxbVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
      //Transfer values to our permanent array while making sure none of them
      //are 0
      for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
        if (p_fTempValues[i].val == 0) {
          modelErr stcErr;
          stcErr.iErrorCode = BAD_DATA;
          stcErr.sFunction = "clLogBiLevelGrowth::DoShellSetup";
          stcErr.sMoreInfo = "Xb values cannot equal 0.";
          throw(stcErr);
        }
        mp_fHiLightXb[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
      }

      //High-light max growth
      FillSpeciesSpecificValue( p_oElement, "gr_lognormalBilevHiLiteMaxGrowth",
          "gr_lbhlmgVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
      //Transfer values to our permanent array while making sure none of them
      //are 0
      for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
        if (p_fTempValues[i].val < 0) {
          modelErr stcErr;
          stcErr.iErrorCode = BAD_DATA;
          stcErr.sFunction = "clLogBiLevelGrowth::DoShellSetup";
          stcErr.sMoreInfo = "Max growth values must be greater than 0.";
          throw(stcErr);
        }
        mp_fHiLightMaxGrowth[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
      }

    } else {
      for (i = 0; i < m_iNumBehaviorSpecies; i++) {
        mp_fHiLightThreshold[i] = 100;
      }
    }

    delete[] p_fTempValues;
  }
  catch ( modelErr & err )
  {
    delete[] p_fTempValues;
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    delete[] p_fTempValues;
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    delete[] p_fTempValues;
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clLogBiLevelGrowth::DoShellSetup" ;
    throw( stcErr );
  }
}
//---------------------------------------------------------------------------
// PRStormBiLevelGrowth.cpp
//---------------------------------------------------------------------------
#include "PRStormBiLevelGrowth.h"
#include "TreePopulation.h"
#include "SimManager.h"
#include "ParsingFunctions.h"
#include "Grid.h"
#include "GrowthOrg.h"
#include "Allometry.h"

#define MINDIAM 0.001

//////////////////////////////////////////////////////////////////////////////
// Constructor
/////////////////////////////////////////////////////////////////////////////*/
clPRStormBiLevelGrowth::clPRStormBiLevelGrowth( clSimManager * p_oSimManager ) :
     clWorkerBase( p_oSimManager ), clBehaviorBase( p_oSimManager ),
     clGrowthBase( p_oSimManager )
{

  try
  {
    mp_oStormLight = NULL;
    mp_oStorm = NULL;
    mp_fLoLightSlope = NULL;
    mp_fLoLightIntercept = NULL;
    mp_fHiLightA = NULL;
    mp_fHiLightB = NULL;
    mp_fHiLightThreshold = NULL;
    mp_iIndexes = NULL;

    m_iGrowthMethod = diameter_auto;
    m_iLightCode = -1;
    m_iStormtimeCode = -1;
    m_iYearsPerTimestep = 0;

    m_sNameString = "prstormbilevelgrowthshell";
    m_sXMLRoot = "PRStormBilevelGrowth";
  }
  catch ( modelErr & err )
  {
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clPRStormBiLevelGrowth::clPRStormBiLevelGrowth" ;
    throw( stcErr );
  }
}

//////////////////////////////////////////////////////////////////////////////
// Destructor
/////////////////////////////////////////////////////////////////////////////*/
clPRStormBiLevelGrowth::~clPRStormBiLevelGrowth()
{
  delete[] mp_fLoLightSlope;
  delete[] mp_fLoLightIntercept;
  delete[] mp_fHiLightA;
  delete[] mp_fHiLightB;
  delete[] mp_fHiLightThreshold;
  delete[] mp_iIndexes;
}

//////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
/////////////////////////////////////////////////////////////////////////////*/
void clPRStormBiLevelGrowth::DoShellSetup( DOMDocument * p_oDoc )
{
  doubleVal * p_fTempValues = NULL; //for getting species-specific values
  try
  {
    clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
    DOMElement * p_oElement = p_oDoc->getDocumentElement();
    short int iNumSpecies = p_oPop->GetNumberOfSpecies(), i;

    //Get number of years per timestep
    m_iYearsPerTimestep = mp_oSimManager->GetNumberOfYearsPerTimestep();

    //Declare the arrays we'd like read
    mp_fLoLightSlope = new double[m_iNumBehaviorSpecies];
    mp_fLoLightIntercept = new double[m_iNumBehaviorSpecies];
    mp_fHiLightA = new double[m_iNumBehaviorSpecies];
    mp_fHiLightB = new double[m_iNumBehaviorSpecies];
    mp_fHiLightThreshold = new double[m_iNumBehaviorSpecies];
    mp_iIndexes = new int[iNumSpecies];

    //Set up the array indexes
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_iIndexes[mp_iWhatSpecies[i]] = i;

    //Find the storm grid
    mp_oStorm = mp_oSimManager->GetGridObject("Storm Damage");
    if (NULL == mp_oStorm) {
      modelErr stcErr;
      stcErr.iErrorCode = BAD_DATA;
      stcErr.sFunction = "clPRStormBiLevelGrowth::DoShellSetup";
      stcErr.sMoreInfo = "The storm behavior must be used with PR Storm Bi-Level Growth.";
      throw(stcErr);
    }
    m_iStormtimeCode = mp_oStorm->GetFloatDataCode("stormtime");
    if (-1 == m_iStormtimeCode) {
      modelErr stcErr;
      stcErr.iErrorCode = BAD_DATA;
      stcErr.sFunction = "clPRStormBiLevelGrowth::DoShellSetup";
      stcErr.sMoreInfo = "The \"stormtime\" was not found in the \"Storm Damage\" grid.";
      throw(stcErr);
    }

    //Find the storm light grid
    mp_oStormLight = mp_oSimManager->GetGridObject("Storm Light");
    if (NULL == mp_oStormLight) {
      modelErr stcErr;
      stcErr.iErrorCode = BAD_DATA;
      stcErr.sFunction = "clPRStormBiLevelGrowth::DoShellSetup";
      stcErr.sMoreInfo = "The storm light behavior must be used with PR Storm Bi-Level Growth.";
      throw(stcErr);
    }
    m_iLightCode = mp_oStormLight->GetFloatDataCode("Light");
    if (-1 == m_iLightCode) {
      modelErr stcErr;
      stcErr.iErrorCode = BAD_DATA;
      stcErr.sFunction = "clPRStormBiLevelGrowth::DoShellSetup";
      stcErr.sMoreInfo = "The \"Light\" was not found in the \"Storm Light\" grid.";
      throw(stcErr);
    }

    //Declare the species-specific temp array and pre-load with the species that
    //this behavior affects
    p_fTempValues = new doubleVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    //Low-light growth intercept
    FillSpeciesSpecificValue( p_oElement, "gr_prBilevStmGrwthLoLiteIntercept",
        "gr_pbsglliVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fLoLightIntercept[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

    //Low-light growth slope
    FillSpeciesSpecificValue( p_oElement, "gr_prBilevStmGrwthLoLiteSlope",
        "gr_pbsgllsVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fLoLightSlope[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

    //High-light threshold
    FillSpeciesSpecificValue( p_oElement, "gr_prBilevStmGrwthHiLiteThreshold",
      "gr_pbsghltVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array, making sure all values are
    //between 0 and 100
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if (p_fTempValues[i].val < 0 || p_fTempValues[i].val > 100) {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clPRStormBiLevelGrowth::DoShellSetup";
        stcErr.sMoreInfo = "All values in high-light growth threshold must be between 0 and 100.";
        throw(stcErr);
      }
      mp_fHiLightThreshold[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }

    //High-light growth "a"
    FillSpeciesSpecificValue( p_oElement, "gr_prBilevStmGrwthHiLiteA",
      "gr_pbsghlaVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array - transform this from cm to m
    //of height
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fHiLightA[mp_iIndexes[p_fTempValues[i].code]] =
         p_fTempValues[i].val/100.0;

    //High-light growth "b"
    FillSpeciesSpecificValue( p_oElement, "gr_prBilevStmGrwthHiLiteB",
      "gr_pbsghlbVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fHiLightB[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

    delete[] p_fTempValues;
  }
  catch ( modelErr & err )
  {
    delete[] p_fTempValues;
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    delete[] p_fTempValues;
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    delete[] p_fTempValues;
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clPRStormBiLevelGrowth::DoShellSetup" ;
    throw( stcErr );
  }
}
/////////////////////////////////////////////////////////////////////////////
// GetData()
/////////////////////////////////////////////////////////////////////////////
void clDimensionAnalysis::GetData( xercesc::DOMDocument * p_oDoc )
{
  floatVal * p_fTempValues = NULL; //for getting species-specific values
  intVal * p_iTempValues = NULL; //for getting species-specific values
  boolVal * p_bTempValues = NULL; //for getting species-specific values
  std::stringstream sQueryTemp;
  try
  {
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
    float fConvertGramsToMg = CONVERT_G_TO_KG * CONVERT_KG_TO_MG,
          fConvertLbsToMg = CONVERT_LBS_TO_KG * CONVERT_KG_TO_MG;
    int i;
    bool bSapling = false, bAdult = false, bSnag = false;

    //*************************
    // Read in parameters
    //*************************

    //Set up our arrays that will extract values only for the species
    //assigned to this behavior
    p_fTempValues = new floatVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];
    p_iTempValues = new intVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_iTempValues[i].code = mp_iWhatSpecies[i];
    p_bTempValues = new boolVal[m_iNumBehaviorSpecies];
      for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
        p_bTempValues[i].code = mp_iWhatSpecies[i];

    //Declare our arrays
    mp_fA = new float[m_iNumBehaviorSpecies];
    mp_fB = new float[m_iNumBehaviorSpecies];
    mp_fC = new float[m_iNumBehaviorSpecies];
    mp_fD = new float[m_iNumBehaviorSpecies];
    mp_fE = new float[m_iNumBehaviorSpecies];
    mp_fCorrectionFactor = new float[m_iNumBehaviorSpecies];
    mp_fDbhConverter = new float[m_iNumBehaviorSpecies];
    mp_fBiomassConverter = new float[m_iNumBehaviorSpecies];
    mp_iEquationID = new int[m_iNumBehaviorSpecies];
    mp_iWhatDia = new int[m_iNumBehaviorSpecies];
    mp_bUseCorrectionFactor = new bool[m_iNumBehaviorSpecies];
    mp_bConvertDBH = new bool[m_iNumBehaviorSpecies];

    //Get the parameter file values

    //a in the biomass equation
    FillSpeciesSpecificValue( p_oElement, "bi_a", "bi_aVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fA[i] = p_fTempValues[i].val;

    //b in the biomass equation
    FillSpeciesSpecificValue( p_oElement, "bi_b", "bi_bVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fB[i] = p_fTempValues[i].val;

    //c in the biomass equation
    FillSpeciesSpecificValue( p_oElement, "bi_c", "bi_cVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fC[i] = p_fTempValues[i].val;

    //d in the biomass equation
    FillSpeciesSpecificValue( p_oElement, "bi_d", "bi_dVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fD[i] = p_fTempValues[i].val;

    //e in the biomass equation
    FillSpeciesSpecificValue( p_oElement, "bi_e", "bi_eVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fE[i] = p_fTempValues[i].val;

    //Use correction factor
    FillSpeciesSpecificValue( p_oElement, "bi_useCorrectionFactor", "bi_ucfVal", p_bTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_bUseCorrectionFactor[i] = p_bTempValues[i].val;

    //Correction factor
    FillSpeciesSpecificValue( p_oElement, "bi_correctionFactorValue", "bi_cfvVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fCorrectionFactor[i] = p_fTempValues[i].val;

    //Equation ID
    FillSpeciesSpecificValue( p_oElement, "bi_eqID", "bi_eiVal", p_iTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_iEquationID[i] = p_iTempValues[i].val;

    //Make sure the equation ID is between 1 and 9
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if (mp_iEquationID[i] < 1 || mp_iEquationID[i] > 9 ) {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clDimensionAnalysis::GetData";
        std::stringstream s;
        s << "Unidentified equation ID \"" << mp_iEquationID[i]
          << "\" for species \"" << mp_iWhatSpecies[i] << "\".";
        stcErr.sMoreInfo = s.str();
        throw(stcErr);
      }
    }

    //Meaning of "dia"
    FillSpeciesSpecificValue( p_oElement, "bi_whatDia", "bi_wdVal", p_iTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_iWhatDia[i] = p_iTempValues[i].val;

    //Make sure the value is valid
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if (mp_iWhatDia[i] < DBH || mp_iWhatDia[i] > DBH2 ) {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clDimensionAnalysis::GetData";
        std::stringstream s;
        s << "Unidentified dia meaning \"" << mp_iWhatDia[i]
          << "\" for species \"" << mp_iWhatSpecies[i] << "\".";
        stcErr.sMoreInfo = s.str();
        throw(stcErr);
      }
    }

    //DBH units
    FillSpeciesSpecificValue( p_oElement, "bi_dbhUnits", "bi_duVal", p_iTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Go through and assign the appropriate correction factor for each
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if (mm == p_iTempValues[i].val) {
        mp_fDbhConverter[i] = CONVERT_CM_TO_MM;
        mp_bConvertDBH[i] = true;
      }
      else if (cm == p_iTempValues[i].val) {
        mp_fDbhConverter[i] = 1;
        mp_bConvertDBH[i] = false;
      }
      else if (in == p_iTempValues[i].val) {
        mp_fDbhConverter[i] = CONVERT_CM_TO_IN;
        mp_bConvertDBH[i] = true;
      }
      else {
        //Unrecognized value - throw an error
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clDimensionAnalysis::GetData";
        std::stringstream s;
        s << "Unidentified DBH units code \"" << p_iTempValues[i].val
          << "\" for species \"" << mp_iWhatSpecies[i] << "\".";
        stcErr.sMoreInfo = s.str();
        throw(stcErr);
      }
    }

    //Biomass units
    FillSpeciesSpecificValue( p_oElement, "bi_biomassUnits", "bi_buVal", p_iTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Go through and assign the appropriate correction factor for each
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if (g == p_iTempValues[i].val) {
        mp_fBiomassConverter[i] = fConvertGramsToMg;
      }
      else if (kg == p_iTempValues[i].val) {
        mp_fBiomassConverter[i] = CONVERT_KG_TO_MG;
      }
      else if (lb == p_iTempValues[i].val) {
        mp_fBiomassConverter[i] = fConvertLbsToMg;
      }
      else {
        //Unrecognized value - throw an error
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clDimensionAnalysis::GetData";
        std::stringstream s;
        s << "Unidentified biomass units code \"" << p_iTempValues[i].val
          << "\" for species \"" << mp_iWhatSpecies[i] << "\".";
        stcErr.sMoreInfo = s.str();
        throw(stcErr);
      }
    }


    //*************************
    // Format query string
    //*************************
    //Do a type/species search on all the types and species
    sQueryTemp << "species=";
    for (i = 0; i < m_iNumBehaviorSpecies - 1; i++) {
      sQueryTemp << mp_iWhatSpecies[i] << ",";
    }
    sQueryTemp << mp_iWhatSpecies[m_iNumBehaviorSpecies - 1];

    //Find all the types
    for (i = 0; i < m_iNumSpeciesTypeCombos; i++) {
      if ( clTreePopulation::sapling == mp_whatSpeciesTypeCombos[i].iType ) {
        bSapling = true;
      } else if ( clTreePopulation::adult == mp_whatSpeciesTypeCombos[i].iType ) {
        bAdult = true;
      } else if ( clTreePopulation::snag == mp_whatSpeciesTypeCombos[i].iType ) {
        bSnag = true;
      }
    }
    sQueryTemp << "::type=";
    if (bSapling) {
      sQueryTemp << clTreePopulation::sapling << ",";
    } if (bAdult) {
      sQueryTemp << clTreePopulation::adult << ",";
    } if (bSnag) {
      sQueryTemp << clTreePopulation::snag << ",";
    }

    //Remove the last comma and put it in m_sQuery
    m_sQuery = sQueryTemp.str().substr(0, sQueryTemp.str().length() - 1);

    delete[] p_fTempValues;
    delete[] p_iTempValues;
    delete[] p_bTempValues;

    Action();
  }
  catch ( modelErr & err )
  {
    delete[] p_fTempValues;
    delete[] p_iTempValues;
    delete[] p_bTempValues;
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    delete[] p_fTempValues;
    delete[] p_iTempValues;
    delete[] p_bTempValues;
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clDimensionAnalysis::GetData" ;
    throw( stcErr );
  }
}
//---------------------------------------------------------------------------
// MichMenNegGrowth.cpp
//---------------------------------------------------------------------------
#include "MichMenNegGrowth.h"
#include "TreePopulation.h"
#include "SimManager.h"
#include "ParsingFunctions.h"
#include "GrowthOrg.h"
#include <math.h>
#include <sstream>

//////////////////////////////////////////////////////////////////////////////
// Constructor
//////////////////////////////////////////////////////////////////////////////
clMichMenNegGrowth::clMichMenNegGrowth( clSimManager * p_oSimManager ) :
  clWorkerBase( p_oSimManager ), clBehaviorBase( p_oSimManager ), clGrowthBase( p_oSimManager )
{
  try
  {
    m_sNameString = "michmenneggrowthshell";
    m_sXMLRoot = "MichaelisMentenNegativeGrowth";

    m_iGrowthMethod = height_only;
    mp_fAlpha = NULL;
    mp_fBeta = NULL;
    mp_fPhi = NULL;
    mp_fGamma = NULL;
    mp_iIndexes = NULL;
    mp_iAutoCorrCodes = NULL;
    mp_fStdDev = NULL;
    mp_fProbAutoCorr = NULL;

    m_iNewTreeFloats += 1; //make sure we leave room for the growth data member

    m_iYearsPerTimestep = 0;
  }
  catch ( modelErr & err )
  {
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clMichMenNegGrowth::clMichMenNegGrowth" ;
    throw( stcErr );
  }
}

//////////////////////////////////////////////////////////////////////////////
// Destructor
/////////////////////////////////////////////////////////////////////////////*/
clMichMenNegGrowth::~clMichMenNegGrowth()
{
  delete[] mp_fAlpha;
  delete[] mp_fBeta;
  delete[] mp_fPhi;
  delete[] mp_fGamma;
  delete[] mp_iIndexes;
  delete[] mp_fStdDev;
  delete[] mp_fProbAutoCorr;
  for (int i = 0; i < m_iNumBehaviorSpecies; i++)
    delete[] mp_iAutoCorrCodes[i];
  delete[] mp_iAutoCorrCodes;
}

//////////////////////////////////////////////////////////////////////////////
// RegisterTreeDataMembers()
/////////////////////////////////////////////////////////////////////////////*/
void clMichMenNegGrowth::RegisterTreeDataMembers() {
 try {
   clTreePopulation *p_oPop = (clTreePopulation *)mp_oSimManager->GetPopulationObject("treepopulation");
   short int iNumTypes = p_oPop->GetNumberOfTypes(), //number of unique types
             iNumTotalSpecies = p_oPop->GetNumberOfSpecies(),
             i, j;           //loop counters

   //Call the base class version as well
   clGrowthBase::RegisterTreeDataMembers();

   mp_iIndexes = new int[iNumTotalSpecies];
   for (i = 0; i < iNumTotalSpecies; i++) mp_iIndexes[i] = -1;

    //Set up the array indexes
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_iIndexes[mp_iWhatSpecies[i]] = i;

   //Declare the temp. types array to be as big as the combo list to make
   //sure we have space for everything, and initialize values to -1
   mp_iAutoCorrCodes = new short int*[m_iNumBehaviorSpecies];
   for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_iAutoCorrCodes[i] = new short int[iNumTypes];
   for (i = 0; i < m_iNumBehaviorSpecies; i++)
     for (j = 0; j < iNumTypes; j++)
       mp_iAutoCorrCodes[i][j] = -1;


   //Register the variables for what's actually in our type/species
   //combos
   for (i = 0; i < m_iNumSpeciesTypeCombos; i++) {
     //Register the code and capture it
     mp_iAutoCorrCodes[mp_iIndexes[mp_whatSpeciesTypeCombos[i].iSpecies]]
                      [mp_whatSpeciesTypeCombos[i].iType] =
       p_oPop->RegisterFloat("autocorr", mp_whatSpeciesTypeCombos[i].iSpecies,
                            mp_whatSpeciesTypeCombos[i].iType);
   }
 }
 catch (modelErr&err) {throw(err);}
 catch (modelMsg &msg) {throw(msg);} //non-fatal error
 catch (...) {
   modelErr stcErr;
   stcErr.iErrorCode = UNKNOWN;
   stcErr.sFunction = "clAbsoluteGrowth::RegisterTreeDataMembers";
   throw(stcErr);
 }
}

//////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
/////////////////////////////////////////////////////////////////////////////*/
void clMichMenNegGrowth::DoShellSetup( DOMDocument * p_oDoc )
{
  doubleVal * p_fTempValues = NULL; //for getting species-specific values
  try
  {
    clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    short int i;


    //Get number of years per timestep
    m_iYearsPerTimestep = mp_oSimManager->GetNumberOfYearsPerTimestep();

    //Declare the arrays we'd like read
    mp_fAlpha = new double[m_iNumBehaviorSpecies];
    mp_fBeta = new double[m_iNumBehaviorSpecies];
    mp_fPhi = new double[m_iNumBehaviorSpecies];
    mp_fGamma = new double[m_iNumBehaviorSpecies];
    mp_fStdDev = new double[m_iNumBehaviorSpecies];
    mp_fProbAutoCorr = new double[m_iNumBehaviorSpecies];

    //Declare the species-specific temp array and pre-load with the species that
    //this behavior affects
    p_fTempValues = new doubleVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    //Alpha
    FillSpeciesSpecificValue( p_oElement, "gr_mmNegGrowthAlpha",
        "gr_mmngaVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      mp_fAlpha[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }

    //Beta
    FillSpeciesSpecificValue( p_oElement, "gr_mmNegGrowthBeta",
        "gr_mmngbVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array while making sure none of them
    //are 0
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if (p_fTempValues[i].val == 0) {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clMichMenNegGrowth::DoShellSetup";
        stcErr.sMoreInfo = "Beta values cannot equal 0.";
        throw(stcErr);
      }
      mp_fBeta[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }


    //Gamma
    FillSpeciesSpecificValue( p_oElement, "gr_mmNegGrowthGamma",
        "gr_mmnggVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      mp_fGamma[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }

    //Phi
    FillSpeciesSpecificValue( p_oElement, "gr_mmNegGrowthPhi",
        "gr_mmngpVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      mp_fPhi[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }

    //standard deviation of growth stochasticity in cm/year
    FillSpeciesSpecificValue( p_oElement, "gr_mmNegGrowthStdDev",
        "gr_mmngsdVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      mp_fStdDev[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }

    //one year probability of autocorrelation
    FillSpeciesSpecificValue( p_oElement, "gr_mmNegGrowthAutoCorrProb",
        "gr_mmngacpVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if (p_fTempValues[i].val < 0 || p_fTempValues[i].val > 1) {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clMichMenNegGrowth::DoShellSetup";
        stcErr.sMoreInfo = "Autocorrelation probability must be between 0 and 1.";
        throw(stcErr);
      }
      mp_fProbAutoCorr[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }

    delete[] p_fTempValues;

    //Make sure all species/type combos have "Light" registered
    for ( int i = 0; i < m_iNumSpeciesTypeCombos; i++ )
    {
      if ( -1 == mp_oGrowthOrg->GetLightCode(mp_whatSpeciesTypeCombos[i].iSpecies,
                                           mp_whatSpeciesTypeCombos[i].iType ) )
      {
        modelErr stcErr;
        stcErr.sFunction = "clRelativeGrowth::DoShellSetup";
        std::stringstream s;
        s << "Type/species combo species="
          << mp_whatSpeciesTypeCombos[i].iSpecies << " type="
          << mp_whatSpeciesTypeCombos[i].iType
          << " does not have a required light behavior.";
        stcErr.sMoreInfo = s.str();
        stcErr.iErrorCode = BAD_DATA;
        throw( stcErr );
      }
    }
  }
  catch ( modelErr & err )
  {
    delete[] p_fTempValues;
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    delete[] p_fTempValues;
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    delete[] p_fTempValues;
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clMichMenNegGrowth::DoShellSetup" ;
    throw( stcErr );
  }
}
////////////////////////////////////////////////////////////////////////////
// DoSetup
////////////////////////////////////////////////////////////////////////////
void clPrecipitationEffectDoubleLogistic::DoSetup(clTreePopulation *p_oPop, clBehaviorBase *p_oNCI, xercesc::DOMElement *p_oElement) {
  doubleVal * p_fTempValues; //for getting species-specific values
  int iNumBehaviorSpecies = p_oNCI->GetNumBehaviorSpecies(),
      iNumTotalSpecies = p_oPop->GetNumberOfSpecies(), i, iPrecipType;

  mp_fAl = new double[iNumTotalSpecies];
  mp_fBl = new double[iNumTotalSpecies];
  mp_fCl = new double[iNumTotalSpecies];
  mp_fAh = new double[iNumTotalSpecies];
  mp_fBh = new double[iNumTotalSpecies];
  mp_fCh = new double[iNumTotalSpecies];

  //Set up our doubleVal array that will extract values only for the species
  //assigned to this behavior
  p_fTempValues = new doubleVal[iNumBehaviorSpecies];
  for ( i = 0; i < iNumBehaviorSpecies; i++ ) p_fTempValues[i].code = p_oNCI->GetBehaviorSpecies(i);

  //Precipitation effect al
  FillSpeciesSpecificValue( p_oElement, "nciDoubLogPrecipEffAl",
      "ndlpealVal", p_fTempValues, iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fAl[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Precipitation effect bl
  FillSpeciesSpecificValue( p_oElement, "nciDoubLogPrecipEffBl",
      "ndlpeblVal", p_fTempValues, iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fBl[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Precipitation effect cl
  FillSpeciesSpecificValue( p_oElement, "nciDoubLogPrecipEffCl",
      "ndlpeclVal", p_fTempValues, iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fCl[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Precipitation effect ah
  FillSpeciesSpecificValue( p_oElement, "nciDoubLogPrecipEffAh",
      "ndlpeahVal", p_fTempValues, iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fAh[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Precipitation effect bh
  FillSpeciesSpecificValue( p_oElement, "nciDoubLogPrecipEffBh",
      "ndlpebhVal", p_fTempValues, iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fBh[p_fTempValues[i].code] = p_fTempValues[i].val;

  //Precipitation effect ch
  FillSpeciesSpecificValue( p_oElement, "nciDoubLogPrecipEffCh",
      "ndlpechVal", p_fTempValues, iNumBehaviorSpecies, p_oPop, true );
  //Transfer to the appropriate array buckets
  for ( i = 0; i < iNumBehaviorSpecies; i++ )
    mp_fCh[p_fTempValues[i].code] = p_fTempValues[i].val;

  delete[] p_fTempValues;

  //Precip value desired
  iPrecipType = mean_precip;
  FillSingleValue(p_oElement, "nciDoubleLogisticPrecipType", &iPrecipType, true);
  if (iPrecipType == mean_precip) {
    m_precip = &clPlot::GetMeanAnnualPrecip;
  } else if (iPrecipType == seasonal_precip) {
    m_precip = &clPlot::GetSeasonalPrecipitation;
  } else if (iPrecipType == water_deficit) {
    m_precip = &clPlot::GetWaterDeficit;
  } else {
    modelErr stcErr;
    stcErr.iErrorCode = BAD_DATA;
    stcErr.sFunction = "clPrecipitationEffectDoubleLogistic::DoSetup";
    stcErr.sMoreInfo = "Unrecognized precipitation type value.";
    throw( stcErr );
  }
}
///////////////////////////////////////////////////////////////////////////////
// GetParameterFileData
/////////////////////////////////////////////////////////////////////////////
void clSubstrateDepSeedSurvival::GetParameterFileData(
    xercesc::DOMDocument * p_oDoc) {
  doubleVal * p_fTemp = NULL; //for getting species-specific values
  try {
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    clTreePopulation * p_oPop =
        (clTreePopulation *) mp_oSimManager->GetPopulationObject(
            "treepopulation");

    short int iNumSpecies = p_oPop->GetNumberOfSpecies(), i;

    //Declare our data arrays
    mp_iIndexes = new short int[iNumSpecies];
    //Load the indexes array
    //Make the list of indexes
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_iIndexes[mp_iWhatSpecies[i]] = i;

    //Declare the canopy array values
    mp_fCanGroundScarSoilFav = new double[m_iNumBehaviorSpecies];
    mp_fCanGroundTipUpFav = new double[m_iNumBehaviorSpecies];
    mp_fCanGroundFreshLogFav = new double[m_iNumBehaviorSpecies];
    mp_fCanGroundDecLogFav = new double[m_iNumBehaviorSpecies];
    mp_fCanGroundForFlLitterFav = new double[m_iNumBehaviorSpecies];
    mp_fCanGroundForFlMossFav = new double[m_iNumBehaviorSpecies];

    //Set up our temp array - pre-load with this behavior's species
    p_fTemp = new doubleVal[m_iNumBehaviorSpecies];
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      p_fTemp[i].code = mp_iWhatSpecies[i];

    //Canopy scarified soil favorability
    FillSpeciesSpecificValue(p_oElement, "es_scarifiedSoilCanopyFav",
        "es_sscfVal", p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
    //Now transfer the values to the permanent array
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_fCanGroundScarSoilFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

    //Canopy tip-up mound favorability
    FillSpeciesSpecificValue(p_oElement, "es_tipUpCanopyFav", "es_tucfVal",
        p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
    //Now transfer the values to the permanent array
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_fCanGroundTipUpFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

    //Canopy fresh log favorability
    FillSpeciesSpecificValue(p_oElement, "es_freshLogCanopyFav", "es_flcfVal",
        p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
    //Now transfer the values to the permanent array
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_fCanGroundFreshLogFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

    //Canopy decayed log favorability
    FillSpeciesSpecificValue(p_oElement, "es_decayedLogCanopyFav",
        "es_dlcfVal", p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
    //Now transfer the values to the permanent array
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_fCanGroundDecLogFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

    //Canopy forest floor litter favorability
    FillSpeciesSpecificValue(p_oElement, "es_forestFloorLitterCanopyFav",
        "es_fflcfVal", p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
    //Now transfer the values to the permanent array
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_fCanGroundForFlLitterFav[mp_iIndexes[p_fTemp[i].code]]
          = p_fTemp[i].val;

    //Canopy forest floor moss favorability
    FillSpeciesSpecificValue(p_oElement, "es_forestFloorMossCanopyFav",
        "es_ffmcfVal", p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
    //Now transfer the values to the permanent array
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_fCanGroundForFlMossFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

    //Verify that all values are between 0 and 1
    for (i = 0; i < m_iNumBehaviorSpecies; i++) {
      if (mp_fCanGroundScarSoilFav[i] < 0 || mp_fCanGroundScarSoilFav[i] > 1
          || mp_fCanGroundTipUpFav[i] < 0 || mp_fCanGroundTipUpFav[i] > 1
          || mp_fCanGroundFreshLogFav[i] < 0 || mp_fCanGroundFreshLogFav[i] > 1
          || mp_fCanGroundDecLogFav[i] < 0 || mp_fCanGroundDecLogFav[i] > 1
          || mp_fCanGroundForFlLitterFav[i] < 0
          || mp_fCanGroundForFlLitterFav[i] > 1 || mp_fCanGroundForFlMossFav[i]
          < 0 || mp_fCanGroundForFlMossFav[i] > 1) {
        modelErr stcErr;
        stcErr.sFunction = "clSubstrateDepSeedSurvival::GetParameterFileData";
        stcErr.sMoreInfo = "All substrate favorabilities must be between 0 and 1.";
        stcErr.iErrorCode = BAD_DATA;
        throw(stcErr);
      }
    }

    if (m_bUsesGap) {
      //Declare the gap array values
      mp_fGapMoundScarSoilFav = new double[m_iNumBehaviorSpecies];
      mp_fGapMoundTipUpFav = new double[m_iNumBehaviorSpecies];
      mp_fGapMoundFreshLogFav = new double[m_iNumBehaviorSpecies];
      mp_fGapMoundDecLogFav = new double[m_iNumBehaviorSpecies];
      mp_fGapMoundForFlLitterFav = new double[m_iNumBehaviorSpecies];
      mp_fGapMoundForFlMossFav = new double[m_iNumBehaviorSpecies];

      //Load the gap values
      //Gap scarified soil favorability
      FillSpeciesSpecificValue(p_oElement, "es_scarifiedSoilGapFav",
          "es_ssgfVal", p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
      //Now transfer the values to the permanent array
      for (i = 0; i < m_iNumBehaviorSpecies; i++)
        mp_fGapMoundScarSoilFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

      //Gap tip-up mound favorability
      FillSpeciesSpecificValue(p_oElement, "es_tipUpGapFav", "es_tugfVal",
          p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
      //Now transfer the values to the permanent array
      for (i = 0; i < m_iNumBehaviorSpecies; i++)
        mp_fGapMoundTipUpFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

      //Gap fresh log favorability
      FillSpeciesSpecificValue(p_oElement, "es_freshLogGapFav", "es_flgfVal",
          p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
      //Now transfer the values to the permanent array
      for (i = 0; i < m_iNumBehaviorSpecies; i++)
        mp_fGapMoundFreshLogFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

      //Gap decayed log favorability
      FillSpeciesSpecificValue(p_oElement, "es_decayedLogGapFav", "es_dlgfVal",
          p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
      //Now transfer the values to the permanent array
      for (i = 0; i < m_iNumBehaviorSpecies; i++)
        mp_fGapMoundDecLogFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

      //Gap forest floor litter favorability
      FillSpeciesSpecificValue(p_oElement, "es_forestFloorLitterGapFav",
          "es_fflgfVal", p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
      //Now transfer the values to the permanent array
      for (i = 0; i < m_iNumBehaviorSpecies; i++)
        mp_fGapMoundForFlLitterFav[mp_iIndexes[p_fTemp[i].code]]
            = p_fTemp[i].val;

      //Gap forest floor moss favorability
      FillSpeciesSpecificValue(p_oElement, "es_forestFloorMossGapFav",
          "es_ffmgfVal", p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
      //Now transfer the values to the permanent array
      for (i = 0; i < m_iNumBehaviorSpecies; i++)
        mp_fGapMoundForFlMossFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

      //Verify that all values are between 0 and 1
      for (i = 0; i < m_iNumBehaviorSpecies; i++) {
        if (mp_fGapMoundScarSoilFav[i] < 0 || mp_fGapMoundScarSoilFav[i] > 1
            || mp_fGapMoundTipUpFav[i] < 0 || mp_fGapMoundTipUpFav[i] > 1
            || mp_fGapMoundFreshLogFav[i] < 0 || mp_fGapMoundFreshLogFav[i] > 1
            || mp_fGapMoundDecLogFav[i] < 0 || mp_fGapMoundDecLogFav[i] > 1
            || mp_fGapMoundForFlLitterFav[i] < 0
            || mp_fGapMoundForFlLitterFav[i] > 1 || mp_fGapMoundForFlMossFav[i]
            < 0 || mp_fGapMoundForFlMossFav[i] > 1) {
          modelErr stcErr;
          stcErr.sFunction = "clSubstrateDepSeedSurvival::GetParameterFileData";
          stcErr.sMoreInfo = "All substrate favorabilities must be between 0 and 1.";
          stcErr.iErrorCode = BAD_DATA;
          throw(stcErr);
        }
      }
    }

    //If using microtopography...
    if (m_bUsesMicro) {
      //Declare the gap array values
      mp_fGapMoundScarSoilFav = new double[m_iNumBehaviorSpecies];
      mp_fGapMoundTipUpFav = new double[m_iNumBehaviorSpecies];
      mp_fGapMoundFreshLogFav = new double[m_iNumBehaviorSpecies];
      mp_fGapMoundDecLogFav = new double[m_iNumBehaviorSpecies];
      mp_fGapMoundForFlLitterFav = new double[m_iNumBehaviorSpecies];
      mp_fGapMoundForFlMossFav = new double[m_iNumBehaviorSpecies];

      //Proportion of plot that is mound
      FillSingleValue(p_oElement, "es_moundProportion", &m_fMoundProp, true);
      if (m_fMoundProp < 0 || m_fMoundProp > 1) {
        modelErr stcErr;
        stcErr.sFunction = "clSubstrateDepSeedSurvival::GetParameterFileData";
        stcErr.sMoreInfo = "Mound proportion must be between 0 and 1.";
        stcErr.iErrorCode = BAD_DATA;
        throw(stcErr);
      }

      //Mound scarified soil favorability
      FillSpeciesSpecificValue(p_oElement, "es_scarifiedSoilMoundFav",
          "es_ssmfVal", p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
      //Now transfer the values to the permanent array
      for (i = 0; i < m_iNumBehaviorSpecies; i++)
        mp_fGapMoundScarSoilFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

      //Mound tip-up mound favorability
      FillSpeciesSpecificValue(p_oElement, "es_tipUpMoundFav", "es_tumfVal",
          p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
      //Now transfer the values to the permanent array
      for (i = 0; i < m_iNumBehaviorSpecies; i++)
        mp_fGapMoundTipUpFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

      //Mound fresh log favorability
      FillSpeciesSpecificValue(p_oElement, "es_freshLogMoundFav", "es_flmfVal",
          p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
      //Now transfer the values to the permanent array
      for (i = 0; i < m_iNumBehaviorSpecies; i++)
        mp_fGapMoundFreshLogFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

      //Mound decayed log favorability
      FillSpeciesSpecificValue(p_oElement, "es_decayedLogMoundFav",
          "es_dlmfVal", p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
      //Now transfer the values to the permanent array
      for (i = 0; i < m_iNumBehaviorSpecies; i++)
        mp_fGapMoundDecLogFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

      //Mound forest floor litter favorability
      FillSpeciesSpecificValue(p_oElement, "es_forestFloorLitterMoundFav",
          "es_fflmfVal", p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
      //Now transfer the values to the permanent array
      for (i = 0; i < m_iNumBehaviorSpecies; i++)
        mp_fGapMoundForFlLitterFav[mp_iIndexes[p_fTemp[i].code]]
            = p_fTemp[i].val;

      //Mound forest floor moss favorability
      FillSpeciesSpecificValue(p_oElement, "es_forestFloorMossMoundFav",
          "es_ffmmfVal", p_fTemp, m_iNumBehaviorSpecies, p_oPop, true);
      //Now transfer the values to the permanent array
      for (i = 0; i < m_iNumBehaviorSpecies; i++)
        mp_fGapMoundForFlMossFav[mp_iIndexes[p_fTemp[i].code]] = p_fTemp[i].val;

      //Verify that all values are between 0 and 1
      for (i = 0; i < m_iNumBehaviorSpecies; i++) {
        if (mp_fGapMoundScarSoilFav[i] < 0 || mp_fGapMoundScarSoilFav[i] > 1
            || mp_fGapMoundTipUpFav[i] < 0 || mp_fGapMoundTipUpFav[i] > 1
            || mp_fGapMoundFreshLogFav[i] < 0 || mp_fGapMoundFreshLogFav[i] > 1
            || mp_fGapMoundDecLogFav[i] < 0 || mp_fGapMoundDecLogFav[i] > 1
            || mp_fGapMoundForFlLitterFav[i] < 0
            || mp_fGapMoundForFlLitterFav[i] > 1 || mp_fGapMoundForFlMossFav[i]
            < 0 || mp_fGapMoundForFlMossFav[i] > 1) {
          modelErr stcErr;
          stcErr.sFunction = "clSubstrateDepSeedSurvival::GetParameterFileData";
          stcErr.sMoreInfo = "All substrate favorabilities must be between 0 and 1.";
          stcErr.iErrorCode = BAD_DATA;
          throw(stcErr);
        }
      }
    }

    delete[] p_fTemp;
  } catch (modelErr& err) {
    delete[] p_fTemp;
    throw(err);
  } catch (modelMsg & msg) {
    delete[] p_fTemp;
    throw(msg);
  } //non-fatal error
  catch (...) {
    delete[] p_fTemp;
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clSubstrateDepSeedSurvival::GetParameterFileData";
    throw(stcErr);
  }
}
//////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
//////////////////////////////////////////////////////////////////////////////
void clBrowsedRelativeGrowth::DoShellSetup( DOMDocument * p_oDoc )
{
  doubleVal * p_fTempValues = NULL; //for getting species-specific values
  try
  {
    clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    short int i, j, iNumTypes = p_oPop->GetNumberOfTypes();

    m_iNumSpecies = p_oPop->GetNumberOfSpecies();

    //Set up our doubleVal array that will extract values only for the species
    //assigned to this behavior
    p_fTempValues = new doubleVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    m_ifNumberYearsPerTimestep = mp_oSimManager->GetNumberOfYearsPerTimestep();

    //Declare the arrays
    mp_fUnbrowsedS = new double[m_iNumSpecies];
    mp_fBrowsedS = new double[m_iNumSpecies];
    mp_fUnbrowsedA = new double[m_iNumSpecies];
    mp_fBrowsedA = new double[m_iNumSpecies];
    mp_fUnbrowsedDiamExp = new double[m_iNumSpecies];
    mp_fBrowsedDiamExp = new double[m_iNumSpecies];

    //Unbrowsed S
    FillSpeciesSpecificValue(p_oElement, "gr_slopeGrowthResponse", "gr_sgrVal",
                          p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true);
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_fUnbrowsedS[p_fTempValues[i].code] = p_fTempValues[i].val;


    //Unbrowsed A
    FillSpeciesSpecificValue(p_oElement, "gr_asympDiameterGrowth", "gr_adgVal",
                          p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true);
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_fUnbrowsedA[p_fTempValues[i].code] = p_fTempValues[i].val;

    //Unbrowsed diameter exponent
    FillSpeciesSpecificValue( p_oElement, "gr_relGrowthDiamExp", "gr_rgdeVal",
                          p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fUnbrowsedDiamExp[p_fTempValues[i].code] = p_fTempValues[i].val;

    //Browsed S
    FillSpeciesSpecificValue(p_oElement, "gr_browsedSlopeGrowthResponse",
       "gr_bsgrVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true);
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_fBrowsedS[p_fTempValues[i].code] = p_fTempValues[i].val;

    //Browsed A
    FillSpeciesSpecificValue(p_oElement, "gr_browsedAsympDiameterGrowth",
       "gr_badgVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true);
    for (i = 0; i < m_iNumBehaviorSpecies; i++)
      mp_fBrowsedA[p_fTempValues[i].code] = p_fTempValues[i].val;

    //Browsed diameter exponent
    FillSpeciesSpecificValue( p_oElement, "gr_browsedRelGrowthDiamExp",
        "gr_brgdeVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fBrowsedDiamExp[p_fTempValues[i].code] = p_fTempValues[i].val;

    //Scale the browsed and unbrowsed S values
    for (i = 0; i < m_iNumBehaviorSpecies; i++) {
      if (mp_fBrowsedS[mp_iWhatSpecies[i]] != 0.0) {
        mp_fBrowsedS[mp_iWhatSpecies[i]] =
                                          mp_fBrowsedA[mp_iWhatSpecies[i]] /
                                          mp_fBrowsedS[mp_iWhatSpecies[i]];
      }
      if (mp_fUnbrowsedS[mp_iWhatSpecies[i]] != 0.0) {
        mp_fUnbrowsedS[mp_iWhatSpecies[i]] =
                                           mp_fUnbrowsedA[mp_iWhatSpecies[i]] /
                                           mp_fUnbrowsedS[mp_iWhatSpecies[i]];
      }
    }

    //Collect the "Light" codes
    mp_iLightCodes = new short int *[m_iNumSpecies];
    mp_iBrowsedCodes = new short int *[m_iNumSpecies];
    for (i = 0; i < m_iNumSpecies; i++) {
      mp_iLightCodes[i] = new short int[iNumTypes];
      mp_iBrowsedCodes[i] = new short int[iNumTypes];
      for (j = 0; j < iNumTypes; j++) {
        mp_iLightCodes[i][j] = -1;
        mp_iBrowsedCodes[i][j] = -1;
      }
    }
    for (i = 0; i < m_iNumSpeciesTypeCombos; i++ )
    {
      mp_iLightCodes[mp_whatSpeciesTypeCombos[i].iSpecies]
                    [mp_whatSpeciesTypeCombos[i].iType] =
            mp_oGrowthOrg->GetLightCode(mp_whatSpeciesTypeCombos[i].iSpecies,
                                           mp_whatSpeciesTypeCombos[i].iType );
      if (-1 ==  mp_iLightCodes[mp_whatSpeciesTypeCombos[i].iSpecies]
                               [mp_whatSpeciesTypeCombos[i].iType] )
      {
        modelErr stcErr;
        stcErr.sFunction = "clBrowsedRelativeGrowth::DoShellSetup" ;
        std::stringstream s;
        s << "Type/species combo species="
          << mp_whatSpeciesTypeCombos[i].iSpecies << " type="
          << mp_whatSpeciesTypeCombos[i].iType
          << " does not have a required light behavior.";
        stcErr.sMoreInfo = s.str();
        stcErr.iErrorCode = BAD_DATA;
        throw( stcErr );
      }

      mp_iBrowsedCodes[mp_whatSpeciesTypeCombos[i].iSpecies]
                      [mp_whatSpeciesTypeCombos[i].iType] =
            p_oPop->GetBoolDataCode("Browsed",
                                    mp_whatSpeciesTypeCombos[i].iSpecies,
                                    mp_whatSpeciesTypeCombos[i].iType );
      if (-1 ==  mp_iBrowsedCodes[mp_whatSpeciesTypeCombos[i].iSpecies]
                                 [mp_whatSpeciesTypeCombos[i].iType] )
      {
        modelErr stcErr;
        stcErr.sFunction = "clBrowsedRelativeGrowth::DoShellSetup" ;
        std::stringstream s;
        s << "Type/species combo species="
          << mp_whatSpeciesTypeCombos[i].iSpecies << " type="
          << mp_whatSpeciesTypeCombos[i].iType
          << " does not have the browse behavior.";
        stcErr.sMoreInfo = s.str();
        stcErr.iErrorCode = BAD_DATA;
        throw( stcErr );
      }
    }

    delete[] p_fTempValues;
  }
  catch ( modelErr & err )
  {
    delete[] p_fTempValues;
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    delete[] p_fTempValues;
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    delete[] p_fTempValues;
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clBrowsedRelativeGrowth::DoShellSetup" ;
    throw( stcErr );
  }
}
////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
////////////////////////////////////////////////////////////////////////////
void clSenescenceMort::DoShellSetup( xercesc::DOMDocument * p_oDoc )
{
  try
  {
    clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    short int i; //loop counter

    m_iNumTotalSpecies = p_oPop->GetNumberOfSpecies();

    //Declare the floatVal arrays and populate with the species to which this
    //behavior applies
    mp_fRandomAlpha = new floatVal[m_iNumBehaviorSpecies];
    mp_fRandomBeta = new floatVal[m_iNumBehaviorSpecies];
    mp_fDbhAtOnset = new floatVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
    {
      mp_fRandomAlpha[i].code = mp_iWhatSpecies[i];
      mp_fRandomBeta[i].code = mp_iWhatSpecies[i];
      mp_fDbhAtOnset[i].code = mp_iWhatSpecies[i];
    }

    //Capture the values from the parameter file

    //Random mortality alpha
    FillSpeciesSpecificValue( p_oElement, "mo_senescenceAlpha", "mo_saVal",
        mp_fRandomAlpha, m_iNumBehaviorSpecies, p_oPop, true );


    //Random mortality beta
    FillSpeciesSpecificValue( p_oElement, "mo_senescenceBeta", "mo_sbVal",
        mp_fRandomBeta, m_iNumBehaviorSpecies, p_oPop, true );


    //Dbh at onset of senescence
    FillSpeciesSpecificValue( p_oElement, "mo_dbhAtOnsetOfSenescence",
        "mo_daoosVal", mp_fDbhAtOnset, m_iNumBehaviorSpecies, p_oPop, true );


    //Max dbh - that of asymptotic max mortality
    FillSingleValue( p_oElement, "mo_dbhAtAsympMaxMort", & m_iMaxDbh, false );

    CalculateMortalityProbability();

    //Make sure that only saplings and adults were assigned to this behavior
    for ( i = 0; i < m_iNumSpeciesTypeCombos; i++ )
      if ( clTreePopulation::sapling != mp_whatSpeciesTypeCombos->iType
          && clTreePopulation::adult != mp_whatSpeciesTypeCombos->iType )
      {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        strcpy( stcErr.cFunction, "clSenescenceMort::DoShellSetup" );
        strcpy( stcErr.cMoreInfo, "This behavior cannot be applied to seedlings" );
        throw( stcErr );
      }
  }
  catch ( modelErr & err )
  {
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    strcpy( stcErr.cFunction, "clSenescenceMort::DoShellSetup" );
    throw( stcErr );
  }
}
//---------------------------------------------------------------------------
// MichMenPhotoinhibition.cpp
//---------------------------------------------------------------------------
#include "MichMenPhotoinhibition.h"
#include "TreePopulation.h"
#include "SimManager.h"
#include "ParsingFunctions.h"
#include "GrowthOrg.h"
#include <math.h>
#include <sstream>

//////////////////////////////////////////////////////////////////////////////
// Constructor
/////////////////////////////////////////////////////////////////////////////*/
clMichMenPhotoinhibition::clMichMenPhotoinhibition( clSimManager * p_oSimManager ) :
  clWorkerBase( p_oSimManager ), clBehaviorBase( p_oSimManager ), clGrowthBase( p_oSimManager )
{
  try
  {
    m_sNameString = "michmenphotogrowthshell";
    m_sXMLRoot = "MichaelisMentenPhotoinhibitionGrowth";

    m_iGrowthMethod = height_only;
    mp_fAlpha = NULL;
    mp_fBeta = NULL;
    mp_fPhi = NULL;
    mp_fD = NULL;
    mp_iIndexes = NULL;

    m_fYearsPerTimestep = 0;
  }
  catch ( modelErr & err )
  {
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clMichMenPhotoinhibition::clMichMenPhotoinhibition" ;
    throw( stcErr );
  }
}

//////////////////////////////////////////////////////////////////////////////
// Destructor
/////////////////////////////////////////////////////////////////////////////*/
clMichMenPhotoinhibition::~clMichMenPhotoinhibition()
{
  delete[] mp_fAlpha;
  delete[] mp_fBeta;
  delete[] mp_fPhi;
  delete[] mp_fD;
  delete[] mp_iIndexes;
}

//////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
/////////////////////////////////////////////////////////////////////////////*/
void clMichMenPhotoinhibition::DoShellSetup( DOMDocument * p_oDoc )
{
  floatVal * p_fTempValues = NULL; //for getting species-specific values
  try
  {
    clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    short int i;

    //Get number of years per timestep
    m_fYearsPerTimestep = mp_oSimManager->GetNumberOfYearsPerTimestep();

    //Declare the arrays we'd like read
    mp_fAlpha = new float[m_iNumBehaviorSpecies];
    mp_fBeta = new float[m_iNumBehaviorSpecies];
    mp_fPhi = new float[m_iNumBehaviorSpecies];
    mp_fD = new float[m_iNumBehaviorSpecies];
    mp_iIndexes = new int[p_oPop->GetNumberOfSpecies()];

    //Set up the array indexes
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_iIndexes[mp_iWhatSpecies[i]] = i;

    //Declare the species-specific temp array and pre-load with the species that
    //this behavior affects
    p_fTempValues = new floatVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    //Alpha
    FillSpeciesSpecificValue( p_oElement, "gr_mmPhotGrowthAlpha",
        "gr_mmpgaVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      mp_fAlpha[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }

    //Beta
    FillSpeciesSpecificValue( p_oElement, "gr_mmPhotGrowthBeta",
        "gr_mmpgbVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array while making sure none of them
    //are 0
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if (p_fTempValues[i].val == 0) {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clMichMenPhotoinhibition::DoShellSetup";
        stcErr.sMoreInfo = "Beta values cannot equal 0.";
        throw(stcErr);
      }
      mp_fBeta[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }


    //D
    FillSpeciesSpecificValue( p_oElement, "gr_mmPhotGrowthD",
        "gr_mmpgdVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      mp_fD[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }

    //Phi
    FillSpeciesSpecificValue( p_oElement, "gr_mmPhotGrowthPhi",
        "gr_mmpgpVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      mp_fPhi[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;
    }

    delete[] p_fTempValues;

    //Make sure all species/type combos have "Light" registered
    for ( int i = 0; i < m_iNumSpeciesTypeCombos; i++ )
    {
      if ( -1 == mp_oGrowthOrg->GetLightCode(mp_whatSpeciesTypeCombos[i].iSpecies,
                                           mp_whatSpeciesTypeCombos[i].iType ) )
      {
        modelErr stcErr;
        stcErr.sFunction = "clRelativeGrowth::DoShellSetup" ;
        std::stringstream s;
        s << "Type/species combo species="
          << mp_whatSpeciesTypeCombos[i].iSpecies << " type="
          << mp_whatSpeciesTypeCombos[i].iType
          << " does not have a required light behavior.";
        stcErr.iErrorCode = BAD_DATA;
        throw( stcErr );
      }
    }
  }
  catch ( modelErr & err )
  {
    delete[] p_fTempValues;
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    delete[] p_fTempValues;
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    delete[] p_fTempValues;
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clMichMenPhotoinhibition::DoShellSetup" ;
    throw( stcErr );
  }
}
////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
////////////////////////////////////////////////////////////////////////////
void clTempDependentNeighborhoodDisperse::DoShellSetup( DOMDocument * p_oDoc )
{
    doubleVal * p_fTempValues = NULL; //for getting species-specific values
    try
    {
        clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
        DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
        int iNumTotalSpecies = p_oPop->GetNumberOfSpecies();
        short int i; //loop counter

        //Get the minimum sapling height
        m_fMinSaplingHeight = 50;
        for ( i = 0; i < iNumTotalSpecies; i++ )
            if ( p_oPop->GetMaxSeedlingHeight( i ) < m_fMinSaplingHeight )
                m_fMinSaplingHeight = p_oPop->GetMaxSeedlingHeight( i );

        //Declare the temp array and populate it with the species to which this
        //behavior applies
        p_fTempValues = new doubleVal[m_iNumBehaviorSpecies];
        for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
            p_fTempValues[i].code = mp_iWhatSpecies[i];

        //Declare the arrays for holding the variables
        mp_fA = new double[iNumTotalSpecies];
        mp_fB = new double[iNumTotalSpecies];
        mp_fFecM = new double[iNumTotalSpecies];
        mp_fFecN = new double[iNumTotalSpecies];
        mp_fPresB = new double[iNumTotalSpecies];
        mp_fPresM = new double[iNumTotalSpecies];
        mp_fThreshold = new double[iNumTotalSpecies];

        //Capture the values from the parameter file

        //Fecundity M
        FillSpeciesSpecificValue( p_oElement, "di_tempDepNeighFecM",
                                  "di_tdnfmVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
        //Transfer to the appropriate array buckets
        for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
            mp_fFecM[p_fTempValues[i].code] = p_fTempValues[i].val;

        //Fecundity N
        FillSpeciesSpecificValue( p_oElement, "di_tempDepNeighFecN",
                                  "di_tdnfnVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
        //Transfer to the appropriate array buckets
        for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
            mp_fFecN[p_fTempValues[i].code] = p_fTempValues[i].val;

        //Presence M
        FillSpeciesSpecificValue( p_oElement, "di_tempDepNeighPresM",
                                  "di_tdnpmVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
        //Transfer to the appropriate array buckets
        for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
            mp_fPresM[p_fTempValues[i].code] = p_fTempValues[i].val;

        //Presence B
        FillSpeciesSpecificValue( p_oElement, "di_tempDepNeighPresB",
                                  "di_tdnpbVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
        //Transfer to the appropriate array buckets
        for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
            mp_fPresB[p_fTempValues[i].code] = p_fTempValues[i].val;

        //Presence threshold
        FillSpeciesSpecificValue( p_oElement, "di_tempDepNeighPresThreshold",
                                  "di_tdnptVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
        //Transfer to the appropriate array buckets
        for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
            mp_fThreshold[p_fTempValues[i].code] = p_fTempValues[i].val;
        //Reinforce zero and one to ensure that proper behavior occurs
        for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
            if (mp_fThreshold[mp_iWhatSpecies[i]] < 1e-5)
                mp_fThreshold[mp_iWhatSpecies[i]] = -0.01;
            if (mp_fThreshold[mp_iWhatSpecies[i]] > (1 - 1e-5))
                mp_fThreshold[mp_iWhatSpecies[i]] = 1.01;
        }

        //A
        FillSpeciesSpecificValue( p_oElement, "di_tempDepNeighA",
                                  "di_tdnaVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
        //Transfer to the appropriate array buckets
        for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
            mp_fA[p_fTempValues[i].code] = p_fTempValues[i].val;

        //B
        FillSpeciesSpecificValue( p_oElement, "di_tempDepNeighB",
                                  "di_tdnbVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
        //Transfer to the appropriate array buckets
        for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
            mp_fB[p_fTempValues[i].code] = p_fTempValues[i].val;

        //Neighborhood search radius
        FillSingleValue(p_oElement, "di_tempDepNeighRadius", &m_fRadius, true );

        //Check to see if presence testing is required for this run. If all values
        //in the threshold parameter are zero, it is not. Set a flag to save
        //processing later.
        m_bDoPresenceTesting = false;
        for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
            if ( mp_fThreshold[mp_iWhatSpecies[i]] > 0 ) {
                m_bDoPresenceTesting = true;
                break;
            }
        }
        delete[] p_fTempValues;

    }
    catch ( modelErr & err )
    {
        delete[] p_fTempValues;
        throw( err );
    }
    catch ( modelMsg & msg )
    {
        delete[] p_fTempValues;
        throw( msg );
    } //non-fatal error
    catch ( ... )
    {
        delete[] p_fTempValues;
        modelErr stcErr;
        stcErr.iErrorCode = UNKNOWN;
        stcErr.sFunction = "clTempDependentNeighborhoodDisperse::DoShellSetup" ;
        throw( stcErr );
    }
}
////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
////////////////////////////////////////////////////////////////////////////
void clStochDoubleLogTempDepNeighDisperse::DoShellSetup( DOMDocument * p_oDoc )
{
  doubleVal * p_fTempValues = NULL; //for getting species-specific values
  try
  {
    clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    int iNumTotalSpecies = p_oPop->GetNumberOfSpecies();
    short int i; //loop counter

    //Get the minimum sapling height
    m_fMinSaplingHeight = 50;
    for ( i = 0; i < iNumTotalSpecies; i++ )
      if ( p_oPop->GetMaxSeedlingHeight( i ) < m_fMinSaplingHeight )
        m_fMinSaplingHeight = p_oPop->GetMaxSeedlingHeight( i );

    //Declare the temp array and populate it with the species to which this
    //behavior applies
    p_fTempValues = new doubleVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    //Declare the arrays for holding the variables
    mp_fPA = new double[iNumTotalSpecies];
    mp_fPB = new double[iNumTotalSpecies];
    mp_fPM = new double[iNumTotalSpecies];
    mp_fAl = new double[iNumTotalSpecies];
    mp_fBl = new double[iNumTotalSpecies];
    mp_fCl = new double[iNumTotalSpecies];
    mp_fAh = new double[iNumTotalSpecies];
    mp_fBh = new double[iNumTotalSpecies];
    mp_fCh = new double[iNumTotalSpecies];
    mp_fA = new double[iNumTotalSpecies];
    mp_fB = new double[iNumTotalSpecies];

    //Capture the values from the parameter file

    //PA
    FillSpeciesSpecificValue( p_oElement, "di_stochDoubLogTempDepNeighPA",
        "di_sdltdnpaVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fPA[p_fTempValues[i].code] = p_fTempValues[i].val;

    //PB
    FillSpeciesSpecificValue( p_oElement, "di_stochDoubLogTempDepNeighPB",
        "di_sdltdnpbVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fPB[p_fTempValues[i].code] = p_fTempValues[i].val;

    //PM
    FillSpeciesSpecificValue( p_oElement, "di_stochDoubLogTempDepNeighPM",
        "di_sdltdnpmVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fPM[p_fTempValues[i].code] = p_fTempValues[i].val;

    //A
    FillSpeciesSpecificValue( p_oElement, "di_stochDoubLogTempDepNeighA",
        "di_sdltdnaVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fA[p_fTempValues[i].code] = p_fTempValues[i].val;

    //B
    FillSpeciesSpecificValue( p_oElement, "di_stochDoubLogTempDepNeighB",
        "di_sdltdnbVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fB[p_fTempValues[i].code] = p_fTempValues[i].val;

    //Neighborhood search radius
    FillSingleValue(p_oElement, "di_stochDoubLogTempDepNeighRadius", &m_fRadius, true );

    //Original analysis plot size, square meters
    FillSingleValue(p_oElement, "di_stochDoubLogTempDepNeighPlotSize", &m_fAnalysisPlotSize, true );

    //Deterministic or Poisson seed distribution
    FillSingleValue(p_oElement, "di_stochDoubLogTempDepNeighDeterministic", &m_bDeterministic, false );

    //Use temperature dependent portion of fecundity
    FillSingleValue(p_oElement, "di_stochDoubLogTempDepNeighTempFec", &m_bFecTempDep, true );

    //T, in years, to go from cumulative to annualized probability
    FillSingleValue(p_oElement, "di_stochDoubLogTempDepNeighT", &m_fAnnualizePeriod, true );

    //If we are using temperature dependent fecundity, get those values
    if (m_bFecTempDep) {
      //Al
      FillSpeciesSpecificValue( p_oElement, "di_stochDoubLogTempDepNeighAl",
          "di_sdltdnalVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
      //Transfer to the appropriate array buckets
      for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
        mp_fAl[p_fTempValues[i].code] = p_fTempValues[i].val;

      //Bl
      FillSpeciesSpecificValue( p_oElement, "di_stochDoubLogTempDepNeighBl",
          "di_sdltdnblVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
      //Transfer to the appropriate array buckets
      for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
        mp_fBl[p_fTempValues[i].code] = p_fTempValues[i].val;

      //Cl
      FillSpeciesSpecificValue( p_oElement, "di_stochDoubLogTempDepNeighCl",
          "di_sdltdnclVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
      //Transfer to the appropriate array buckets
      for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
        mp_fCl[p_fTempValues[i].code] = p_fTempValues[i].val;

      //Ah
      FillSpeciesSpecificValue( p_oElement, "di_stochDoubLogTempDepNeighAh",
          "di_sdltdnahVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
      //Transfer to the appropriate array buckets
      for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
        mp_fAh[p_fTempValues[i].code] = p_fTempValues[i].val;

      //Bh
      FillSpeciesSpecificValue( p_oElement, "di_stochDoubLogTempDepNeighBh",
          "di_sdltdnbhVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
      //Transfer to the appropriate array buckets
      for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
        mp_fBh[p_fTempValues[i].code] = p_fTempValues[i].val;

      //Ch
      FillSpeciesSpecificValue( p_oElement, "di_stochDoubLogTempDepNeighCh",
          "di_sdltdnchVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
      //Transfer to the appropriate array buckets
      for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
        mp_fCh[p_fTempValues[i].code] = p_fTempValues[i].val;
    }

    delete[] p_fTempValues;

  }
  catch ( modelErr & err )
  {
    delete[] p_fTempValues;
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    delete[] p_fTempValues;
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    delete[] p_fTempValues;
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clStochDoubleLogTempDepNeighDisperse::DoShellSetup" ;
    throw( stcErr );
  }
}
//////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
//////////////////////////////////////////////////////////////////////////////
void clPRSemiStochGrowth::DoShellSetup( DOMDocument * p_oDoc )
{
  try
  {
    clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    floatVal * p_fTempValues; //for getting species-specific values
    short int iNumSpecies = p_oPop->GetNumberOfSpecies(), i;

    //Make the list of indexes
    mp_iIndexes = new short int[iNumSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_iIndexes[mp_iWhatSpecies[i]] = i;

    //Declare the arrays we'd like read
    mp_fHeightThreshold = new float[m_iNumBehaviorSpecies];
    mp_fA = new float[m_iNumBehaviorSpecies];
    mp_fB = new float[m_iNumBehaviorSpecies];
    mp_fMeanDiam = new float[m_iNumBehaviorSpecies];
    mp_fDiamStdDev = new float[m_iNumBehaviorSpecies];

    //Declare the species-specific temp array and pre-load with the species that
    //this behavior affects
    p_fTempValues = new floatVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    //Height threshold for stochastic growth
    FillSpeciesSpecificValue( p_oElement, "gr_prStochHiteThreshold", "gr_pshtVal", p_fTempValues,
        m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fHeightThreshold[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

    //"a" for deterministic growth
    FillSpeciesSpecificValue( p_oElement, "gr_prStochDetermA", "gr_psdaVal", p_fTempValues,
        m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fA[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

    //"b" for deterministic growth
    FillSpeciesSpecificValue( p_oElement, "gr_prStochDetermB", "gr_psdbVal", p_fTempValues,
        m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fB[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

    //Mean diam for stochastic growth
    FillSpeciesSpecificValue( p_oElement, "gr_prStochMeanDBH", "gr_psmdVal", p_fTempValues,
        m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fMeanDiam[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

    //Standard deviation for stochastic growth
    FillSpeciesSpecificValue( p_oElement, "gr_prStochStdDev", "gr_pssdVal", p_fTempValues,
        m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fDiamStdDev[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

    delete[] p_fTempValues;
  }
  catch ( modelErr & err )
  {
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clPRSemiStochGrowth::DoShellSetup" ;
    throw( stcErr );
  }
}
////////////////////////////////////////////////////////////////////////////
// ReadParameterFile()
////////////////////////////////////////////////////////////////////////////
void clWeibullClimateQuadratGrowth::ReadParameterFile(
    xercesc::DOMDocument * p_oDoc, clTreePopulation *p_oPop )
{
  try
  {
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    floatVal * p_fTempValues; //for getting species-specific values
    short int iNumTotalSpecies = p_oPop->GetNumberOfSpecies(),
              i; //loop counter

    m_fMinSaplingHeight = 50;

    //Get the minimum sapling height
    for ( i = 0; i < iNumTotalSpecies; i++ )
    {
      if ( p_oPop->GetMaxSeedlingHeight( i ) < m_fMinSaplingHeight )
      {
        m_fMinSaplingHeight = p_oPop->GetMaxSeedlingHeight( i );
      }
    }

    //Make the list of indexes
    mp_iIndexes = new short int[iNumTotalSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_iIndexes[mp_iWhatSpecies[i]] = i;

    //This alone is sized total number of species
    mp_fMinimumNeighborDBH = new float[iNumTotalSpecies];

    //The rest are sized number of species to which this behavior applies
    mp_fCompC = new float[m_iNumBehaviorSpecies];
    mp_fCompD = new float[m_iNumBehaviorSpecies];
    mp_fPrecipA = new float[m_iNumBehaviorSpecies];
    mp_fPrecipB = new float[m_iNumBehaviorSpecies];
    mp_fPrecipC = new float[m_iNumBehaviorSpecies];
    mp_fTempA = new float[m_iNumBehaviorSpecies];
    mp_fTempB = new float[m_iNumBehaviorSpecies];
    mp_fTempC = new float[m_iNumBehaviorSpecies];
    mp_fMaxRG = new float[m_iNumBehaviorSpecies];

    //Set up our floatVal array that will extract values only for the species
    //assigned to this behavior
    p_fTempValues = new floatVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    //Fill the variables

    //Maximum potential growth
    FillSpeciesSpecificValue( p_oElement, "gr_weibClimQuadMaxGrowth", "gr_wcqmgVal", p_fTempValues,
         m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fMaxRG[i] = p_fTempValues[i].val;

    //Max crowding radius
    FillSingleValue( p_oElement, "gr_weibClimQuadMaxNeighRad", &m_fMaxCrowdingRadius, true );

    //Minimum neighbor DBH
    FillSpeciesSpecificValue( p_oElement, "gr_weibClimQuadMinNeighDBH",
        "gr_wcqmndVal", mp_fMinimumNeighborDBH, p_oPop, true );

    //C
    FillSpeciesSpecificValue( p_oElement, "gr_weibClimQuadCompEffC",
        "gr_wcqcecVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fCompC[i] = p_fTempValues[i].val;

    //D
    FillSpeciesSpecificValue( p_oElement, "gr_weibClimQuadCompEffD",
        "gr_wcqcedVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fCompD[i] = p_fTempValues[i].val;

    //temperature effect a
    FillSpeciesSpecificValue( p_oElement, "gr_weibClimQuadTempEffA",
        "gr_wcqteaVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fTempA[i] = p_fTempValues[i].val;

    //temperature effect b
    FillSpeciesSpecificValue( p_oElement, "gr_weibClimQuadTempEffB",
        "gr_wcqtebVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fTempB[i] = p_fTempValues[i].val;

    //temperature effect c
    FillSpeciesSpecificValue( p_oElement, "gr_weibClimQuadTempEffC",
        "gr_wcqtecVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fTempC[i] = p_fTempValues[i].val;

    //precipitation effect a
    FillSpeciesSpecificValue( p_oElement, "gr_weibClimQuadPrecipEffA",
        "gr_wcqpeaVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fPrecipA[i] = p_fTempValues[i].val;

    //precipitation effect b
    FillSpeciesSpecificValue( p_oElement, "gr_weibClimQuadPrecipEffB",
        "gr_wcqpebVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fPrecipB[i] = p_fTempValues[i].val;

    //precipitation effect c
    FillSpeciesSpecificValue( p_oElement, "gr_weibClimQuadPrecipEffC",
        "gr_wcqpecVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fPrecipC[i] = p_fTempValues[i].val;

    delete[] p_fTempValues;
  }
  catch ( modelErr & err )
  {
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    strcpy( stcErr.cFunction, "clWeibullClimateQuadratGrowth::ReadParameterFile" );
    throw( stcErr );
  }
}
//////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
//////////////////////////////////////////////////////////////////////////////
void clRelativeGrowth::DoShellSetup( DOMDocument * p_oDoc )
{
  try
  {
    clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    doubleVal * p_fTempValues; //for getting species-specific values
    short int iNumSpecies = mp_oGrowthOrg->GetNumberOfSpecies(), i;

    //Set up our doubleVal array that will extract values only for the species
    //assigned to this behavior
    p_fTempValues = new doubleVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    m_iNumberYearsPerTimestep = mp_oSimManager->GetNumberOfYearsPerTimestep();

    //Declare the arrays we'd like read
    if (diameter_auto == m_iGrowthMethod || diameter_only == m_iGrowthMethod) {
      mp_fAsympDiamGrowth = new double[iNumSpecies];
      mp_fSlopeDiamGrowthResponse = new double[iNumSpecies];
    } else {
      mp_fAsympHeightGrowth = new double[iNumSpecies];
      mp_fSlopeHeightGrowthResponse = new double[iNumSpecies];
    }

    mp_fExp = new double[iNumSpecies];

    if ( m_bConstRadialLimited )
    {
      mp_fAdultConstRadInc = new double[iNumSpecies];
    }

    if ( m_bConstBasalAreaLimited )
    {
      mp_fAdultConstBAInc = new double[iNumSpecies];
    }

    //Read the base variables
    GetParameterFileData( p_oDoc );

    if (diameter_auto == m_iGrowthMethod || diameter_only == m_iGrowthMethod) {
      //Get the diameter exponent
      FillSpeciesSpecificValue( p_oElement, "gr_relGrowthDiamExp", "gr_rgdeVal", p_fTempValues,
           m_iNumBehaviorSpecies, p_oPop, true );
    } else {
      //Get the height exponent
      FillSpeciesSpecificValue( p_oElement, "gr_relHeightGrowthHeightExp", "gr_rhgheVal", p_fTempValues,
           m_iNumBehaviorSpecies, p_oPop, true );
    }

    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fExp[p_fTempValues[i].code] = p_fTempValues[i].val;


    //Make sure all species/type combos have "Light" registered
    for ( int i = 0; i < m_iNumSpeciesTypeCombos; i++ )
    {
      if ( -1 == mp_oGrowthOrg->GetLightCode(mp_whatSpeciesTypeCombos[i].iSpecies,
                                           mp_whatSpeciesTypeCombos[i].iType ) )
      {
        modelErr stcErr;
        stcErr.sFunction = "clRelativeGrowth::DoShellSetup";
        std::stringstream s;
        s << "Type/species combo species="
          << mp_whatSpeciesTypeCombos[i].iSpecies << " type="
          << mp_whatSpeciesTypeCombos[i].iType
          << " does not have a required light behavior.";
        stcErr.sMoreInfo = s.str();
        stcErr.iErrorCode = BAD_DATA;
        throw( stcErr );
      }
    }

    delete[] p_fTempValues;
  }
  catch ( modelErr & err )
  {
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clRelativeGrowth::DoShellSetup" ;
    throw( stcErr );
  }
}
////////////////////////////////////////////////////////////////////////////
// ReadParameterFile()
////////////////////////////////////////////////////////////////////////////
void clLaggedPostHarvestGrowth::ReadParameterFile( xercesc::DOMDocument * p_oDoc )
{
  try
  {
    clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    doubleVal * p_fTempValues; //for getting species-specific values

    short int i; //loop counters

    mp_iIndexes = new short int[m_iNumTotalSpecies];

    //The rest are sized number of species to which this behavior applies
    mp_fMaxGrowthConstant = new double[m_iNumBehaviorSpecies];
    mp_fMaxGrowthDbhEffect = new double[m_iNumBehaviorSpecies];
    mp_fNciConstant = new double[m_iNumBehaviorSpecies];
    mp_fNciDbhEffect = new double[m_iNumBehaviorSpecies];
    mp_fTimeSinceHarvestRateParam = new double[m_iNumBehaviorSpecies];


    //If any of the types is seedling, error out
    for ( i = 0; i < m_iNumSpeciesTypeCombos; i++ )
      if ( clTreePopulation::sapling != mp_whatSpeciesTypeCombos[i].iType
          && clTreePopulation::adult != mp_whatSpeciesTypeCombos[i].iType )
      {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clLaggedPostHarvestGrowth::ReadParameterFile" ;
        stcErr.sMoreInfo = "This behavior can only be applied to saplings and adults.";
        throw( stcErr );
      }

    //Make the list of indexes
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_iIndexes[mp_iWhatSpecies[i]] = i;

    //Set up our doubleVal array that will extract values only for the species
    //assigned to this behavior
    p_fTempValues = new doubleVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    //Fill the variables

    //Multiplier constant in Max potential growth term
    FillSpeciesSpecificValue( p_oElement, "gr_lagMaxGrowthConstant", "gr_lmgcVal", p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fMaxGrowthConstant[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

    //Effect of DBH on max potential growth term
    FillSpeciesSpecificValue( p_oElement, "gr_lagMaxGrowthDbhEffect", "gr_lmgdbheVal", p_fTempValues,
        m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fMaxGrowthDbhEffect[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

    //Effect of NCI on growth
    FillSpeciesSpecificValue( p_oElement, "gr_lagNciConstant", "gr_lncicVal", p_fTempValues,
        m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fNciConstant[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

    //Effect of DBH on NCI term
    FillSpeciesSpecificValue( p_oElement, "gr_lagNciDbhEffect", "gr_lncidbheVal", p_fTempValues,
        m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fNciDbhEffect[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

    //Rate parameter for time since harvest lag effect
    FillSpeciesSpecificValue( p_oElement, "gr_lagTimeSinceHarvestRateParam", "gr_ltshrpVal", p_fTempValues,
        m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer to the appropriate array buckets
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      mp_fTimeSinceHarvestRateParam[mp_iIndexes[p_fTempValues[i].code]] = p_fTempValues[i].val;

    //NCI radius
    FillSingleValue( p_oElement, "gr_lagNciDistanceRadius", & m_fNciDistanceRadius, true );


    delete[] p_fTempValues;
  }
  catch ( modelErr & err )
  {
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clLaggedPostHarvestGrowth::ReadParameterFile" ;
    throw( stcErr );
  }
}
////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
////////////////////////////////////////////////////////////////////////////
void clInsectInfestationMortality::DoShellSetup( xercesc::DOMDocument * p_oDoc )
{
  doubleVal * p_fTempValues = NULL; //for getting species-specific values
  try
  {
    clTreePopulation * p_oPop = ( clTreePopulation * ) mp_oSimManager->GetPopulationObject( "treepopulation" );
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    short int i, j, iNumTypes = p_oPop->GetNumberOfTypes();

    m_iNumSpecies = p_oPop->GetNumberOfSpecies();

    //Declare the arrays we'd like read
    mp_fIntercept = new double[m_iNumSpecies];
    mp_fMax = new double[m_iNumSpecies];
    mp_fX0 = new double[m_iNumSpecies];
    mp_fXb = new double[m_iNumSpecies];

    //Declare the species-specific temp array and pre-load with the species
    //that this behavior affects
    p_fTempValues = new doubleVal[m_iNumBehaviorSpecies];
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];

    //Intercept
    FillSpeciesSpecificValue( p_oElement, "mo_insectMortIntercept", "mo_imiVal",
        p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array, making sure all values are
    //between 0 and 1
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if ( 0 > p_fTempValues[i].val || 1 < p_fTempValues[i].val ) {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clInsectInfestationMortality::DoShellSetup" ;
        stcErr.sMoreInfo = "All values for mortality intercept must be between 0 and 1.";
        throw( stcErr );
      }
      mp_fIntercept[p_fTempValues[i].code] = p_fTempValues[i].val;
    }

    //Max mortality probability
    FillSpeciesSpecificValue( p_oElement, "mo_insectMortMaxRate", "mo_immrVal",
        p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array, making sure all values are
    //between 0 and 1
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if ( 0 > p_fTempValues[i].val || 1 < p_fTempValues[i].val ) {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clInsectInfestationMortality::DoShellSetup" ;
        stcErr.sMoreInfo = "All values for max mortality must be between 0 and 1.";
        throw( stcErr );
      }
      mp_fMax[p_fTempValues[i].code] = p_fTempValues[i].val;
    }

    //X0
    FillSpeciesSpecificValue( p_oElement, "mo_insectMortX0", "mo_imx0Val",
        p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array, making sure no values are 0
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      if ( 0 == p_fTempValues[i].val) {
        modelErr stcErr;
        stcErr.iErrorCode = BAD_DATA;
        stcErr.sFunction = "clInsectInfestationMortality::DoShellSetup" ;
        stcErr.sMoreInfo = "Values for insect mortality X0 cannot be 0.";
        throw( stcErr );
      }
      mp_fX0[p_fTempValues[i].code] = p_fTempValues[i].val;
    }

    //Xb
    FillSpeciesSpecificValue( p_oElement, "mo_insectMortXb", "mo_imxbVal",
        p_fTempValues, m_iNumBehaviorSpecies, p_oPop, true );
    //Transfer values to our permanent array
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ ) {
      mp_fXb[p_fTempValues[i].code] = p_fTempValues[i].val;
    }

    //Collect the "YearsInfested" codes
    mp_iDataCodes = new short int *[m_iNumSpecies];
    for (i = 0; i < m_iNumSpecies; i++) {
      mp_iDataCodes[i] = new short int[iNumTypes];
      for (j = 0; j < iNumTypes; j++) {
        mp_iDataCodes[i][j] = -1;
      }
    }
    for (i = 0; i < m_iNumSpeciesTypeCombos; i++ )
    {
      mp_iDataCodes[mp_whatSpeciesTypeCombos[i].iSpecies]
                      [mp_whatSpeciesTypeCombos[i].iType] =
            p_oPop->GetIntDataCode("YearsInfested",
                                    mp_whatSpeciesTypeCombos[i].iSpecies,
                                    mp_whatSpeciesTypeCombos[i].iType );
      if (-1 == mp_iDataCodes[mp_whatSpeciesTypeCombos[i].iSpecies]
                                 [mp_whatSpeciesTypeCombos[i].iType] )
      {
        modelErr stcErr;
        stcErr.sFunction = "clInsectInfestationMortality::DoShellSetup" ;
        std::stringstream s;
        s << "Type/species combo species="
          << mp_whatSpeciesTypeCombos[i].iSpecies << " type="
          << mp_whatSpeciesTypeCombos[i].iType
          << " does not have the insect infestation behavior.";
        stcErr.iErrorCode = BAD_DATA;
        throw( stcErr );
      }
    }

    delete[] p_fTempValues;

    //Pre-calculate mortalities
    m_iMaxMortTime = 0;
    for (i = 0; i < m_iNumBehaviorSpecies; i++) {
      if ((int)(mp_fX0[mp_iWhatSpecies[i]] * 2) > m_iMaxMortTime)
        m_iMaxMortTime = (int)(mp_fX0[mp_iWhatSpecies[i]] * 2);
    }
    m_iMaxMortTime++;
    mp_fMortProbs = new double *[m_iNumSpecies];
    for (i = 0; i < m_iNumSpecies; i++) {
      mp_fMortProbs[i] = new double[m_iMaxMortTime];
      for (j = 0; j < m_iMaxMortTime; j++) mp_fMortProbs[i][j] = 0;
    }

    for (i = 0; i < m_iNumBehaviorSpecies; i++) {
      for (j = 1; j < m_iMaxMortTime; j++) {
        mp_fMortProbs[mp_iWhatSpecies[i]][j] = mp_fIntercept[mp_iWhatSpecies[i]] +
        ((mp_fMax[mp_iWhatSpecies[i]] - mp_fIntercept[mp_iWhatSpecies[i]])/
            (1+pow(j/mp_fX0[mp_iWhatSpecies[i]], mp_fXb[mp_iWhatSpecies[i]])));
      }
    }
  }
  catch ( modelErr & err )
  {
    delete[] p_fTempValues;
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    delete[] p_fTempValues;
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    delete[] p_fTempValues;
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clInsectInfestationMortality::DoShellSetup" ;
    throw( stcErr );
  }
}
//////////////////////////////////////////////////////////////////////////////
// DoShellSetup()
//////////////////////////////////////////////////////////////////////////////
void clDoubleMMRelGrowth::DoShellSetup( DOMDocument * p_oDoc )
{
  doubleVal * p_fTempValues = NULL;
  try
  {
    short int iNumSpecies = mp_oGrowthOrg->GetNumberOfSpecies(), i;

    m_iNumberYearsPerTimestep = mp_oSimManager->GetNumberOfYearsPerTimestep();

    //Declare the arrays we'd like read
    mp_fAsympDiamGrowth = new double[iNumSpecies];
    mp_fSlopeDiamGrowthResponse = new double[iNumSpecies];
    mp_fResourceInfluence = new double[iNumSpecies];

    //Read the base variables with the base class function
    GetParameterFileData( p_oDoc );

    //Now read this behavior's additional parameter
    DOMElement * p_oElement = GetParentParametersElement(p_oDoc);
    p_fTempValues = new doubleVal[m_iNumBehaviorSpecies];
    clTreePopulation *p_oPop = (clTreePopulation*) mp_oSimManager->GetPopulationObject("treepopulation");
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      p_fTempValues[i].code = mp_iWhatSpecies[i];
    FillSpeciesSpecificValue( p_oElement, "gr_diamDoubleMMResourceInfluence", "gr_ddmmriVal", p_fTempValues,
        m_iNumBehaviorSpecies, p_oPop, true );
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
    {
      mp_fResourceInfluence[p_fTempValues[i].code] = p_fTempValues[i].val;
    }

    //UNSCALE the slope of growth response parameter to undo what the base
    //function did because we don't want it
    for ( i = 0; i < m_iNumBehaviorSpecies; i++ )
      if ( mp_fSlopeDiamGrowthResponse[mp_iWhatSpecies[i]] != 0.0 )
        mp_fSlopeDiamGrowthResponse[mp_iWhatSpecies[i]] =
            ( 1 / mp_fSlopeDiamGrowthResponse[mp_iWhatSpecies[i]] ) * mp_fAsympDiamGrowth[mp_iWhatSpecies[i]];

    //Make sure all species/type combos have "Light" registered
    for ( i = 0; i < m_iNumSpeciesTypeCombos; i++ )
    {
      if ( -1 == mp_oGrowthOrg->GetLightCode( mp_whatSpeciesTypeCombos[i].iSpecies, mp_whatSpeciesTypeCombos[i].iType ) )
      {
        modelErr stcErr;
        stcErr.sFunction = "clDoubleMMRelGrowth::DoShellSetup" ;
        std::stringstream s;
        s << "Type/species combo species="
          << mp_whatSpeciesTypeCombos[i].iSpecies << " type="
          << mp_whatSpeciesTypeCombos[i].iType
          << " does not have a required light behavior.";
        stcErr.sMoreInfo = s.str();
        stcErr.iErrorCode = BAD_DATA;
        throw( stcErr );
      }
    }

    //Get the "Resource" grid
    mp_oResourceGrid = mp_oSimManager->GetGridObject( "Resource" );
    if ( NULL == mp_oResourceGrid )
    {
      modelErr stcErr;
      stcErr.sFunction = "clDoubleMMRelGrowth::DoShellSetup" ;
      stcErr.sMoreInfo = "Can't find required grid object \"Resources\".";
      stcErr.iErrorCode = CANT_FIND_OBJECT;
      throw( stcErr );
    }

    m_iResourceCode = mp_oResourceGrid->GetFloatDataCode( "Resource" );
    if ( -1 == m_iResourceCode )
    {
      modelErr stcErr;
      stcErr.sFunction = "clDoubleMMRelGrowth::DoShellSetup" ;
      stcErr.sMoreInfo = "Grid object \"Resources\" is set up incorrectly.";
      stcErr.iErrorCode = CANT_FIND_OBJECT;
      throw( stcErr );
    }

    delete[] p_fTempValues;
  }
  catch ( modelErr & err )
  {
    delete[] p_fTempValues;
    throw( err );
  }
  catch ( modelMsg & msg )
  {
    delete[] p_fTempValues;
    throw( msg );
  } //non-fatal error
  catch ( ... )
  {
    delete[] p_fTempValues;
    modelErr stcErr;
    stcErr.iErrorCode = UNKNOWN;
    stcErr.sFunction = "clDoubleMMRelGrowth::DoShellSetup" ;
    throw( stcErr );
  }
}