Ejemplo n.º 1
0
		//---------------------------------------------------------------------

		private void CheckNeighbor(Site     neighbor,
		                           Location expectedLocation)
		{
			Assert.IsNotNull(neighbor);
			Assert.AreEqual(expectedLocation, neighbor.Location);
			Assert.AreEqual(activeSites[expectedLocation.Row - 1,
			                            expectedLocation.Column - 1],
			                neighbor.IsActive);
		}
 //-------------------------------------------------------
 ///<summary>
 ///Calculate the distance between two Sites
 ///</summary>
 public static double DistanceBetweenSites(Site a, Site b)
 {
 
     int Col = (int) a.Location.Column - (int) b.Location.Column;
     int Row = (int) a.Location.Row - (int) b.Location.Row;
     
     double aSq = System.Math.Pow(Col,2);
     double bSq = System.Math.Pow(Row,2);
     //UI.WriteLine("Col={0}, Row={1}.", Col, Row);
     //UI.WriteLine("aSq={0}, bSq={1}.", aSq, bSq);
     //UI.WriteLine("Distance in Grid Units = {0}.", System.Math.Sqrt(aSq + bSq));
     return (System.Math.Sqrt(aSq + bSq) * (double) Model.Core.CellLength);
 
 }
        //---------------------------------------------------------------------

        TypeIndependent.ISiteCohorts TypeIndependent.ILandscapeCohorts.this[Site site]
        {
            get {
                return cohorts[site];
            }
        }
        //---------------------------------------------------------------------

        public ISiteCohorts this[Site site]
        {
            get {
                return cohorts[site];
            }
        }
        // ---------------------------------------------------------------------
        // This method calculates the initial rate of spread for a specific site.
        // See below for the method that estimates the initial rate of spread for a broad area.
        
        public static double InitialRateOfSpread(double ISI, ISeasonParameters season, Site site)
        {   

            
            int fuelIndex = SiteVars.CFSFuelType[site];
            int PC = SiteVars.PercentConifer[site];
            int PH = SiteVars.PercentHardwood[site];
            int PDF = SiteVars.PercentDeadFir[site];
            
            //UI.WriteLine("Fuel Type Code = {0}.", siteFuelType.ToString());
            
            double RSI = 0.0;  
            
            if (Event.FuelTypeParms[fuelIndex].BaseFuel == BaseFuelType.Conifer ||
                Event.FuelTypeParms[fuelIndex].BaseFuel == BaseFuelType.ConiferPlantation)
            {
                double a = Event.FuelTypeParms[fuelIndex].A;
                double b = Event.FuelTypeParms[fuelIndex].B;
                double c = Event.FuelTypeParms[fuelIndex].C;
                
                double percentHard = (double) PH / 100.0;
                double percentConi = (double) PC / 100.0;
                
                RSI = CalculateRSI(a, b, c, ISI);
                

                if (PDF > 0)
                {
                    if (PH > 0 && season.LeafStatus == LeafOnOff.LeafOn) //M-4
                    {
                        a = 140 * Math.Exp((-1) * 35.5 / (double) PDF);
                        b = 0.0404;
                        c = 3.02 * Math.Exp((-1) * 0.00714 * (double) PDF);
                    }
                    else  //M-3
                    {
                        a = 170 * Math.Exp((-1) * 35 / (double) PDF);
                        b = 0.082 * Math.Exp((-1) * 36 / (double)PDF);
                        c = 1.698 - (0.00303 * PDF);
                    }
                    double MRSI = CalculateRSI(a, b, c, ISI);
                    if (MRSI > RSI)
                        RSI = MRSI;
                }
                
                // These are the classic MIXED CONIFER + DECIDUOUS
                else if (PH > 0)
                {
                    double RSIconifer = RSI;
                    int dIndex = SiteVars.DecidFuelType[site]; //(int)FuelTypeCode.D1;
                    double RSIdecid = CalculateRSI(Event.FuelTypeParms[dIndex].A, Event.FuelTypeParms[dIndex].B, Event.FuelTypeParms[dIndex].C, ISI);

                    if (season.LeafStatus == LeafOnOff.LeafOn)  //M-2
                    {
                        RSI = ((1 - percentHard) * RSIconifer) + (0.2 * percentHard * RSIdecid);
                    }
                    else  //M-1
                    {
                        RSI = ((1 - percentHard) * RSIconifer) + (percentHard * RSIdecid);
                    }

                    //UI.WriteLine("Calculating ROSi for a MIXED type. PH={0}, PC={1}, LeafStatus={2}.", PH, PC, season.LeafStatus);
                    //UI.WriteLine("  RSIcon={0:0.0}, RSIdecid={1:0.0}, RSImix={2:0.000}.", RSIconifer, RSIdecid, RSI);

                }
            }
                

            if (Event.FuelTypeParms[fuelIndex].BaseFuel == BaseFuelType.Open)
            //siteFuelType == FuelTypeCode.O1a)
            {
                double a, b, c;
                int percentCuring = season.PercentCuring;
                
                if(season.NameOfSeason == SeasonName.Spring)  //O1a
                {
                    a = 190; //Event.FuelTypeParms[(int)FuelTypeCode.O1a].A;
                    b = 0.0310; //Event.FuelTypeParms[(int)FuelTypeCode.O1a].B;
                    c = 1.4; //Event.FuelTypeParms[(int)FuelTypeCode.O1a].C;
                }
                else   //O1b
                {
                    a = 250; //Event.FuelTypeParms[(int)FuelTypeCode.O1b].A;
                    b = 0.0350; //Event.FuelTypeParms[(int)FuelTypeCode.O1b].B;
                    c = 1.7; //Event.FuelTypeParms[(int)FuelTypeCode.O1b].C;
                }
                
                double CF = (0.02 * percentCuring) - 1.0;
                RSI = CalculateRSI(a, b, c, ISI);
                if(percentCuring > 50) 
                    RSI *= CF;
                else
                    RSI = 0;
                if (PDF > 0)
                {
                    if (season.LeafStatus == LeafOnOff.LeafOn) //M-4
                    {
                        a = 140 * Math.Exp((-1) * 35.5 / (double)PDF);
                        b = 0.0404;
                        c = 3.02 * Math.Exp((-1) * 0.00714 * (double)PDF);
                    }
                    else //M-3
                    {
                        a = 170 * (Math.Exp(((-1) * 35) / (double)PDF));
                        b = 0.082 * (Math.Exp(((-1) * 36) / (double)PDF));
                        c = 1.698 - (0.00303 * (double)PDF);
                    }
                    double MRSI = CalculateRSI(a, b, c, ISI);
                    if (MRSI > RSI)
                        RSI = MRSI;
                }
            }
            
            if(Event.FuelTypeParms[fuelIndex].BaseFuel == BaseFuelType.NoFuel || fuelIndex == 0)
            //siteFuelType == FuelTypeCode.NoFuel)
            {
                if (PDF > 0)
                {
                    double a=0, b=0, c=0;
                    if (season.LeafStatus == LeafOnOff.LeafOn) //M-4
                    {
                        a = 140 * Math.Exp((-1) * 35.5 / (double)PDF);
                        b = 0.0404;
                        c = 3.02 * Math.Exp((-1) * 0.00714 * (double)PDF);
                    }
                    else //M-3
                    {
                        a = 170 * (Math.Exp(((-1) * 35) / (double)PDF));
                        b = 0.082 * (Math.Exp(((-1) * 36) / (double)PDF));
                        c = 1.698 - (0.00303 * (double)PDF);
                    }
                    RSI = CalculateRSI(a, b, c, ISI);
                }

                else
                {
                    return 0;
                }
            }

            if( Event.FuelTypeParms[fuelIndex].BaseFuel == BaseFuelType.Slash || 
                Event.FuelTypeParms[fuelIndex].BaseFuel == BaseFuelType.Deciduous)
            {
                //UI.WriteLine("Calculating ROSi for a DECIDUOUS or SLASH type.");

                double a = Event.FuelTypeParms[fuelIndex].A;
                double b = Event.FuelTypeParms[fuelIndex].B;
                double c = Event.FuelTypeParms[fuelIndex].C;
                    
                RSI = CalculateRSI(a, b, c, ISI);

                if(Event.FuelTypeParms[fuelIndex].BaseFuel == BaseFuelType.Deciduous 
                    && season.LeafStatus == LeafOnOff.LeafOn)
                //if(siteFuelType == FuelTypeCode.D1 && season.LeafStatus == LeafOnOff.LeafOn)
                    RSI *= 0.2;
                
                if (PDF > 0)
                {
                    if (Event.FuelTypeParms[fuelIndex].BaseFuel == BaseFuelType.Deciduous
                        && season.LeafStatus == LeafOnOff.LeafOn)  //M-4
                    //siteFuelType == FuelTypeCode.D1) 
                    {
                        a = 140 * Math.Exp((-1) * 35.5 / (double) PDF);
                        b = 0.0404;
                        c = 3.02 * Math.Exp((-1) * 0.00714 * (double) PDF);
                    }
                    else //M-3
                    {
                        a = 170 * (Math.Exp(((-1) * 35) / (double) PDF));
                        b = 0.082 * (Math.Exp(((-1) * 36 )/ (double) PDF));
                        c = 1.698 - (0.00303 * (double) PDF);
                    }
                    double MRSI = CalculateRSI(a, b, c, ISI);
                    if (MRSI > RSI)
                        RSI = MRSI;
                }
            }

            
            return RSI;
        }
		//---------------------------------------------------------------------

		private List<Site> GetNeighbors(Site   site,
		                                int    windDirection,
		                                double windSpeed)
		{
			if(windDirection > 7) windDirection = 7;
			double[] windProbs = 
			{
			(((4.0 - windSpeed)/8.0) * (1+windSpeed)), //Primary direction
			(((4.0 - windSpeed)/8.0) * (1+windSpeed)),
			(((4.0 - windSpeed)/8.0)),
			(((4.0 - windSpeed)/8.0) * (1-windSpeed)),
			(((4.0 - windSpeed)/8.0) * (1-windSpeed)), //Opposite of primary direction
			(((4.0 - windSpeed)/8.0) * (1-windSpeed)),
			(((4.0 - windSpeed)/8.0)),
			(((4.0 - windSpeed)/8.0) * (1+windSpeed)),
			};
			
			double windProb = 0.0;
			int index = 0;
			int success = 0;
			List<Site> neighbors = new List<Site>(9);
			foreach (RelativeLocation relativeLoc in neighborhood) 
			{
				Site neighbor = site.GetNeighbor(relativeLoc);

				if(index + windDirection > 7) 
					windProb = windProbs[index + windDirection - 8];
				else 
					windProb = windProbs[index + windDirection];
				//System.Console.WriteLine("WindProb={0:0.00}, windSpeed={1:0.00}, neighbor={2}.", windProb, windSpeed, index+1);
				if (neighbor != null 
					&& Random.GenerateUniform() < windProb)
				{
					neighbors.Add(neighbor);
					success++;
				}
				index++;
			}
			logger.Debug(string.Format("Successfully added {0} neighbors.", success));
			
			//Next, add the 9th neighbor, a neighbor one cell beyond the 
			//8 nearest neighbors.
			//array index 0 = north; 1 = northeast, 2 = east,...,8 = northwest
			int[] vertical  ={2,2,0,-2,-2,-2,0,2};
			int[] horizontal={0,2,2,2,0,-2,-2,-2};

			RelativeLocation relativeLoc9 = 
				new RelativeLocation(vertical[windDirection], horizontal[windDirection]);
			Site neighbor9 = site.GetNeighbor(relativeLoc9);
			if (neighbor9 != null && Random.GenerateUniform() < windSpeed)
				neighbors.Add(neighbor9);
			return neighbors;
		}
 //---------------------------------------------------------------------
 /// <summary>
 /// Determines if a species has at least one mature cohort at a site.
 /// </summary>
 public static bool MaturePresent(ISpecies   species,
     Site       site)
 {
     return cohorts[site].IsMaturePresent(species);
 }
 //---------------------------------------------------------------------
 public static void ResetAnnualValues(Site site)
 {
     // Reset these accumulators to zero:
     SiteVars.AGNPP[site] = 0.0;
 }
        private static List<int> CalculateSlopeEffect(int windSpeed, int windDirection, 
                                                Site site, double RSZ, double f_F,
                                                ISeasonParameters season)
        {
            List<int> siteWindList = new List<int>();
            if (SiteVars.GroundSlope[site] == 0)
            {
                siteWindSpeed = windSpeed;
                siteWindDirection = windDirection;
                //nothing is changed
            }
            else
            {
                FuelTypeCode siteFuelType = (FuelTypeCode)SiteVars.CFSFuelType[site]; ;

                //Walk through the equations from FBP:

               
                double SF = CalculateSF(SiteVars.GroundSlope[site]);  //FBP 39

                double RSF = RSZ * SF;  //FBP 40

                double ISF = 0.0;
                double a, b, c;
                int fuelIndex = SiteVars.CFSFuelType[site];

                if (siteFuelType == FuelTypeCode.O1a)
                {
                    int percentCuring = season.PercentCuring;
                    double CF = (0.02 * percentCuring) - 1.0;
                    if (season.NameOfSeason == SeasonName.Spring)
                    {
                        a = Event.fuelTypeParms[(int)FuelTypeCode.O1a].A;
                        b = Event.fuelTypeParms[(int)FuelTypeCode.O1a].B;
                        c = Event.fuelTypeParms[(int)FuelTypeCode.O1a].C;
                    }
                    else
                    {
                        a = Event.fuelTypeParms[(int)FuelTypeCode.O1b].A;
                        b = Event.fuelTypeParms[(int)FuelTypeCode.O1b].B;
                        c = Event.fuelTypeParms[(int)FuelTypeCode.O1b].C;
                    }

                    ISF = Math.Log((1 - Math.Pow((RSF / (CF * a)), (1 / c)))) / (-1 * b); //FBP 43
                }
                else
                {
                    a = Event.fuelTypeParms[fuelIndex].A;
                    b = Event.fuelTypeParms[fuelIndex].B;
                    c = Event.fuelTypeParms[fuelIndex].C;

                    if (SiteVars.PercentHardwood[site] > 0)
                    {
                        int PC = SiteVars.PercentConifer[site];
                        ISF = Math.Log((1 - Math.Pow(((100 - RSF) / (PC * a)), (1 / c)))) / (-1 * b); //FBP 42
                    }
                    else
                    {
                        ISF = Math.Log((1 - Math.Pow(((RSF) / (a)), (1 / c)))) / (-1 * b); //FBP 41
                    }
                }
                double WSE = (Math.Log((ISF) / (.208 * f_F))) / (0.05039); //FBP 43: The effect the % slope would have on ROS if it were a wind speed
                double WAZ = windDirection * Math.PI / 180;  //wind direction/azimuth in radians
                double SAZ = SiteVars.UphillSlopeAzimuth[site] * Math.PI / 180;  //uphill slope azimuth in radians
                
                double WSX = (windSpeed * Math.Sin(WAZ)) + (WSE * Math.Sin(SAZ));  //FBP 47 
                double WSY = (windSpeed * Math.Cos(WAZ)) + (WSE * Math.Cos(SAZ));  //FBP 48

                 
                double WSV = Math.Sqrt(Math.Pow(WSX, 2) + Math.Pow(WSY, 2));  //FBP 49
                siteWindSpeed = (int)WSV;

                double RAZ = Math.Acos(WSY / WSV);  //FBP 50

                if (WSX < 0) RAZ = 360 - RAZ;
                siteWindDirection = (int)RAZ;
            }
            siteWindList.Add(siteWindSpeed);
            siteWindList.Add(siteWindDirection);
            SiteVars.SiteWindSpeed[site] = (ushort)siteWindSpeed;
            SiteVars.SiteWindDirection[site] = (ushort)siteWindDirection;

            return siteWindList;
            
            
            
        }
        private static List<Site> Get8Neighbors(Site site)
        {
            List<Site> neighbors = new List<Site>();
        
            RelativeLocation[] neighborhood = new RelativeLocation[] 
            {
                new RelativeLocation(-1,  0),  // north
                new RelativeLocation(-1,  1),  // northeast
                new RelativeLocation( 0,  1),  // east
                new RelativeLocation( 1,  1),  // southeast
                new RelativeLocation( 1,  0),  // south
                new RelativeLocation( 1, -1),  // southwest
                new RelativeLocation( 0, -1),  // west
                new RelativeLocation(-1, -1),  // northwest
            };

            foreach (RelativeLocation relativeLoc in neighborhood) 
            {
                Site neighbor = site.GetNeighbor(relativeLoc);
                if(neighbor != null && neighbor.IsActive)
                    neighbors.Add(neighbor);
            }
            Landis.Util.Random.Shuffle(neighbors);
        
            return neighbors;
        }
 //-------------------------------------------------------
 //Calculate the distance (in units of cells) from a location to a center
 //point (row and column = 0).
 private static double CellDistanceBetweenSites(Site asite, Site bsite)
 {
     double row = ((double) asite.Location.Row - (double) bsite.Location.Row);
     double column = ((double) asite.Location.Column - (double) bsite.Location.Column);
      double cSq = column * column;
      double rSq = row * row;
      return Math.Sqrt(cSq + rSq);
 }
        private static bool ElipseDistanceBetweenSites(Site igSite, Site burnSite, double C, double D, double fireDirection)
        {
            bool lessThan = false;
            
            //In the landscape, 'higher' rows have lower numbers, the inverse of what you 
            //would expect if the ignition site is located at (0,0).
            double dYburn = ((double) igSite.Location.Row - (double) burnSite.Location.Row);
            double dXburn = ((double) burnSite.Location.Column - (double) igSite.Location.Column);
        
            C = C / Model.Core.CellLength;
            D = D / Model.Core.CellLength;
            
            //Assume that ignition site (F0) is at location 0,0.
            double LengthA = Math.Sqrt((dXburn*dXburn) + (dYburn*dYburn));
        
            //Where is second focal site?
            double dYf1 = C * 2 * Math.Sin((90 + fireDirection) * Math.PI / 180);
            double dXf1 = C * 2 * Math.Cos((90 + fireDirection) * Math.PI / 180);
            
            double dXburn_f1 = dXburn - dXf1;
            double dYburn_f1 = dYburn - dYf1;
            
            double LengthB = Math.Sqrt((dXburn_f1 * dXburn_f1) + (dYburn_f1 * dYburn_f1));

            if(LengthA + LengthB <= ((C + D) * 2.0) )  
                lessThan = true;
            //UI.WriteLine("LengthA={0:0.0}, LengthB={1:0.0}, C={2:0.0}, D={3:0.0}.", LengthA, LengthB, C,D);
            //UI.WriteLine("dXf1={0:0.0}, dYf1={1:0.0}, dXburn={2:0.0}, dYburn={3:0.0}.", dXf1, dYf1,dXburn,dYburn);
            //return true;
            return lessThan;
        }
        //-------------------------------------------------------
        private static double Beta(Site sourcesite, Site site, double windDirection)
        {   
            double row = (double) sourcesite.Location.Row - (double) site.Location.Row;
            double column = (double) sourcesite.Location.Column - (double) site.Location.Column;
            
            double atan = 0.0;
            if (row == 0)
            {
                if (column == 0)
                {
                    return atan;
                }
                row = 0.0000001;
            }
            
            atan = Math.Atan(column / row) * 180 / Math.PI;// Convert to degrees
            
            if(Math.Sign(row) == -1) atan -= 180;

            double beta = atan - windDirection;
            
            //Randomize around 8 neighbor directions
            double wiggle = (Util.Random.GenerateUniform() * 45.0) - 22.5;
            beta = beta + wiggle;
            //
            beta = beta * Math.PI / 180;  //Convert to radians
            return beta;

            //atan = atan * Math.PI / 180;  //Back to radians
            
            //UI.WriteLine("Column = {0}, Row = {1}, Atan = {2}.", column, row, atan);
            //return atan - (windDirection * Math.PI / 180);
        }
        private static double CalculateTravelTime(Site site, Site firesource, Event fireEvent)
        {

            //Calculate Fire regime size adjustment:
            IEcoregion ecoregion = SiteVars.Ecoregion[site];
            IMoreEcoregionParameters eventParms = ecoregion.MoreEcoregionParameters;
            double FRUA = eventParms.MeanSize;
            
            ecoregion = SiteVars.Ecoregion[firesource];
            eventParms = ecoregion.MoreEcoregionParameters;
            FRUA = FRUA / eventParms.MeanSize;
            
            
            int fuelIndex = SiteVars.CFSFuelType[site];
            int percentConifer = SiteVars.PercentConifer[site];
            int percentHardwood = SiteVars.PercentHardwood[site];
            int percentDeadFir = SiteVars.PercentDeadFir[site];
            List<int> siteWindList = new List<int>();
            int siteWindSpeed, siteWindDirection;

            FuelTypeCode temp = (FuelTypeCode) fuelIndex;
            //UI.WriteLine("         Fuel Type Code = {0}.", temp.ToString());
            
            IFuelTypeParameters[] fuelTypeParms = fireEvent.FuelTypeParms;
            ISeasonParameters season = fireEvent.FireSeason;

            double f_F = Weather.CalculateFuelMoistureEffect(fireEvent.FFMC);
            double ISZ = 0.208 * f_F;  //No wind
            double RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ,
                                                        percentConifer,
                                                        percentHardwood,
                                                        percentDeadFir,
                                                        season);
            
            siteWindList = CalculateSlopeEffect(fireEvent.WindSpeed, fireEvent.WindDirection, site, RSZ, f_F, season);
            if (siteWindList.Count > 0)
            {
                siteWindSpeed = siteWindList[0];
                siteWindDirection = siteWindList[1];
            }
            else
            {
                siteWindSpeed = fireEvent.WindSpeed;
                siteWindDirection = fireEvent.WindDirection;
            }

            double f_backW = Weather.CalculateBackWindEffect(siteWindSpeed);
            double f_W = Weather.CalculateWindEffect(siteWindSpeed);

            double ISI = 0.208 * f_F * f_W;
            double BISI = 0.208 * f_F * f_backW;

            double BROSi = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 
                                                        percentConifer,
                                                        percentHardwood,
                                                        percentDeadFir,
                                                        season);
           
            double ROSi = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 
                                                        percentConifer,
                                                        percentHardwood,
                                                        percentDeadFir,
                                                        season );
            
            BROSi *= FRUA;
            ROSi  *= FRUA;
            SiteVars.RateOfSpread[site] = ROSi;

            double LB = CalculateLengthBreadthRatio(siteWindSpeed, fuelIndex);
            
            double FROSi = (ROSi + BROSi)/(LB * 2.0);//        (FBP; 89)

            double alpha = siteWindDirection;
            double A = FROSi;
            double beta = Beta(firesource, site, alpha);

            //Randomize around 8 neighbor directions
            //int wiggle = (int)((Util.Random.GenerateUniform() * 45.0) - 22.5);
            //beta = beta + wiggle;
            

            double B = A * LB; //fireEvent.LB; 
            double C = B - BROSi;

            //  Equations below for e, p, b, c, a utlize the polar equation
            //  for an ellipse, given at:
            //  http://www.du.edu/~jcalvert/math/ellipse.htm

            double e = C / B;
            double dist = CellDistanceBetweenSites(site, firesource) * Model.Core.CellLength;
            double r = ROSi;
            if (dist != 0)
            {
                double p = dist * (1 + e * Math.Cos(Math.PI - beta));
                double b = p / (1 - e * e);
                double c = e * b;
                r = (dist / (b + c)) * ROSi;
             
            //double a = (1 / LB) * b;           

            //Equations below for theta, r come from Finney 2002, eq [3], [5]

            //double cosSqBeta = CosSquared(beta);
            //double sinSqBeta = SinSquared(beta);
            //double termA = a * Math.Cos(beta) * Math.Pow(((a*a * cosSqBeta) + ((b*b)-(c*c)) * sinSqBeta),0.5);
            //double termB = b * c * sinSqBeta;
            //double termC = ((a*a) * cosSqBeta) + ((b*b) * sinSqBeta);
            //double theta = Math.Acos((termA - termB) / termC);
            
            //r = (a * ((c * Math.Cos(theta)) + b)) /
            //            Math.Sqrt((a * a * CosSquared(theta)) + (b * b * SinSquared(theta)));
            }
                        
            //-----Added by BRM-----
            SiteVars.AdjROS[site] = r;
            //----------      
            
            //UI.WriteLine("      FROSi = {0}, BROSi = {1}.", FROSi, BROSi);
            //UI.WriteLine("      beta = {0:0.00}, theta = {1:0.00}, alpha = {2:0.00}, Travel time = {3:0.000000}.", beta, theta, alpha, 1/r);
            //UI.WriteLine("      Travel time = {0:0.000000}.  R = {1}.", 1/r, r);
            if (site == firesource)
            {
                double rate = 1.0 / r;  //units = minutes / meter
                double cost = rate * Model.Core.CellLength / 2;     //units = minutes
                return cost;
            }
            else
            {
                double rate = 1.0 / r;  //units = minutes / meter
                double cost = rate * Model.Core.CellLength;     //units = minutes
                return cost;
            }
        }
        //-------------------------------------------------------
        private static Site CalculateMinNeighbor(Site site, Event fireEvent)
        {
            List<Site> neighborhood = Get8Neighbors(site);

            Site lowestNeighbor = null;
            
            double minNeighborTravelTime = SiteVars.MinNeighborTravelTime[site]; 
            
            foreach (Site relneighbor in neighborhood) 
            {
                if( //relneighbor != null && 
                    SiteVars.Event[relneighbor] == fireEvent &&
                    !Double.IsPositiveInfinity(SiteVars.TravelTime[relneighbor]) && 
                    SiteVars.TravelTime[relneighbor] < minNeighborTravelTime)
                {
                    lowestNeighbor = relneighbor;
                    SiteVars.MinNeighborTravelTime[site] = SiteVars.TravelTime[relneighbor];
                    //UI.WriteLine("Location = {0},{1}.  MinTravelTime = {2}.", lowestNeighbor.Row, lowestNeighbor.Column, SiteVars.TravelTime[relneighbor]);
                }
            }
            
            return lowestNeighbor;

        }
 public WeightedSites (Site site, double weight)
 {
     this.site = site;
     this.weight = weight;
 }
Ejemplo n.º 17
0
        //---------------------------------------------------------------------

        private int CalcFuelType(Site site, 
                                        IEnumerable<IFuelType> FuelTypes, 
                                        IEnumerable<ISlashType> SlashTypes)
        {

            double[] forTypValue = new double[100];  //Maximum of 50 fuel types
            double sumConifer = 0.0;
            double sumDecid = 0.0;
            //double totalSppValue = 0.0;
            
            //UI.WriteLine("      Calculating species values...");
            Species.IDataset SpeciesDataset = Model.Core.Species;
            foreach(ISpecies species in SpeciesDataset)
            {
                /* ushort maxSpeciesAge = 0;
                
                double sppValue = 0.0;

                maxSpeciesAge = AgeCohort.Util.GetMaxAge(cohorts[site][species]);

                if(maxSpeciesAge > 0)
                {
                    sppValue = (double) maxSpeciesAge /
                        (double) species.Longevity * 
                        fuelCoefs[species.Index];
                        
                    //if(coniferIndex[species.Index])
                    //    sumConifer += sppValue;
                                
                    //if(decidIndex[species.Index])
                    //    sumDecid += sppValue;

                    //UI.WriteLine("      accumulating species values...");
                    foreach(IFuelType ftype in FuelTypes)
                    {
                        if(maxSpeciesAge >= ftype.MinAge && maxSpeciesAge <= ftype.MaxAge && sppValue > 0)
                        {
                            if(ftype[species.Index] != 0)
                            {
                                if(ftype[species.Index] == -1)
                                    forTypValue[ftype.FuelIndex] -= sppValue;
                                if(ftype[species.Index] == 1)
                                    forTypValue[ftype.FuelIndex] += sppValue;
                             }
                             
                                
                        }
                    }
                }*/
                
              
                ISpeciesCohorts speciesCohorts = cohorts[site][species];
                
                if(speciesCohorts == null)
                    continue;

                foreach(IFuelType ftype in FuelTypes)
                {

                    if(ftype[species.Index] != 0)
                    {
                        double sppValue = 0.0;

                        foreach(ICohort cohort in speciesCohorts)
                        {
                            double cohortValue =0.0;
                            
                        
                            if(cohort.Age >= ftype.MinAge && cohort.Age <= ftype.MaxAge)
                            {
                                // Adjust max range age to the spp longevity
                                double maxAge = System.Math.Min(ftype.MaxAge, (double) species.Longevity);
                                
                                // The fuel type range must be at least 5 years:
                                double ftypeRange = System.Math.Max(1.0, maxAge - (double) ftype.MinAge);
                                
                                // The cohort age relative to the fuel type range:
                                double relativeCohortAge = System.Math.Max(1.0, (double) cohort.Age - ftype.MinAge);
                                
                                cohortValue = relativeCohortAge / ftypeRange * fuelCoefs[species.Index];
                                
                                // Add a weight, dependent upon the size of the range.  Smaller ranges = smaller 
                                // weight because cohorts will more quickly advance to the end of small ranges.
                                //cohortValue *= ftypeRange / 100.0;
                            
                                sppValue += System.Math.Max(sppValue, cohortValue);
                            }
                        }
                        
                        if(ftype[species.Index] == -1)
                            forTypValue[ftype.FuelIndex] -= sppValue;
                        if(ftype[species.Index] == 1)
                            forTypValue[ftype.FuelIndex] += sppValue;
                    }
                } 
                
            }
            
            
            
            //UI.WriteLine("      Determining CFS fuel type...");
            int finalFuelType = 0;
            int decidFuelType = 0;
            int coniferFuelType = 0;
            int openFuelType = 0;
            int slashFuelType = 0;
            double maxValue = 0.0;
            double maxDecidValue = 0.0;
            double maxConiferValue = 0.0;
            double maxConPlantValue = 0.0;
            double maxOpenValue = 0.0;
            double maxSlashValue = 0.0;

            //Set the PERCENT CONIFER DOMINANCE:
            int coniferDominance = 0;
            int hardwoodDominance = 0;

            
            //First assign the CONIFER and DECIDUOUS types:
            foreach(IFuelType ftype in FuelTypes)
            {
                if(ftype != null)
                {

                    if ((ftype.BaseFuel == BaseFuelType.Conifer || ftype.BaseFuel == BaseFuelType.ConiferPlantation) 
                        && forTypValue[ftype.FuelIndex] > 0)
                    {
                        sumConifer += forTypValue[ftype.FuelIndex];
                        //maxOtherValue = forTypValue[ftype.FuelIndex];
                        //otherFuelType = ftype.FuelIndex;
                    }
                    
                    //This is calculated for the mixed types:
                    if ((ftype.BaseFuel == BaseFuelType.Deciduous) 
                        && forTypValue[ftype.FuelIndex] > 0)
                    {
                        sumDecid += forTypValue[ftype.FuelIndex];
                        //maxDecidValue = forTypValue[ftype.FuelIndex];
                        //decidFuelType = ftype.FuelIndex;
                    }

                    // CONIFER
                    if(forTypValue[ftype.FuelIndex] > maxConiferValue && ftype.BaseFuel == BaseFuelType.Conifer)
                    {
                        
                        maxConiferValue = forTypValue[ftype.FuelIndex];
                        if(maxConiferValue > maxConPlantValue)
                        coniferFuelType = ftype.FuelIndex;
                    }
                    // CONIFER PLANTATION
                    if (forTypValue[ftype.FuelIndex] > maxConPlantValue && ftype.BaseFuel == BaseFuelType.ConiferPlantation)
                    {

                        maxConPlantValue = forTypValue[ftype.FuelIndex];
                        if(maxConPlantValue > maxConiferValue)
                        coniferFuelType = ftype.FuelIndex;
                    }

                    // OPEN
                    if (forTypValue[ftype.FuelIndex] > maxOpenValue && ftype.BaseFuel == BaseFuelType.Open)
                    {

                        maxOpenValue = forTypValue[ftype.FuelIndex];
                        openFuelType = ftype.FuelIndex;
                    }
                    
                    // SLASH
                    if (forTypValue[ftype.FuelIndex] > maxSlashValue && ftype.BaseFuel == BaseFuelType.Slash)
                    {

                        maxSlashValue = forTypValue[ftype.FuelIndex];
                        slashFuelType = ftype.FuelIndex;
                    }

                    // DECIDUOUS
                    if(forTypValue[ftype.FuelIndex] > maxDecidValue && ftype.BaseFuel == BaseFuelType.Deciduous)
                    {
                        
                        maxDecidValue = forTypValue[ftype.FuelIndex];
                        decidFuelType = ftype.FuelIndex;
                    }

                }
            }

            if (maxConiferValue >= maxConPlantValue && maxConiferValue >= maxDecidValue && maxConiferValue >= maxOpenValue && maxConiferValue >= maxSlashValue)
            {
                maxValue = maxConiferValue;
            }
            else if (maxDecidValue >= maxConiferValue && maxDecidValue >= maxConPlantValue && maxDecidValue >= maxOpenValue && maxDecidValue >= maxSlashValue)
            {
                maxValue = maxDecidValue;
            }
            else if (maxConPlantValue >= maxConiferValue && maxConPlantValue >= maxDecidValue && maxConPlantValue >= maxOpenValue && maxConPlantValue >= maxSlashValue)
            {
                maxValue = maxConPlantValue;
                finalFuelType = coniferFuelType;
                decidFuelType = 0;
                sumConifer = 100;
                sumDecid = 0;
            }
            else if (maxSlashValue >= maxConiferValue && maxSlashValue >= maxConPlantValue && maxSlashValue >= maxDecidValue && maxSlashValue >= maxOpenValue)
            {
                maxValue = maxSlashValue;
                finalFuelType = slashFuelType;
                decidFuelType = 0;
                sumConifer = 0;
                sumDecid = 0;
            }
            else if (maxOpenValue >= maxConiferValue && maxOpenValue >= maxConPlantValue && maxOpenValue >= maxDecidValue && maxOpenValue >= maxSlashValue)
            {
                maxValue = maxOpenValue;
                finalFuelType = openFuelType;
                decidFuelType = 0;
                sumConifer = 0;
                sumDecid = 0;
            }
            
            
            //Set the PERCENT DOMINANCE values:
            if (sumConifer > 0 || sumDecid > 0)
            {
                coniferDominance = (int)((sumConifer / (sumConifer + sumDecid) * 100) + 0.5);
                hardwoodDominance = (int)((sumDecid / (sumConifer + sumDecid) * 100) + 0.5);
                if (hardwoodDominance < hardwoodMax)
                {
                    coniferDominance = 100;
                    hardwoodDominance = 0;
                    finalFuelType = coniferFuelType;
                    decidFuelType = 0;
                }
                if (coniferDominance < hardwoodMax)
                {
                    coniferDominance = 0;
                    hardwoodDominance = 100;
                    finalFuelType = decidFuelType;
                    decidFuelType = 0;
                }
                if (hardwoodDominance > hardwoodMax && coniferDominance > hardwoodMax)
                    finalFuelType = coniferFuelType;
            }
            

            
            //---------------------------------------------------------------------
            // Next check the disturbance types.  This will override any other existing fuel type.
            foreach(SlashType slash in SlashTypes)
            {
                if (SiteVars.HarvestCohortsKilled != null && SiteVars.HarvestCohortsKilled[site] > 0)
                {
                    if (SiteVars.TimeOfLastHarvest != null &&
                        (Model.Core.CurrentTime - SiteVars.TimeOfLastHarvest[site] <= slash.MaxAge))
                    {
                        foreach (string pName in slash.PrescriptionNames)
                        {
                            if (SiteVars.HarvestPrescriptionName != null && SiteVars.HarvestPrescriptionName[site].Trim() == pName.Trim())
                            {
                                finalFuelType = slash.FuelIndex; //Name;
                                decidFuelType = 0;
                                coniferDominance = 0;
                                hardwoodDominance = 0;
                            }
                        }
                    }
                }
                //Check for fire severity effects of fuel type
                if (SiteVars.FireSeverity != null && SiteVars.FireSeverity[site] > 0)
                {
                    if (SiteVars.TimeOfLastFire != null &&
                        (Model.Core.CurrentTime - SiteVars.TimeOfLastFire[site] <= slash.MaxAge))
                    {
                        foreach (string pName in slash.PrescriptionNames)
                        {
                            if (pName.StartsWith("FireSeverity"))
                            {
                                if((pName.Substring((pName.Length - 1), 1)).ToString() == SiteVars.FireSeverity[site].ToString())
                                {
                                    finalFuelType = slash.FuelIndex; //Name;
                                    decidFuelType = 0;
                                    coniferDominance = 0;
                                    hardwoodDominance = 0;
                                }
                            }
                        }
                    }
                }
                //Check for wind severity effects of fuel type
                if (SiteVars.WindSeverity != null && SiteVars.WindSeverity[site] > 0)
                {
                    if (SiteVars.TimeOfLastWind != null &&
                        (Model.Core.CurrentTime - SiteVars.TimeOfLastWind[site] <= slash.MaxAge))
                    {
                        foreach (string pName in slash.PrescriptionNames)
                        {
                            if (pName.StartsWith("WindSeverity"))
                            {
                                if ((pName.Substring((pName.Length - 1), 1)).ToString() == SiteVars.WindSeverity[site].ToString())
                                {
                                    finalFuelType = slash.FuelIndex; //Name;
                                    decidFuelType = 0;
                                    coniferDominance = 0;
                                    hardwoodDominance = 0;
                                }
                            }
                        }
                    }
                }
            }

            
            /*
            //If NEITHER conifer nor deciduous, then set those dominances values to zero:
            foreach(IFuelType ftype in FuelTypes)
                if (ftype.FuelIndex == finalFuelType && ftype.BaseFuel != BaseFuelType.Conifer 
                    && ftype.BaseFuel != BaseFuelType.ConiferPlantation 
                    && ftype.BaseFuel != BaseFuelType.Deciduous)
                {
                    coniferDominance = 0;
                    hardwoodDominance = 0;
                }
            */
            
            //if(decidFuelType == 0) hardwoodDominance = 0;
            
            //Assign Percent Conifer:
            SiteVars.PercentConifer[site] = coniferDominance;
            SiteVars.PercentHardwood[site] = hardwoodDominance;

            SiteVars.CFSFuelType[site] = finalFuelType;
            SiteVars.DecidFuelType[site] = decidFuelType;
            
            return finalFuelType;

        }
 AgeCohort.ISiteCohorts Cohorts.ILandscapeCohorts<AgeCohort.ISiteCohorts>.this[Site site]
 {
     get {
         return null;
     }
 }
Ejemplo n.º 19
0
        //---------------------------------------------------------------------

        private int CalcFuelType(Site site,
                                        IEnumerable<IFuelType> FuelTypes,
                                        IEnumerable<IDisturbanceType> DisturbanceTypes)
        {

            double[] forTypValue = new double[100];  //Maximum of 100 fuel types
            double sumConifer = 0.0;
            double sumDecid = 0.0;

            //UI.WriteLine("      Calculating species values...");
            Species.IDataset SpeciesDataset = Model.Core.Species;
            foreach(ISpecies species in SpeciesDataset)
            {
                /*ushort maxSpeciesAge = 0;
                double sppValue = 0.0;
                maxSpeciesAge = AgeCohort.Util.GetMaxAge(cohorts[site][species]);

                if(maxSpeciesAge > 0)
                {
                    sppValue = (double) maxSpeciesAge /
                        (double) species.Longevity *
                        (double) fuelCoefs[species.Index];

                    //if(coniferIndex[species.Index])
                    //    sumConifer += sppValue;

                    //if(decidIndex[species.Index])
                    //    sumDecid += sppValue;

                    //UI.WriteLine("      accumulating species values...");
                    foreach(IFuelType ftype in FuelTypes)
                    {
                        if(maxSpeciesAge >= ftype.MinAge && maxSpeciesAge <= ftype.MaxAge && sppValue > 0)
                        {
                            if(ftype[species.Index] != 0)
                            {
                                if(ftype[species.Index] == -1)
                                    forTypValue[ftype.FuelIndex] -= sppValue;
                                if(ftype[species.Index] == 1)
                                    forTypValue[ftype.FuelIndex] += sppValue;
                             }


                        }
                    }
                } */

                // This is the new algorithm, based on where a cohort is within it's age range.
                // This algorithm is less biased towards older cohorts.
                ISpeciesCohorts speciesCohorts = cohorts[site][species];

                if(speciesCohorts == null)
                    continue;

                foreach(IFuelType ftype in FuelTypes)
                {

                    if(ftype[species.Index] != 0)
                    {
                        double sppValue = 0.0;

                        foreach(ICohort cohort in speciesCohorts)
                        {
                            double cohortValue =0.0;


                            if(cohort.Age >= ftype.MinAge && cohort.Age <= ftype.MaxAge)
                            {
                                // Adjust max range age to the spp longevity
                                double maxAge = System.Math.Min(ftype.MaxAge, (double) species.Longevity);

                                // The fuel type range must be at least 5 years:
                                double ftypeRange = System.Math.Max(1.0, maxAge - (double) ftype.MinAge);

                                // The cohort age relative to the fuel type range:
                                double relativeCohortAge = System.Math.Max(1.0, (double) cohort.Age - ftype.MinAge);

                                cohortValue = relativeCohortAge / ftypeRange * fuelCoefs[species.Index];

                                // Use the one cohort with the largest value:
                                //sppValue += System.Math.Max(sppValue, cohortValue);  // A BUG, should be...
                                sppValue = System.Math.Max(sppValue, cohortValue);
                            }
                        }

                        if(ftype[species.Index] == -1)
                            forTypValue[ftype.FuelIndex] -= sppValue;
                        if(ftype[species.Index] == 1)
                            forTypValue[ftype.FuelIndex] += sppValue;
                    }
                }

            }

            int finalFuelType = 0;
            int decidFuelType = 0;
            //int coniferFuelType = 0;
            //int openFuelType = 0;
            //int slashFuelType = 0;
            double maxValue = 0.0;
            double maxDecidValue = 0.0;
            //double maxConiferValue = 0.0;
            //double maxConPlantValue = 0.0;
            //double maxOpenValue = 0.0;
            //double maxSlashValue = 0.0;

            //Set the PERCENT CONIFER DOMINANCE:
            int coniferDominance = 0;
            int hardwoodDominance = 0;


            //First accumulate data for the BASE fuel types:
            foreach(IFuelType ftype in FuelTypes)
            {
                if(ftype != null)
                {

                    if ((ftype.BaseFuel == BaseFuelType.Conifer || ftype.BaseFuel == BaseFuelType.ConiferPlantation)
                        && forTypValue[ftype.FuelIndex] > 0)
                    {
                        sumConifer += forTypValue[ftype.FuelIndex];
                    }

                    //This is calculated for the mixed types:
                    if ((ftype.BaseFuel == BaseFuelType.Deciduous)
                        && forTypValue[ftype.FuelIndex] > 0)
                    {
                        sumDecid += forTypValue[ftype.FuelIndex];
                    }

                    if(forTypValue[ftype.FuelIndex] > maxValue)
                    {
                        maxValue = forTypValue[ftype.FuelIndex];
                        finalFuelType = ftype.FuelIndex;
                    }

                    if(ftype.BaseFuel == BaseFuelType.Deciduous && forTypValue[ftype.FuelIndex] > maxDecidValue)
                    {
                        maxDecidValue = forTypValue[ftype.FuelIndex];
                        decidFuelType = ftype.FuelIndex;
                    }

                }
            }

            // Next, use rules to modify the conifer and deciduous dominance:


            foreach(IFuelType ftype in FuelTypes)
            {
                if(ftype != null)
                {

                    if(ftype.FuelIndex == finalFuelType && ftype.BaseFuel == BaseFuelType.ConiferPlantation)
                    {
                        decidFuelType = 0;
                        sumConifer = 100;
                        sumDecid = 0;
                    }

                    // a SLASH type
                    else if(ftype.FuelIndex == finalFuelType && ftype.BaseFuel == BaseFuelType.Slash)
                    {
                        //maxValue = maxSlashValue;
                        //finalFuelType = slashFuelType;
                        //decidFuelType = 0;
                        sumConifer = 0;
                        sumDecid = 0;
                    }

            // an OPEN type
                    else if(ftype.FuelIndex == finalFuelType && ftype.BaseFuel == BaseFuelType.Open)
                    {
                        //maxValue = maxOpenValue;
                        //finalFuelType = openFuelType;
                        //decidFuelType = 0;
                        sumConifer = 0;
                        sumDecid = 0;
                    }

                }
            }
            //Set the PERCENT DOMINANCE values:
            if (sumConifer > 0 || sumDecid > 0)
            {
                coniferDominance = (int)((sumConifer / (sumConifer + sumDecid) * 100) + 0.5);
                hardwoodDominance = (int)((sumDecid / (sumConifer + sumDecid) * 100) + 0.5);
                if (hardwoodDominance < hardwoodMax)
                {
                    coniferDominance = 100;
                    hardwoodDominance = 0;
                }
                if (coniferDominance < hardwoodMax)
                {
                    coniferDominance = 0;
                    hardwoodDominance = 100;
                    finalFuelType = decidFuelType;
                }
            }

            //---------------------------------------------------------------------
            // Next check the disturbance types.  This will override any other existing fuel type.
            foreach(DisturbanceType slash in DisturbanceTypes)
            {
                if (SiteVars.HarvestCohortsKilled != null && SiteVars.HarvestCohortsKilled[site] > 0)
                {
                    if (SiteVars.TimeOfLastHarvest != null &&
                        (Model.Core.CurrentTime - SiteVars.TimeOfLastHarvest[site] <= slash.MaxAge))
                    {
                        foreach (string pName in slash.PrescriptionNames)
                        {
                            if (SiteVars.HarvestPrescriptionName != null && SiteVars.HarvestPrescriptionName[site].Trim() == pName.Trim())
                            {
                                finalFuelType = slash.FuelIndex; //Name;
                                decidFuelType = 0;
                                coniferDominance = 0;
                                hardwoodDominance = 0;
                            }
                        }
                    }
                }
                //Check for fire severity effects of fuel type
                if (SiteVars.FireSeverity != null && SiteVars.FireSeverity[site] > 0)
                {
                    if (SiteVars.TimeOfLastFire != null &&
                        (Model.Core.CurrentTime - SiteVars.TimeOfLastFire[site] <= slash.MaxAge))
                    {
                        foreach (string pName in slash.PrescriptionNames)
                        {
                            if (pName.StartsWith("FireSeverity"))
                            {
                                if((pName.Substring((pName.Length - 1), 1)).ToString() == SiteVars.FireSeverity[site].ToString())
                                {
                                    finalFuelType = slash.FuelIndex; //Name;
                                    decidFuelType = 0;
                                    coniferDominance = 0;
                                    hardwoodDominance = 0;
                                }
                            }
                        }
                    }
                }
                //Check for wind severity effects of fuel type
                if (SiteVars.WindSeverity != null && SiteVars.WindSeverity[site] > 0)
                {
                    if (SiteVars.TimeOfLastWind != null &&
                        (Model.Core.CurrentTime - SiteVars.TimeOfLastWind[site] <= slash.MaxAge))
                    {
                        foreach (string pName in slash.PrescriptionNames)
                        {
                            if (pName.StartsWith("WindSeverity"))
                            {
                                if ((pName.Substring((pName.Length - 1), 1)).ToString() == SiteVars.WindSeverity[site].ToString())
                                {
                                    finalFuelType = slash.FuelIndex; //Name;
                                    decidFuelType = 0;
                                    coniferDominance = 0;
                                    hardwoodDominance = 0;
                                }
                            }
                        }
                    }
                }
            }

            //Assign Percent Conifer:
            SiteVars.PercentConifer[site] = coniferDominance;
            SiteVars.PercentHardwood[site] = hardwoodDominance;

            SiteVars.FuelType[site] = finalFuelType;
            SiteVars.DecidFuelType[site] = decidFuelType;

            return finalFuelType;

        }
Ejemplo n.º 20
0
		//---------------------------------------------------------------------

		private List<Site> GetNeighbors(Site site)
		{
			List<Site> neighbors = new List<Site>(4);
			foreach (RelativeLocation relativeLoc in neighborhood) {
				Site neighbor = site.GetNeighbor(relativeLoc);
				if (neighbor != null)
					neighbors.Add(neighbor);
			}
			return neighbors;
		}
        //---------------------------------------------------------------------
        // This method replaces the delegate method.  It is called every year when
        // ACT_ANPP is calculated, for each cohort.  Therefore, this method is operating at
        // an ANNUAL time step and separate from the normal extension time step.

        public static double DefoliateCohort(Biomass.ICohort cohort, Site site, int siteBiomass)
        {

            //UI.WriteLine("   Calculating insect defoliation...");

            int sppIndex = cohort.Species.Index;
            double totalDefoliation = 0.0;

            foreach(IInsect insect in manyInsect)
            {
                if(!insect.ActiveOutbreak)
                    continue;

                double defoliation = 0.0;
                double weightedDefoliation = 0.0;
                int suscIndex = insect.SppTable[sppIndex].Susceptibility - 1;

                if (suscIndex < 0) suscIndex = 0;

                // Get the Neighborhood GrowthReduction Density
                double meanNeighborhoodDefoliation = 0.0;
                int neighborCnt = 0;

                // If it is the first year, the neighborhood growth reduction
                // will have been initialized in Outbreak.InitializeDefoliationPatches

                if(insect.NeighborhoodDefoliation[site] > 0)
                {
                    //UI.WriteLine("   First Year of Defoliation:  Using initial patch defo={0:0.00}.", SiteVars.NeighborhoodDefoliation[site]);
                    meanNeighborhoodDefoliation = insect.NeighborhoodDefoliation[site];
                }

                // If not the first year, calculate mean neighborhood defoliation based on the
                // previous year.
                else
                {
                    double sumNeighborhoodDefoliation = 0.0;

                    //UI.WriteLine("Look at the Neighbors... ");
                    foreach (RelativeLocation relativeLoc in insect.Neighbors)
                    {
                        Site neighbor = site.GetNeighbor(relativeLoc);
                        if (neighbor != null && neighbor.IsActive)
                        {
                            neighborCnt++;

                            // The previous year...
                            //if(SiteVars.DefoliationByYear[neighbor].ContainsKey(Model.Core.CurrentTime - 1))
                            //    sumNeighborhoodDefoliation += SiteVars.DefoliationByYear[neighbor][Model.Core.CurrentTime - 1];
                            sumNeighborhoodDefoliation += insect.LastYearDefoliation[neighbor];
                        }
                    }

                    if(neighborCnt > 0.0)
                        meanNeighborhoodDefoliation = sumNeighborhoodDefoliation / (double) neighborCnt;

                }  //endif

                if(meanNeighborhoodDefoliation > 1.0 || meanNeighborhoodDefoliation < 0)
                {
                    UI.WriteLine("MeanNeighborhoodDefoliation={0}; NeighborCnt={1}.", meanNeighborhoodDefoliation, neighborCnt);
                    throw new ApplicationException("Error: Mean Neighborhood GrowthReduction is not between 1.0 and 0.0");
                }

                // First assume that there are no neighbors whatsoever:
                DistributionType dist = insect.SusceptibleTable[suscIndex].Distribution_0.Name;
                double value1 = insect.SusceptibleTable[suscIndex].Distribution_0.Value1;
                double value2 = insect.SusceptibleTable[suscIndex].Distribution_0.Value2;

                if(meanNeighborhoodDefoliation <= 1.0 && meanNeighborhoodDefoliation >= 0.8)
                {
                    dist = insect.SusceptibleTable[suscIndex].Distribution_80.Name;
                    value1 = insect.SusceptibleTable[suscIndex].Distribution_80.Value1;
                    value2 = insect.SusceptibleTable[suscIndex].Distribution_80.Value2;
                }
                else if(meanNeighborhoodDefoliation < 0.8 && meanNeighborhoodDefoliation >= 0.6)
                {
                    dist = insect.SusceptibleTable[suscIndex].Distribution_60.Name;
                    value1 = insect.SusceptibleTable[suscIndex].Distribution_60.Value1;
                    value2 = insect.SusceptibleTable[suscIndex].Distribution_60.Value2;
                }
                else if(meanNeighborhoodDefoliation < 0.6 && meanNeighborhoodDefoliation >= 0.4)
                {
                    dist = insect.SusceptibleTable[suscIndex].Distribution_40.Name;
                    value1 = insect.SusceptibleTable[suscIndex].Distribution_40.Value1;
                    value2 = insect.SusceptibleTable[suscIndex].Distribution_40.Value2;
                }
                else if(meanNeighborhoodDefoliation < 0.4 && meanNeighborhoodDefoliation >= 0.2)
                {
                    dist = insect.SusceptibleTable[suscIndex].Distribution_20.Name;
                    value1 = insect.SusceptibleTable[suscIndex].Distribution_20.Value1;
                    value2 = insect.SusceptibleTable[suscIndex].Distribution_20.Value2;
                }
                else if(meanNeighborhoodDefoliation < 0.2 && meanNeighborhoodDefoliation >= 0.0)
                {
                    dist = insect.SusceptibleTable[suscIndex].Distribution_0.Name;
                    value1 = insect.SusceptibleTable[suscIndex].Distribution_0.Value1;
                    value2 = insect.SusceptibleTable[suscIndex].Distribution_0.Value2;
                }

                // Next, ensure that all cohorts of the same susceptibility class
                // receive the same level of defoliation.

                if(insect.HostDefoliationByYear[site].ContainsKey(Model.Core.CurrentTime))
                {
                    if(insect.HostDefoliationByYear[site][Model.Core.CurrentTime][suscIndex] <= 0.00000000)
                    {
                        defoliation = Distribution.GenerateRandomNum(dist, value1, value2);
                        insect.HostDefoliationByYear[site][Model.Core.CurrentTime][suscIndex] = defoliation;
                    }
                    else
                        defoliation = insect.HostDefoliationByYear[site][Model.Core.CurrentTime][suscIndex];
                }
                else
                {
                    insect.HostDefoliationByYear[site].Add(Model.Core.CurrentTime, new Double[3]{0.0, 0.0, 0.0});
                    defoliation = Distribution.GenerateRandomNum(dist, value1, value2);
                    insect.HostDefoliationByYear[site][Model.Core.CurrentTime][suscIndex] = defoliation;
                }


                // Alternatively, allow defoliation to vary even among cohorts and species with
                // the same susceptibility.
                //defoliation = Distribution.GenerateRandomNum(dist, value1, value2);

                if(defoliation > 1.0 || defoliation < 0)
                {
                    UI.WriteLine("DEFOLIATION TOO BIG or SMALL:  {0}, {1}, {2}, {3}.", dist, value1, value2, defoliation);
                    throw new ApplicationException("Error: New defoliation is not between 1.0 and 0.0");
                }

                //UI.WriteLine("Cohort age={0}, species={1}, suscIndex={2}, defoliation={3}.", cohort.Age, cohort.Species.Name, (suscIndex -1), defoliation);
                
                // For first insect in a given year, actual defoliation equals the potential defoliation drawn from insect distributions.
                if (totalDefoliation == 0.0)
                {
                    weightedDefoliation = (defoliation * ((double)cohort.Biomass / (double)siteBiomass));
                    //UI.WriteLine("Cohort age={0}, species={1}, suscIndex={2}, cohortDefoliation={3}.", cohort.Age, cohort.Species.Name, (suscIndex+1), cohortDefoliation);
                }
                // For second insect in a given year, actual defoliation can only be as high as the amount of canopy foliage left by first insect.
                // This change makes sure next year's neighborhoodDefoliation will reflect actual defoliation, rather than "potential" defoliation.
                // It should also ensure that the sum of defoliation maps for all insects adds up to 1 for a given year.
                else
                {
                    weightedDefoliation = (Math.Min((1 - totalDefoliation), defoliation) * ((double)cohort.Biomass / (double)siteBiomass));
                }

                insect.ThisYearDefoliation[site] += weightedDefoliation;

                if (insect.ThisYearDefoliation[site] > 1.0) // Weighted defoliation cannot exceed 100% of site biomass.
                    insect.ThisYearDefoliation[site] = 1.0;

                //Put in error statement to see if sum of weighted defoliation is ever over 1.
                if (insect.ThisYearDefoliation[site] > 1.0 || insect.ThisYearDefoliation[site] < 0)
                {
                    UI.WriteLine("Site Weighted Defoliation = {0:0.000000}.  Site R/C={1}/{2}.  Last Weighted Defoliation = {3}.", insect.ThisYearDefoliation[site], site.Location.Row, site.Location.Column, weightedDefoliation);
                    throw new ApplicationException("Error: Site Weighted Defoliation is not between 1.0 and 0.0");
                }
                totalDefoliation += defoliation; // Is totalDefoliation getting used anywhere else? Or an orphan?
            }

            if(totalDefoliation > 1.0)  // Cannot exceed 100% defoliation, comment out to see if it ever does.
                totalDefoliation = 1.0;

            if(totalDefoliation > 1.0 || totalDefoliation < 0)
            {
                UI.WriteLine("Cohort Total Defoliation = {0:0.00}.  Site R/C={1}/{2}.", totalDefoliation, site.Location.Row, site.Location.Column);
                throw new ApplicationException("Error: Total Defoliation is not between 1.0 and 0.0");
            }


            return totalDefoliation;

        }
Ejemplo n.º 22
0
        //---------------------------------------------------------------------

        private List<Site> GetNeighbors(Site site, int windDirection)
        {
            if(windDirection > 7) windDirection = 7;
            double[] windProbs = 
            {
            (((4.0 - this.intensity)/8.0) * (1+this.intensity)), //Primary direction
            (((4.0 - this.intensity)/8.0) * (1+this.intensity)),
            (((4.0 - this.intensity)/8.0)),
            (((4.0 - this.intensity)/8.0) * (1-this.intensity)),
            (((4.0 - this.intensity)/8.0) * (1-this.intensity)), //Opposite of primary direction
            (((4.0 - this.intensity)/8.0) * (1-this.intensity)),
            (((4.0 - this.intensity)/8.0)),
            (((4.0 - this.intensity)/8.0) * (1+this.intensity)),
            };
            
            double windProb = 0.0;
            int index = 0;
            List<Site> neighbors = new List<Site>(9);
            foreach (RelativeLocation relativeLoc in neighborhood) 
            {
                Site neighbor = site.GetNeighbor(relativeLoc);
                if(index + windDirection > 7) 
                    windProb = windProbs[index + windDirection - 8];
                else 
                    windProb = windProbs[index + windDirection];
                if (neighbor != null && Random.GenerateUniform() < windProb)
                    neighbors.Add(neighbor);
                index++;
            }
            
            //Next, add the 9th neighbor, a neighbor one cell beyond the 
            //8 nearest neighbors.
            //array index 0 = north; 1 = northeast, 2 = east,...,8 = northwest
            int[] vertical  ={2,2,0,-2,-2,-2,0,2};
            int[] horizontal={0,2,2,2,0,-2,-2,-2};

            RelativeLocation relativeLoc9 = 
                new RelativeLocation(vertical[windDirection], horizontal[windDirection]);
            Site neighbor9 = site.GetNeighbor(relativeLoc9);
            if (neighbor9 != null && Random.GenerateUniform() < this.intensity)
                neighbors.Add(neighbor9);
            return neighbors;
        }
        //---------------------------------------------------------------------
        private byte CalcForestType(IForestType[] forestTypes,
            Site site)
        {
            int forTypeCnt = 0;

            double[] forTypValue = new double[forestTypes.Length];
            Species.IDataset SpeciesDataset = modelCore.Species;
            foreach(ISpecies species in SpeciesDataset)
            {
                double sppValue = 0.0;

                //Biomass.ICohort cohort = cohorts[site][species];

                //sppValue = cohort.Biomass;//Util.ComputeBiomass(cohorts[site][species]);
                sppValue = Util.ComputeBiomass(cohorts[site][species]);

                forTypeCnt = 0;
                foreach(IForestType ftype in forestTypes)
                {
                    if(ftype[species.Index] != 0)
                    {
                        if(ftype[species.Index] == -1)
                            forTypValue[forTypeCnt] -= sppValue;
                        if(ftype[species.Index] == 1)
                            forTypValue[forTypeCnt] += sppValue;
                    }
                    forTypeCnt++;
                }
            }

            int finalForestType = 0;
            double maxValue = 0.0;
            forTypeCnt = 0;
            foreach(IForestType ftype in forestTypes)
            {
                //System.Console.WriteLine("ForestTypeNum={0}, Value={1}.",forTypeCnt,forTypValue[forTypeCnt]);
                if(forTypValue[forTypeCnt]>maxValue)
                {
                    maxValue = forTypValue[forTypeCnt];
                    finalForestType = forTypeCnt+1;
                }
                forTypeCnt++;
            }
            return (byte) finalForestType;
        }
        //---------------------------------------------------------------------
        // This method replaces the delegate method.  It is called every year when
        // ACT_ANPP is calculated, for each cohort.  Therefore, this method is operating at
        // an ANNUAL time step and separate from the normal extension time step.

        public static double ReduceCohortGrowth(Biomass.ICohort cohort, Site site, int siteBiomass)
        {
            //UI.WriteLine("   Calculating cohort growth reduction due to insect defoliation...");

            double summaryGrowthReduction = 0.0;

            int sppIndex = cohort.Species.Index;

            foreach(IInsect insect in PlugIn.ManyInsect)
            {
                if(!insect.ActiveOutbreak)
                    continue;

                int suscIndex = insect.SppTable[sppIndex].Susceptibility - 1;
                //if (suscIndex < 0) suscIndex = 0;

                int yearBack = 0;
                double annualDefoliation = 0.0;

                if(insect.HostDefoliationByYear[site].ContainsKey(Model.Core.CurrentTime - yearBack))
                {
                    //UI.WriteLine("Host Defoliation By Year:  Time={0}, suscIndex={1}, spp={2}.", (Model.Core.CurrentTime - yearBack), suscIndex+1, cohort.Species.Name);
                    annualDefoliation += insect.HostDefoliationByYear[site][Model.Core.CurrentTime - yearBack][suscIndex];
                }
                double cumulativeDefoliation = annualDefoliation;

                while(annualDefoliation > 0)
                {
                    yearBack++;
                    annualDefoliation = 0.0;
                    if(insect.HostDefoliationByYear[site].ContainsKey(Model.Core.CurrentTime - yearBack))
                    {
                        //UI.WriteLine("Host Defoliation By Year:  Time={0}, suscIndex={1}, spp={2}.", (Model.Core.CurrentTime - yearBack), suscIndex+1, cohort.Species.Name);
                        annualDefoliation = insect.HostDefoliationByYear[site][Model.Core.CurrentTime - yearBack][suscIndex];
                        cumulativeDefoliation += annualDefoliation;
                    }
                }

                double slope = insect.SppTable[sppIndex].GrowthReduceSlope;
                double intercept = insect.SppTable[sppIndex].GrowthReduceIntercept;


                double growthReduction = 1.0 - (cumulativeDefoliation * slope + intercept);

                double weightedGD = (growthReduction * ((double) cohort.Biomass / (double) siteBiomass));
                //Below looks like it should be multiplied by weightedGD above, but it isn't?? CHECK!
                summaryGrowthReduction += growthReduction;
                //UI.WriteLine("Time={0}, Spp={1}, SummaryGrowthReduction={2:0.00}.", Model.Core.CurrentTime,cohort.Species.Name, summaryGrowthReduction);

            }
            if (summaryGrowthReduction > 1.0)  // Cannot exceed 100%
                summaryGrowthReduction = 1.0;

            if(summaryGrowthReduction > 1.0 || summaryGrowthReduction < 0)
            {
                UI.WriteLine("Cohort Total Growth Reduction = {0:0.00}.  Site R/C={1}/{2}.", summaryGrowthReduction, site.Location.Row, site.Location.Column);
                throw new ApplicationException("Error: Total Growth Reduction is not between 1.0 and 0.0");
            }

            return summaryGrowthReduction;
        }
Ejemplo n.º 25
0
        //---------------------------------------------------------------------

        private int CalcFuelType(Site site,
                                        IEnumerable<IFuelType> FuelTypes,
                                        IEnumerable<IDisturbanceType> DisturbanceTypes)
        {

            double[] forTypValue = new double[100];  //Maximum of 100 fuel types
            double sumConifer = 0.0;
            double sumDecid = 0.0;
            IEcoregion ecoregion = Model.Core.Ecoregion[(ActiveSite) site];

            foreach(ISpecies species in Model.Core.Species)
            {

                ISpeciesCohorts speciesCohorts = cohorts[site][species];

                if(speciesCohorts == null)
                    continue;

                foreach(IFuelType ftype in FuelTypes)
                {

                    if(ftype.Ecoregions[ecoregion.Index])
                    {

                        if(ftype[species.Index] != 0)
                        {
                            int sppValue = 0;

                            foreach(ICohort cohort in speciesCohorts)
                                if(cohort.Age >= ftype.MinAge && cohort.Age <= ftype.MaxAge)
                                    sppValue += cohort.Biomass;

                            //UI.WriteLine("sppVaue={0}, spp={1}, cohortB={2}.", sppValue, cohort.Species.Name, cohort.Biomass);

                            if(ftype[species.Index] == -1)
                                forTypValue[ftype.Index] -= sppValue;

                            if(ftype[species.Index] == 1)
                                forTypValue[ftype.Index] += sppValue;
                        }
                    }
                }

            }



            int finalFuelType = 0;
            int decidFuelType = 0;
            int coniferFuelType = 0;
            int openFuelType = 0;
            int slashFuelType = 0;
            double maxValue = 0.0;
            double maxDecidValue = 0.0;
            double maxConiferValue = 0.0;
            double maxConPlantValue = 0.0;
            double maxOpenValue = 0.0;
            double maxSlashValue = 0.0;

            //Set the PERCENT CONIFER DOMINANCE:
            int coniferDominance = 0;
            int hardwoodDominance = 0;


            //First accumulate data for the various Base Fuel Types:
            foreach(IFuelType ftype in FuelTypes)
            {
                if(ftype != null)
                {

                    //UI.WriteLine("   FuelType:  Index={0}.", ftype.Index);

                    // Sum for the Conifer and Deciduous dominance
                    if ((ftype.BaseFuel == BaseFuelType.Conifer || ftype.BaseFuel == BaseFuelType.ConiferPlantation)
                        && forTypValue[ftype.Index] > 0)
                    {
                        sumConifer += forTypValue[ftype.Index];
                    }

                    //This is calculated for the mixed types:
                    if ((ftype.BaseFuel == BaseFuelType.Deciduous)
                        && forTypValue[ftype.Index] > 0)
                    {
                        sumDecid += forTypValue[ftype.Index];
                    }

                    // CONIFER
                    if(forTypValue[ftype.Index] > maxConiferValue && ftype.BaseFuel == BaseFuelType.Conifer)
                    {

                        maxConiferValue = forTypValue[ftype.Index];
                        if(maxConiferValue > maxConPlantValue)
                            coniferFuelType = ftype.Index;
                    }
                    // CONIFER PLANTATION
                    if (forTypValue[ftype.Index] > maxConPlantValue && ftype.BaseFuel == BaseFuelType.ConiferPlantation)
                    {

                        maxConPlantValue = forTypValue[ftype.Index];
                        if(maxConPlantValue > maxConiferValue)
                            coniferFuelType = ftype.Index;
                    }

                    // OPEN
                    if (forTypValue[ftype.Index] > maxOpenValue && ftype.BaseFuel == BaseFuelType.Open)
                    {

                        maxOpenValue = forTypValue[ftype.Index];
                        openFuelType = ftype.Index;
                    }

                    // SLASH
                    if (forTypValue[ftype.Index] > maxSlashValue && ftype.BaseFuel == BaseFuelType.Slash)
                    {

                        maxSlashValue = forTypValue[ftype.Index];
                        slashFuelType = ftype.Index;
                    }

                    // DECIDUOUS
                    if(forTypValue[ftype.Index] > maxDecidValue && ftype.BaseFuel == BaseFuelType.Deciduous)
                    {

                        maxDecidValue = forTypValue[ftype.Index];
                        decidFuelType = ftype.Index;
                    }

                }
            }

            // Rules indicating a CONIFER cell
            if (maxConiferValue >= maxConPlantValue
                && maxConiferValue >= maxDecidValue
                && maxConiferValue >= maxOpenValue
                && maxConiferValue >= maxSlashValue)
            {
                maxValue = maxConiferValue;
            }

            // Rules indicating a DECIDUOUS cell
            else if (maxDecidValue >= maxConiferValue
                    && maxDecidValue >= maxConPlantValue
                    && maxDecidValue >= maxOpenValue
                    && maxDecidValue >= maxSlashValue)
            {
                maxValue = maxDecidValue;
            }

            // Rules indicating a CONIFER PLANTATION cell
            else if (maxConPlantValue >= maxConiferValue
                    && maxConPlantValue >= maxDecidValue
                    && maxConPlantValue >= maxOpenValue
                    && maxConPlantValue >= maxSlashValue)
            {
                maxValue = maxConPlantValue;
                finalFuelType = coniferFuelType;
                decidFuelType = 0;
                sumConifer = 100;
                sumDecid = 0;
            }

            // Rules indicating a SLASH cell
            else if (maxSlashValue >= maxConiferValue
                    && maxSlashValue >= maxConPlantValue
                    && maxSlashValue >= maxDecidValue
                    && maxSlashValue >= maxOpenValue)
            {
                maxValue = maxSlashValue;
                finalFuelType = slashFuelType;
                decidFuelType = 0;
                sumConifer = 0;
                sumDecid = 0;
            }

            // Rules indicating an OPEN (typically grass) cell
            else if (maxOpenValue >= maxConiferValue
                    && maxOpenValue >= maxConPlantValue
                    && maxOpenValue >= maxDecidValue
                    && maxOpenValue >= maxSlashValue)
            {
                maxValue = maxOpenValue;
                finalFuelType = openFuelType;
                decidFuelType = 0;
                sumConifer = 0;
                sumDecid = 0;
            }


            //Set the PERCENT DOMINANCE values:
            if (sumConifer > 0 || sumDecid > 0)
            {
                coniferDominance = (int)((sumConifer / (sumConifer + sumDecid) * 100) + 0.5);
                hardwoodDominance = (int)((sumDecid / (sumConifer + sumDecid) * 100) + 0.5);
                if (hardwoodDominance < hardwoodMax)
                {
                    coniferDominance = 100;
                    hardwoodDominance = 0;
                    finalFuelType = coniferFuelType;
                    decidFuelType = 0;
                }
                if (coniferDominance < hardwoodMax)
                {
                    coniferDominance = 0;
                    hardwoodDominance = 100;
                    finalFuelType = decidFuelType;
                    decidFuelType = 0;
                }
                if (hardwoodDominance > hardwoodMax && coniferDominance > hardwoodMax)
                    finalFuelType = coniferFuelType;
            }

            //---------------------------------------------------------------------
            // Next check the disturbance types.  This will override any other existing fuel type.
            foreach(DisturbanceType slash in DisturbanceTypes)
            {
                //if (SiteVars.HarvestCohortsKilled != null && SiteVars.HarvestCohortsKilled[site] > 0)
                //{
                    if (SiteVars.TimeOfLastHarvest != null &&
                        (Model.Core.CurrentTime - SiteVars.TimeOfLastHarvest[site] <= slash.MaxAge))
                    {
                        foreach (string pName in slash.PrescriptionNames)
                        {
                            if (SiteVars.HarvestPrescriptionName != null && SiteVars.HarvestPrescriptionName[site].Trim() == pName.Trim())
                            {
                                finalFuelType = slash.FuelIndex; //Name;
                                decidFuelType = 0;
                                coniferDominance = 0;
                                hardwoodDominance = 0;
                            }
                        }
                    }
                //}
                //Check for fire severity effects of fuel type
                if (SiteVars.FireSeverity != null && SiteVars.FireSeverity[site] > 0)
                {
                    if (SiteVars.TimeOfLastFire != null &&
                        (Model.Core.CurrentTime - SiteVars.TimeOfLastFire[site] <= slash.MaxAge))
                    {
                        foreach (string pName in slash.PrescriptionNames)
                        {
                            if (pName.StartsWith("FireSeverity"))
                            {
                                if((pName.Substring((pName.Length - 1), 1)).ToString() == SiteVars.FireSeverity[site].ToString())
                                {
                                    finalFuelType = slash.FuelIndex; //Name;
                                    decidFuelType = 0;
                                    coniferDominance = 0;
                                    hardwoodDominance = 0;
                                }
                            }
                        }
                    }
                }
                //Check for wind severity effects of fuel type
                if (SiteVars.WindSeverity != null && SiteVars.WindSeverity[site] > 0)
                {
                    if (SiteVars.TimeOfLastWind != null &&
                        (Model.Core.CurrentTime - SiteVars.TimeOfLastWind[site] <= slash.MaxAge))
                    {
                        foreach (string pName in slash.PrescriptionNames)
                        {
                            if (pName.StartsWith("WindSeverity"))
                            {
                                if ((pName.Substring((pName.Length - 1), 1)).ToString() == SiteVars.WindSeverity[site].ToString())
                                {
                                    finalFuelType = slash.FuelIndex; //Name;
                                    decidFuelType = 0;
                                    coniferDominance = 0;
                                    hardwoodDominance = 0;
                                }
                            }
                        }
                    }
                }
            }

            SiteVars.PercentConifer[site]   = coniferDominance;
            SiteVars.PercentHardwood[site]  = hardwoodDominance;

            SiteVars.FuelType[site]         = finalFuelType;
            SiteVars.DecidFuelType[site]    = decidFuelType;

            return finalFuelType;

        }
Ejemplo n.º 26
0
        //---------------------------------------------------------------------
        public static void ResetAnnualValues(Site site)
        {
            // Reset these accumulators to zero:
            SiteVars.CohortLeafN[site] = 0.0;
            SiteVars.CohortLeafC[site] = 0.0;
            SiteVars.CohortWoodN[site] = 0.0;
            SiteVars.CohortWoodC[site] = 0.0;
            SiteVars.GrossMineralization[site] = 0.0;
            SiteVars.AGNPPcarbon[site] = 0.0;
            SiteVars.BGNPPcarbon[site] = 0.0;
            SiteVars.LitterfallC[site] = 0.0;

            SiteVars.Stream[site]          = new Layer(LayerName.Other, LayerType.Other);
            SiteVars.SourceSink[site]      = new Layer(LayerName.Other, LayerType.Other);

            SiteVars.SurfaceDeadWood[site].NetMineralization = 0.0;
            SiteVars.SurfaceStructural[site].NetMineralization = 0.0;
            SiteVars.SurfaceMetabolic[site].NetMineralization = 0.0;

            SiteVars.SoilDeadWood[site].NetMineralization = 0.0;
            SiteVars.SoilStructural[site].NetMineralization = 0.0;
            SiteVars.SoilMetabolic[site].NetMineralization = 0.0;

            SiteVars.SOM1surface[site].NetMineralization = 0.0;
            SiteVars.SOM1soil[site].NetMineralization = 0.0;
            SiteVars.SOM2[site].NetMineralization = 0.0;
            SiteVars.SOM3[site].NetMineralization = 0.0;
            SiteVars.AnnualNEE[site] = 0.0;
            //SiteVars.FireEfflux[site] = 0.0;
            //SiteVars.AgeMortality[site] = 0.0;
        }
        //---------------------------------------------------------------------

        AgeCohort.ISiteCohorts ILandscapeCohorts<AgeCohort.ISiteCohorts>.this[Site site]
        {
            get {
                return cohorts[site];
            }
        }
        //---------------------------------------------------------------------
        private byte CalcForestType(Site site, IForestType[] forestTypes)
        {
            int forTypeCnt = 0;

            double[] forTypValue = new double[forestTypes.Length];
            Species.IDataset SpeciesDataset = modelCore.Species;
            foreach(ISpecies species in SpeciesDataset)
            {
                ushort maxSpeciesAge = 0;
                double sppValue = 0.0;
                //ISpeciesCohorts speciesCohorts = cohorts[species];
                maxSpeciesAge = AgeCohort.Util.GetMaxAge(cohorts[site][species]);
                //MaxAge(speciesCohorts);

                if(maxSpeciesAge > 0)
                {
                    sppValue = (double) maxSpeciesAge /
                        (double) species.Longevity *
                        (double) reclassCoefs[species.Index];

                    forTypeCnt = 0;
                    foreach(IForestType ftype in forestTypes)
                    {
                        if(ftype[species.Index] != 0)
                        {
                            if(ftype[species.Index] == -1)
                                forTypValue[forTypeCnt] -= sppValue;
                            if(ftype[species.Index] == 1)
                                forTypValue[forTypeCnt] += sppValue;
                        }
                        forTypeCnt++;
                    }
                }
            }

            int finalForestType = 0;
            double maxValue = 0.0;
            forTypeCnt = 0;
            foreach(IForestType ftype in forestTypes)
            {
                //System.Console.WriteLine("ForestTypeNum={0}, Value={1}.",forTypeCnt,forTypValue[forTypeCnt]);
                if(forTypValue[forTypeCnt]>maxValue)
                {
                    maxValue = forTypValue[forTypeCnt];
                    finalForestType = forTypeCnt+1;
                }
                forTypeCnt++;
            }
            return (byte) finalForestType;
        }
		//---------------------------------------------------------------------

		private List<Site> GetNeighbors(Site site, int windDirection)
		{
			List<Site> neighbors = new List<Site>(5);
			foreach (RelativeLocation relativeLoc in neighborhood) {
				Site neighbor = site.GetNeighbor(relativeLoc);
				if (neighbor != null)
					neighbors.Add(neighbor);
			}

			int vertical=0;
			int horizontal=0;
			if(windDirection==1) {  //wind is from south
				vertical = -2;
				horizontal = 0;
			}
			if(windDirection==2) {  //wind is from north
				vertical = 2;
				horizontal = 0;
			}
			if(windDirection==3) {  //wind is from east
				vertical = 0;
				horizontal = -2;
			}
			if(windDirection==4) {  //wind is from west
				vertical = 0;
				horizontal = 2;
			}

			RelativeLocation relativeLoc5 = new RelativeLocation(vertical, horizontal);
			Site neighbor5 = site.GetNeighbor(relativeLoc5);
			if (neighbor5 != null)
				neighbors.Add(neighbor5);

			return neighbors;
		}
Ejemplo n.º 30
0
        //---------------------------------------------------------------------

        /// <summary>
        /// Validates that a site refers to the same landscape as the site
        /// variable was created for.
        /// </summary>
        protected void Validate(Site site)
        {
            Trace.Assert(site != null);
            Trace.Assert(site.Landscape == landscape);
        }