public void LocalComputeMethod() { CohortDefoliation.Delegates.Compute computeMethod = CohortDefoliation.Compute; try { CohortDefoliation.Compute = MyCompute; myComputeCalled = false; Assert.AreEqual(myComputeResult, CohortDefoliation.Compute(myCohort, myActiveSite, mySiteBiomass)); Assert.IsTrue(myComputeCalled); } finally { // Restore the compute delegate. CohortDefoliation.Compute = computeMethod; } }
//--------------------------------------------------------------------- /// <summary> /// Computes the change in a cohort's biomass due to Annual Net Primary /// Productivity (ANPP), age-related mortality (M_AGE), and development- /// related mortality (M_BIO). /// </summary> public int ComputeChange(ICohort cohort, ActiveSite site) { ecoregion = PlugIn.ModelCore.Ecoregion[site]; int siteBiomass = SiteVars.TotalBiomass[site]; //Save the pre-growth root biomass. This needs to be calculated BEFORE growth and mortality double TotalRoots = Roots.CalculateRootBiomass(site, cohort.Species, cohort.Biomass); SiteVars.soilClass[site].CollectRootBiomass(TotalRoots, 0); // First, calculate age-related mortality. // Age-related mortality will include woody and standing leaf biomass (=0 for deciduous trees). double mortalityAge = ComputeAgeMortality(cohort); double actualANPP = ComputeActualANPP(cohort, site, siteBiomass, SiteVars.PreviousYearMortality[site]); // Age mortality is discounted from ANPP to prevent the over- // estimation of mortality. ANPP cannot be negative. actualANPP = Math.Max(1, actualANPP - mortalityAge); // Growth-related mortality double mortalityGrowth = ComputeGrowthMortality(cohort, site, siteBiomass); // Age-related mortality is discounted from growth-related // mortality to prevent the under-estimation of mortality. Cannot be negative. mortalityGrowth = Math.Max(0, mortalityGrowth - mortalityAge); // Also ensure that growth mortality does not exceed actualANPP. mortalityGrowth = Math.Min(mortalityGrowth, actualANPP); // Total mortality for the cohort double totalMortality = mortalityAge + mortalityGrowth; if (totalMortality > cohort.Biomass) { throw new ApplicationException("Error: Mortality exceeds cohort biomass"); } // Defoliation ranges from 1.0 (total) to none (0.0). defoliation = CohortDefoliation.Compute(cohort, site, siteBiomass); double defoliationLoss = 0.0; if (defoliation > 0) { double standing_nonwood = ComputeFractionANPPleaf(cohort.Species) * actualANPP; defoliationLoss = standing_nonwood * defoliation; SiteVars.soilClass[site].DisturbanceImpactsDOM(site, "defol", 0); //just soil impacts. Dist impacts are handled differently?? } int deltaBiomass = (int)(actualANPP - totalMortality - defoliationLoss); double newBiomass = cohort.Biomass + (double)deltaBiomass; double totalLitter = UpdateDeadBiomass(cohort, actualANPP, totalMortality, site, newBiomass); //if (site.Location.Row == 279 && site.Location.Column == 64 && cohort.Species.Name == "Pl") //{ // PlugIn.ModelCore.UI.WriteLine("Yr={0}, Age={1}, mortGrow={2}, mortAge={3}, ANPP={4}, totLitter={5}", PlugIn.ModelCore.CurrentTime, cohort.Age, mortalityGrowth, mortalityAge, actualANPP, totalLitter); // } //if (cohort.Species.Name == "pinubank") //{ //PlugIn.ModelCore.UI.WriteLine("Age={0}, ANPPact={1:0.0}, M={2:0.0}, litter={3:0.00}.", cohort.Age, actualANPP, totalMortality, totalLitter); //PlugIn.ModelCore.UI.WriteLine("Name={0}, Age={1}, B={2}, ANPPact={3:0.0}, delta={4:0.0}", cohort.Species.Name, cohort.Age, cohort.Biomass, actualANPP, deltaBiomass); // PlugIn.ModelCore.UI.WriteLine("Name={0}, Age={1}, B={2}, Mage={3:0.0}, Mgrowth={4:0.0}, ANPPact={5:0.0}, delta={6:0.0}, newbiomass={7:0.0}", cohort.Species.Name, cohort.Age, cohort.Biomass, mortalityAge, mortalityGrowth, actualANPP, deltaBiomass, newBiomass); //} //The KillNow flag indicates that this is the year of growth in which to kill off some cohorts in order to make snags. if (SiteVars.soilClass[site].bKillNow && Snags.bSnagsPresent) { //if (SiteVars.soilClass[site].diedAt == cohort.Age && SiteVars.soilClass[site].spIndex == cohort.Species.Index) //there could be more than one species-age combination, so we have to loop through them. //However, the user has been asked to put the ages in order from smallest to largest, so we can stop looking //as soon as we reach an age that is older than the cohort's age. for (int idx = 0; idx < Snags.NUMSNAGS; idx++) { if (cohort.Age == Snags.DiedAt[idx] && Snags.initSpecIdx[idx] == cohort.Species.Index) { deltaBiomass = -cohort.Biomass; //set biomass to 0 to make core remove this from the list //when this cohort gets passed to the cohort died event, there is no longer any biomass present, so //we have to capture the biomass information here, while we still can. double foliar = (double)cohort.ComputeNonWoodyBiomass(site); double wood = ((double)cohort.Biomass - foliar); Snags.bSnagsUsed[idx] = true; SiteVars.soilClass[site].CollectBiomassMortality(cohort.Species, cohort.Age, wood, foliar, 5 + idx); } if (Snags.DiedAt[idx] > cohort.Age || Snags.DiedAt[idx] == 0) { break; } } } if (deltaBiomass > -cohort.Biomass) { //if we didn't kill this cohort to make a snag, then update the post-growth root biomass. TotalRoots = Roots.CalculateRootBiomass(site, cohort.Species, newBiomass); SiteVars.soilClass[site].CollectRootBiomass(TotalRoots, 1); } return(deltaBiomass); }
public void DefaultIs0() { Assert.AreEqual(0.0, CohortDefoliation.Compute(null, null, 0)); }