private void CheckDensityDrivenDispersal(ModelGrid gridForDispersal, uint latIndex, uint lonIndex, Cohort cohortToDisperse, int functionalGroup, int cohortNumber) { // Check the population density double NumberOfIndividuals = cohortToDisperse.CohortAbundance; // Get the cell area, in kilometres squared double CellArea = gridForDispersal.GetCellEnvironment(latIndex, lonIndex)["Cell Area"][0]; // If below the density threshold if ((NumberOfIndividuals / CellArea) < _DensityThresholdScaling / cohortToDisperse.AdultMass) { // Temporary variables to keep track of directions in which cohorts enter/exit cells during the multiple advection steps per time step uint ExitDirection = new uint(); uint EntryDirection = new uint(); ExitDirection = 9999; // Check to see if it disperses (based on the same movement scaling as used in diffusive movement) // Calculate dispersal speed for that cohort double DispersalSpeed = CalculateDispersalSpeed(cohortToDisperse.IndividualBodyMass); // Cohort tries to disperse double[] DispersalArray = CalculateDispersalProbability(gridForDispersal, latIndex, lonIndex, CalculateDispersalSpeed(cohortToDisperse.AdultMass)); double CohortDispersed = CheckForDispersal(DispersalArray[0]); if (CohortDispersed > 0) { uint[] DestinationCell = CellToDisperseTo(gridForDispersal, latIndex, lonIndex, DispersalArray, DispersalArray[0], DispersalArray[4], DispersalArray[5], ref ExitDirection, ref EntryDirection); // Update the delta array of cells to disperse to, if the cohort moves if (DestinationCell[0] < 999999) { // Update the delta array of cohorts gridForDispersal.DeltaFunctionalGroupDispersalArray[latIndex, lonIndex].Add((uint)functionalGroup); gridForDispersal.DeltaCohortNumberDispersalArray[latIndex, lonIndex].Add((uint)cohortNumber); // Update the delta array of cells to disperse to gridForDispersal.DeltaCellToDisperseToArray[latIndex, lonIndex].Add(DestinationCell); // Update the delta array of exit and entry directions gridForDispersal.DeltaCellExitDirection[latIndex, lonIndex].Add(ExitDirection); gridForDispersal.DeltaCellEntryDirection[latIndex, lonIndex].Add(EntryDirection); } } } }
/// <summary> /// Calculates the probability of responsive dispersal given average individual dispersal speed and grid cell /// </summary> /// <param name="madingleyGrid">The model grid</param> /// <param name="latIndex">The latitude index of the grid cell to check for dispersal</param> /// <param name="lonIndex">The longitude index of the grid cell to check for dispersal</param> /// <param name="dispersalSpeed">The average dispersal speed of individuals in the acting cohort</param> /// <returns>A six element array. /// The first element is the probability of dispersal. /// The second element is the probability of dispersing in the u (longitudinal) direction /// The third element is the probability of dispersing in the v (latitudinal) direction /// The fourth element is the probability of dispersing in the diagonal direction /// The fifth element is the u velocity /// The sixth element is the v velocity /// Note that the second, third, and fourth elements are always positive; thus, they do not indicate 'direction' in terms of dispersal.</returns> protected double[] CalculateDispersalProbability(ModelGrid madingleyGrid, uint latIndex, uint lonIndex, double dispersalSpeed) { double LatCellLength = madingleyGrid.CellHeightsKm[latIndex]; double LonCellLength = madingleyGrid.CellWidthsKm[latIndex]; // Pick a direction at random double RandomDirection = RandomNumberGenerator.GetUniform() * 2 * Math.PI; // Calculate the u and v components given the dispersal speed double uSpeed = dispersalSpeed * Math.Cos(RandomDirection); double vSpeed = dispersalSpeed * Math.Sin(RandomDirection); // Check that the whole cell hasn't moved out (i.e. that dispersal speed is not greater than cell length). // This could happen if dispersal speed was high enough; indicates a need to adjust the time step, or to slow dispersal if ((uSpeed > LonCellLength) || (vSpeed > LatCellLength)) { Debug.Fail("Dispersal probability should always be <= 1"); } // Calculate the area of the grid cell that is now outside in the diagonal direction double AreaOutsideBoth = Math.Abs(uSpeed * vSpeed); // Calculate the area of the grid cell that is now outside in the u direction (not including the diagonal) double AreaOutsideU = Math.Abs(uSpeed * LatCellLength) - AreaOutsideBoth; // Calculate the proportion of the grid cell that is outside in the v direction (not including the diagonal double AreaOutsideV = Math.Abs(vSpeed * LonCellLength) - AreaOutsideBoth; // Get the cell area, in kilometres squared double CellArea = madingleyGrid.GetCellEnvironment(latIndex, lonIndex)["Cell Area"][0]; // Convert areas to a probability double DispersalProbability = (AreaOutsideU + AreaOutsideV + AreaOutsideBoth) / CellArea; // Check that we don't have any issues if (DispersalProbability > 1) { //Debug.Fail("Dispersal probability should always be <= 1"); DispersalProbability = 1.0; } double[] NewArray = { DispersalProbability, AreaOutsideU / CellArea, AreaOutsideV / CellArea, AreaOutsideBoth / CellArea, uSpeed, vSpeed }; return(NewArray); }
/// <summary> /// Initializes the ecosystem model /// </summary> /// <param name="mmi">An instance of the model initialisation class</param> public static void Load(Tuple<Madingley.Common.Environment, SortedList<string, EnviroData>> mmi, bool readData) { var e = mmi.Item1; if (e.SpecificLocations == false) { var CellList = new List<Tuple<int, int>>(); var NumLatCells = (uint)((e.TopLatitude - e.BottomLatitude) / e.CellSize); var NumLonCells = (uint)((e.RightmostLongitude - e.LeftmostLongitude) / e.CellSize); // Loop over all cells in the model for (int latitudeIndex = 0; latitudeIndex < NumLatCells; latitudeIndex++) { for (int longitudeIndex = 0; longitudeIndex < NumLonCells; longitudeIndex++) { // Add the vector to the list of all active grid cells CellList.Add(Tuple.Create(latitudeIndex, longitudeIndex)); } } e.FocusCells = CellList; } if (readData) { var cellList = e.FocusCells.Select(a => new UInt32[] { (uint)a.Item1, (uint)a.Item2 }).ToList(); var EcosystemModelGrid = new ModelGrid((float)e.BottomLatitude, (float)e.LeftmostLongitude, (float)e.TopLatitude, (float)e.RightmostLongitude, (float)e.CellSize, (float)e.CellSize, cellList, mmi.Item2, e.SpecificLocations); Func<Tuple<int, int>, IDictionary<string, double[]>> convertCellEnvironment = cell => { var env = EcosystemModelGrid.GetCellEnvironment((uint)cell.Item1, (uint)cell.Item2); return env.ToDictionary(kv => kv.Key, kv => kv.Value.ToArray()); }; e.CellEnvironment = e.FocusCells.Select(convertCellEnvironment).ToList(); } }
/// <summary> /// Initializes the ecosystem model /// </summary> /// <param name="mmi">An instance of the model initialisation class</param> public static void Load(Tuple <Madingley.Common.Environment, SortedList <string, EnviroData> > mmi) { var e = mmi.Item1; if (e.SpecificLocations == false) { var CellList = new List <Tuple <int, int> >(); var NumLatCells = (uint)((e.TopLatitude - e.BottomLatitude) / e.CellSize); var NumLonCells = (uint)((e.RightmostLongitude - e.LeftmostLongitude) / e.CellSize); // Loop over all cells in the model for (int latitudeIndex = 0; latitudeIndex < NumLatCells; latitudeIndex++) { for (int longitudeIndex = 0; longitudeIndex < NumLonCells; longitudeIndex++) { // Add the vector to the list of all active grid cells CellList.Add(Tuple.Create(latitudeIndex, longitudeIndex)); } } e.FocusCells = CellList; } var cellList = e.FocusCells.Select(a => new UInt32[] { (uint)a.Item1, (uint)a.Item2 }).ToList(); var EcosystemModelGrid = new ModelGrid((float)e.BottomLatitude, (float)e.LeftmostLongitude, (float)e.TopLatitude, (float)e.RightmostLongitude, (float)e.CellSize, (float)e.CellSize, cellList, mmi.Item2, e.SpecificLocations); Func <Tuple <int, int>, IDictionary <string, double[]> > convertCellEnvironment = cell => { var env = EcosystemModelGrid.GetCellEnvironment((uint)cell.Item1, (uint)cell.Item2); return(env.ToDictionary(kv => kv.Key, kv => kv.Value.ToArray())); }; e.CellEnvironment = e.FocusCells.Select(convertCellEnvironment).ToList(); }
/// <summary> /// Calculates the probability of diffusive dispersal given average individual dispersal speed /// </summary> /// <param name="madingleyGrid">The model grid</param> /// <param name="latIndex">The latitude index of the grid cell to check for dispersal</param> /// <param name="lonIndex">The longitude index of the grid cell to check for dispersal</param> /// <param name="dispersalSpeed">The average speed at which individuals in this cohort move around their environment, in km per month</param> /// <returns>A six element array. /// The first element is the probability of dispersal. /// The second element is the probability of dispersing in the u (longitudinal) direction /// The third element is the probability of dispersing in the v (latitudinal) direction /// The fourth element is the probability of dispersing in the diagonal direction /// The fifth element is the u velocity modified by the random diffusion component /// The sixth element is the v velocity modified by the random diffusion component /// Note that the second, third, and fourth elements are always positive; thus, they do not indicate 'direction' in terms of dispersal.</returns> private double[] CalculateDispersalProbability(ModelGrid madingleyGrid, uint latIndex, uint lonIndex, double dispersalSpeed) { // Check that the u speed and v speed are not greater than the cell length. If they are, then rescale them; this limits the max velocity // so that cohorts cannot be advected more than one grid cell per time step double LatCellLength = madingleyGrid.CellHeightsKm[latIndex]; double LonCellLength = madingleyGrid.CellWidthsKm[latIndex]; // Pick a direction at random double RandomDirection = RandomNumberGenerator.GetUniform() * 2 * Math.PI; // Calculate the u and v components given the dispersal speed double uSpeed = dispersalSpeed * Math.Cos(RandomDirection); double vSpeed = dispersalSpeed * Math.Sin(RandomDirection); // Calculate the area of the grid cell that is now outside in the diagonal direction double AreaOutsideBoth = Math.Abs(uSpeed * vSpeed); // Calculate the area of the grid cell that is now outside in the u direction (not including the diagonal) double AreaOutsideU = Math.Abs(uSpeed * LatCellLength) - AreaOutsideBoth; // Calculate the proportion of the grid cell that is outside in the v direction (not including the diagonal double AreaOutsideV = Math.Abs(vSpeed * LonCellLength) - AreaOutsideBoth; // Get the cell area, in kilometres squared double CellArea = madingleyGrid.GetCellEnvironment(latIndex, lonIndex)["Cell Area"][0]; // Convert areas to a probability double DispersalProbability = (AreaOutsideU + AreaOutsideV + AreaOutsideBoth) / CellArea; // Check that the whole cell hasn't moved out. This could happen if dispersal speed was high enough if (DispersalProbability >= 1) { Debug.Fail("Dispersal probability in diffusion should always be <= 1"); } double[] NewArray = { DispersalProbability, AreaOutsideU / CellArea, AreaOutsideV / CellArea, AreaOutsideBoth / CellArea, uSpeed, vSpeed }; return(NewArray); }
/// <summary> /// Sets up the model grid within a Madingley model run /// </summary> /// <param name="initialisation">An instance of the model initialisation class</param> /// <param name="scenarioParameters">The parameters for the scenarios to run</param> /// <param name="scenarioIndex">The index of the scenario that this model is to run</param> public void SetUpModelGrid(MadingleyModelInitialisation initialisation, ScenarioParameterInitialisation scenarioParameters, int scenarioIndex, int simulation) { // If the intialisation file contains a column pointing to another file of specific locations, and if this column is not blank then read the // file indicated if (SpecificLocations) { // Set up the model grid using these locations EcosystemModelGrid = new ModelGrid(BottomLatitude, LeftmostLongitude, TopLatitude, RightmostLongitude, CellSize, CellSize, _CellList, EnviroStack, CohortFunctionalGroupDefinitions, StockFunctionalGroupDefinitions, GlobalDiagnosticVariables, initialisation.TrackProcesses, SpecificLocations, RunGridCellsInParallel,GlobalModelTimeStepUnit); } else { _CellList = new List<uint[]>(); //Switched order so we create cell list first then initialise cells using list rather than grid. uint NumLatCells = (uint)((TopLatitude - BottomLatitude) / CellSize); uint NumLonCells = (uint)((RightmostLongitude - LeftmostLongitude) / CellSize); // Loop over all cells in the model for (uint ii = 0; ii < NumLatCells; ii += 1) { for (uint jj = 0; jj < NumLonCells; jj += 1) { // Define a vector to hold the pair of latitude and longitude indices for this grid cell uint[] cellIndices = new uint[2]; // Add the latitude and longitude indices to this vector cellIndices[0] = ii; cellIndices[1] = jj; // Add the vector to the list of all active grid cells _CellList.Add(cellIndices); } } EcologyTimer = new StopWatch(); EcologyTimer.Start(); // Set up a full model grid (i.e. not for specific locations) // Set up the model grid using these locations EcosystemModelGrid = new ModelGrid(BottomLatitude, LeftmostLongitude, TopLatitude, RightmostLongitude, CellSize, CellSize, _CellList, EnviroStack, CohortFunctionalGroupDefinitions, StockFunctionalGroupDefinitions, GlobalDiagnosticVariables, initialisation.TrackProcesses, SpecificLocations, RunGridCellsInParallel, GlobalModelTimeStepUnit); List<int> cellsToRemove = new List<int>(); if (initialisation.RunRealm == "terrestrial") { for (int ii = 0; ii < _CellList.Count; ii += 1) { if ((EcosystemModelGrid.GetCellEnvironment(_CellList[ii][0], _CellList[ii][1])["Realm"][0] == 2.0) || (EcosystemModelGrid.GetCellEnvironment(_CellList[ii][0], _CellList[ii][1])["LandSeaMask"][0] == 0.0)) { cellsToRemove.Add(ii); } } } else if (initialisation.RunRealm == "marine") { for (int ii = 0; ii < _CellList.Count; ii += 1) { if (EcosystemModelGrid.GetCellEnvironment(_CellList[ii][0], _CellList[ii][1])["Realm"][0] == 1.0) { cellsToRemove.Add(ii); } } } for (int ii = (cellsToRemove.Count - 1); ii >= 0; ii--) { _CellList.RemoveAt(cellsToRemove[ii]); } EcologyTimer.Stop(); Console.WriteLine("Time to initialise cells: {0}", EcologyTimer.GetElapsedTimeSecs()); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Madingley Model memory usage post grid cell seed: {0}", GC.GetTotalMemory(true) / 1E9, " (G Bytes)\n"); Console.ForegroundColor = ConsoleColor.White; } if (initialisation.InputState) { InputModelState = new InputModelState(initialisation.ModelStatePath[simulation], initialisation.ModelStateFilename[simulation],EcosystemModelGrid, _CellList); } // When the last simulation for the current scenario // if ((scenarioParameters.scenarioSimulationsNumber.Count == 1) && (scenarioIndex == scenarioParameters.scenarioSimulationsNumber[scenarioIndex] - 1)) EnviroStack.Clear(); // Seed stocks and cohorts in the grid cells // If input state from output from a previous simulation if (initialisation.InputState) { // Seed grid cell cohort and stocks EcosystemModelGrid.SeedGridCellStocksAndCohorts(_CellList, InputModelState, CohortFunctionalGroupDefinitions, StockFunctionalGroupDefinitions); //remove cohorts that do not contain any biomass foreach (uint[] CellPair in _CellList) { GridCellCohortHandler workingGridCellCohorts = EcosystemModelGrid.GetGridCellCohorts(CellPair[0], CellPair[1]); for (int kk = 0; kk < CohortFunctionalGroupDefinitions.GetNumberOfFunctionalGroups(); kk++) { // Loop through each cohort in the functional group for (int ll = (workingGridCellCohorts[kk].Count - 1); ll >= 0; ll--) { // If cohort abundance is less than the extinction threshold then add to the list for extinction if (workingGridCellCohorts[kk][ll].CohortAbundance.CompareTo(0) <= 0 || workingGridCellCohorts[kk][ll].IndividualBodyMass.CompareTo(0.0) == 0) { // Remove the extinct cohort from the list of cohorts workingGridCellCohorts[kk].RemoveAt(ll); } } } } } else { EcosystemModelGrid.SeedGridCellStocksAndCohorts(_CellList, CohortFunctionalGroupDefinitions, StockFunctionalGroupDefinitions, GlobalDiagnosticVariables, ref NextCohortID, InitialisationFileStrings["OutputDetail"] == "high", DrawRandomly, initialisation.DispersalOnly, InitialisationFileStrings["DispersalOnlyType"], RunGridCellsInParallel); } Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Madingley Model memory usage pre Collect: {0}", Math.Round(GC.GetTotalMemory(true) / 1E9, 2), " (GBytes)"); Console.ForegroundColor = ConsoleColor.White; GC.Collect(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Madingley Model memory usage post Collect: {0}", Math.Round(GC.GetTotalMemory(true) / 1E9, 5), " (GBytes)\n"); Console.ForegroundColor = ConsoleColor.White; }
/// <summary> /// Calculates the probability of advective dispersal given the grid cell /// </summary> /// <param name="madingleyGrid">The model grid</param> /// <param name="latIndex">The latitude index of the grid cell to check for dispersal</param> /// <param name="lonIndex">The longitude index of the grid cell to check for dispersal</param> /// <param name="currentMonth">The current model month</param> /// <returns>A six element array. /// The first element is the probability of dispersal. /// The second element is the probability of dispersing in the u (longitudinal) direction /// The third element is the probability of dispersing in the v (latitudinal) direction /// The fourth element is the probability of dispersing in the diagonal direction /// The fifth element is the distance travelled in the u direction (u velocity modified by the random diffusion component) /// The sixth element is the distance travelled in the v direction (v velocity modified by the random diffusion component) /// Note that the second, third, and fourth elements are always positive; thus, they do not indicate 'direction' in terms of dispersal.</returns> private double[] CalculateDispersalProbability(ModelGrid madingleyGrid, uint latIndex, uint lonIndex, uint currentMonth, double rescaleduSpeed, double rescaledvSpeed) { // Distance travelled in u (longitudinal) direction double uDistanceTravelled; // Distance travelled in v (latitudinal) direction double vDistanceTravelled; // U and V components of the diffusive velocity double[] DiffusiveUandVComponents = new double[2]; // Length in km of a cell boundary latitudinally double LatCellLength; // Length in km of a cell boundary longitudinally double LonCellLength; // Area of the grid cell that is outside in the diagonal direction after dispersal, in kilometres squared double AreaOutsideBoth; // Area of the grid cell that is outside in the u (longitudinal) direction after dispersal, in kilometres squared double AreaOutsideU; // Area of the grid cell that is outside in the v (latitudinal) direction after dispersal, in kilometres squared double AreaOutsideV; // Cell area, in kilometres squared double CellArea; // Probability of dispersal double DispersalProbability; // Calculate the diffusive movement speed, with a direction chosen at random DiffusiveUandVComponents = CalculateDiffusion(); // Calculate the distance travelled in this dispersal (not global) time step. both advective and diffusive speeds need to have been converted to km / advective model time step uDistanceTravelled = rescaleduSpeed + DiffusiveUandVComponents[0]; vDistanceTravelled = rescaledvSpeed + DiffusiveUandVComponents[1]; // Check that the u distance travelled and v distance travelled are not greater than the cell length LatCellLength = madingleyGrid.CellHeightsKm[latIndex]; LonCellLength = madingleyGrid.CellWidthsKm[latIndex]; if (Math.Abs(uDistanceTravelled) >= LonCellLength) { Debug.Fail("u velocity greater than cell width"); } if (Math.Abs(vDistanceTravelled) >= LatCellLength) { Debug.Fail("v velocity greater than cell width"); } // We assume that the whole grid cell moves at the given velocity and calculate the area that is then outside the original grid cell location. // This then becomes the probability of dispersal // Calculate the area of the grid cell that is now outside in the diagonal direction. AreaOutsideBoth = Math.Abs(uDistanceTravelled * vDistanceTravelled); // Calculate the area of the grid cell that is now outside in the u (longitudinal) direction (not including the diagonal) AreaOutsideU = Math.Abs(uDistanceTravelled * LatCellLength) - AreaOutsideBoth; // Calculate the proportion of the grid cell that is outside in the v (latitudinal) direction (not including the diagonal) AreaOutsideV = Math.Abs(vDistanceTravelled * LonCellLength) - AreaOutsideBoth; // Get the cell area, in kilometres squared CellArea = madingleyGrid.GetCellEnvironment(latIndex, lonIndex)["Cell Area"][0]; // Convert areas to a probability DispersalProbability = (AreaOutsideU + AreaOutsideV + AreaOutsideBoth) / CellArea; // Check that the whole cell hasn't moved out. Could this happen for the fastest currents in a month? Definitely, // if current speeds were not constrained if (DispersalProbability >= 1) { Debug.Fail("Dispersal probability in advection should always be <= 1"); } double[] NewArray = { DispersalProbability, AreaOutsideU / CellArea, AreaOutsideV / CellArea, AreaOutsideBoth / CellArea, uDistanceTravelled, vDistanceTravelled }; return(NewArray); }
/// <summary> /// Calculates the probability of diffusive dispersal given average individual dispersal speed /// </summary> /// <param name="madingleyGrid">The model grid</param> /// <param name="latIndex">The latitude index of the grid cell to check for dispersal</param> /// <param name="lonIndex">The longitude index of the grid cell to check for dispersal</param> /// <param name="dispersalSpeed">The average speed at which individuals in this cohort move around their environment, in km per month</param> /// <returns>A six element array. /// The first element is the probability of dispersal. /// The second element is the probability of dispersing in the u (longitudinal) direction /// The third element is the probability of dispersing in the v (latitudinal) direction /// The fourth element is the probability of dispersing in the diagonal direction /// The fifth element is the u velocity modified by the random diffusion component /// The sixth element is the v velocity modified by the random diffusion component /// Note that the second, third, and fourth elements are always positive; thus, they do not indicate 'direction' in terms of dispersal.</returns> private double[] CalculateDispersalProbability(ModelGrid madingleyGrid, uint latIndex, uint lonIndex, double dispersalSpeed) { // Check that the u speed and v speed are not greater than the cell length. If they are, then rescale them; this limits the max velocity // so that cohorts cannot be advected more than one grid cell per time step double LatCellLength = madingleyGrid.CellHeightsKm[latIndex]; double LonCellLength = madingleyGrid.CellWidthsKm[latIndex]; // Pick a direction at random double RandomDirection = RandomNumberGenerator.GetUniform() * 2 * Math.PI; // Calculate the u and v components given the dispersal speed double uSpeed = dispersalSpeed * Math.Cos(RandomDirection); double vSpeed = dispersalSpeed * Math.Sin(RandomDirection); // Calculate the area of the grid cell that is now outside in the diagonal direction double AreaOutsideBoth = Math.Abs(uSpeed * vSpeed); // Calculate the area of the grid cell that is now outside in the u direction (not including the diagonal) double AreaOutsideU = Math.Abs(uSpeed * LatCellLength) - AreaOutsideBoth; // Calculate the proportion of the grid cell that is outside in the v direction (not including the diagonal double AreaOutsideV = Math.Abs(vSpeed * LonCellLength) - AreaOutsideBoth; // Get the cell area, in kilometres squared double CellArea = madingleyGrid.GetCellEnvironment(latIndex, lonIndex)["Cell Area"][0]; // Convert areas to a probability double DispersalProbability = (AreaOutsideU + AreaOutsideV + AreaOutsideBoth) / CellArea; // Check that the whole cell hasn't moved out. This could happen if dispersal speed was high enough if (DispersalProbability >= 1) { Debug.Fail("Dispersal probability in diffusion should always be <= 1"); } double[] NewArray = { DispersalProbability, AreaOutsideU / CellArea, AreaOutsideV / CellArea, AreaOutsideBoth / CellArea, uSpeed, vSpeed }; return NewArray; }
public InputModelState(string outputPath, string filename, ModelGrid ecosystemModelGrid, List<uint[]> cellList) { //Set the input state flag to be true _InputState = true; // Construct the string required to access the file using Scientific Dataset string _ReadFileString = "msds:nc?file=input/ModelStates/" + filename +".nc&openMode=readOnly"; // Open the data file using Scientific Dataset DataSet StateDataSet = DataSet.Open(_ReadFileString); float[] Latitude = StateDataSet.GetData<float[]>("Latitude"); float[] Longitude = StateDataSet.GetData<float[]>("Longitude"); float[] CohortFunctionalGroup = StateDataSet.GetData<float[]>("Cohort Functional Group"); float[] Cohort = StateDataSet.GetData<float[]>("Cohort"); float[] StockFunctionalGroup = StateDataSet.GetData<float[]>("Stock Functional Group"); float[] Stock = StateDataSet.GetData<float[]>("Stock"); // Check that the longitudes and latitudes in the input state match the cell environment for (int la = 0; la < Latitude.Length; la++) { Debug.Assert(ecosystemModelGrid.GetCellEnvironment((uint)la, 0)["Latitude"][0] == Latitude[la], "Error: input-state grid doesn't match current model grid"); } for (int lo = 0; lo < Longitude.Length; lo++) { Debug.Assert(ecosystemModelGrid.GetCellEnvironment(0, (uint)lo)["Longitude"][0] == Longitude[lo], "Error: input-state grid doesn't match current model grid"); } List<double[,,]> CohortJuvenileMass = new List<double[,,]>(); List<double[,,]> CohortAdultMass = new List<double[,,]>(); List<double[,,]> CohortIndividualBodyMass = new List<double[,,]>(); List<double[,,]> CohortCohortAbundance = new List<double[,,]>(); List<double[,,]> CohortLogOptimalPreyBodySizeRatio = new List<double[,,]>(); List<double[,,]> CohortBirthTimeStep = new List<double[,,]>(); List<double[,,]> CohortProportionTimeActive = new List<double[,,]>(); List<double[,,]> CohortTrophicIndex = new List<double[,,]>(); double[,,,] tempData = new double[Latitude.Length, Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]; tempData = StateDataSet.GetData<double[,,,]>("CohortJuvenileMass"); for (int la = 0; la < Latitude.Length; la++) { CohortJuvenileMass.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortJuvenileMass[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortAdultMass"); for (int la = 0; la < Latitude.Length; la++) { CohortAdultMass.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortAdultMass[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortIndividualBodyMass"); for (int la = 0; la < Latitude.Length; la++) { CohortIndividualBodyMass.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortIndividualBodyMass[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortCohortAbundance"); for (int la = 0; la < Latitude.Length; la++) { CohortCohortAbundance.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortCohortAbundance[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortLogOptimalPreyBodySizeRatio"); for (int la = 0; la < Latitude.Length; la++) { CohortLogOptimalPreyBodySizeRatio.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortLogOptimalPreyBodySizeRatio[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortBirthTimeStep"); for (int la = 0; la < Latitude.Length; la++) { CohortBirthTimeStep.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortBirthTimeStep[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortProportionTimeActive"); for (int la = 0; la < Latitude.Length; la++) { CohortProportionTimeActive.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortProportionTimeActive[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortTrophicIndex"); for (int la = 0; la < Latitude.Length; la++) { CohortTrophicIndex.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortTrophicIndex[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } _GridCellCohorts = new GridCellCohortHandler[Latitude.Length, Longitude.Length]; long temp = 0; for (int cell = 0; cell < cellList.Count; cell++) { _GridCellCohorts[cellList[cell][0], cellList[cell][1]] = new GridCellCohortHandler(CohortFunctionalGroup.Length); for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { _GridCellCohorts[cellList[cell][0], cellList[cell][1]][fg] = new List<Cohort>(); for (int c = 0; c < Cohort.Length; c++) { if (CohortCohortAbundance[(int)cellList[cell][0]][cellList[cell][1],fg,c] > 0.0) { Cohort TempCohort = new Cohort( (byte)fg, CohortJuvenileMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], CohortAdultMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], CohortIndividualBodyMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], CohortCohortAbundance[(int)cellList[cell][0]][cellList[cell][1], fg, c], Math.Exp(CohortLogOptimalPreyBodySizeRatio[(int)cellList[cell][0]][cellList[cell][1], fg, c]), Convert.ToUInt16(CohortBirthTimeStep[(int)cellList[cell][0]][cellList[cell][1], fg, c]), CohortProportionTimeActive[(int)cellList[cell][0]][cellList[cell][1], fg, c], ref temp, CohortTrophicIndex[(int)cellList[cell][0]][cellList[cell][1], fg, c], false); _GridCellCohorts[cellList[cell][0], cellList[cell][1]][fg].Add(TempCohort); } } } } CohortJuvenileMass.RemoveRange(0, CohortJuvenileMass.Count); CohortAdultMass.RemoveRange(0, CohortAdultMass.Count); CohortIndividualBodyMass.RemoveRange(0, CohortIndividualBodyMass.Count); CohortCohortAbundance.RemoveRange(0, CohortCohortAbundance.Count); CohortLogOptimalPreyBodySizeRatio.RemoveRange(0, CohortLogOptimalPreyBodySizeRatio.Count); CohortBirthTimeStep.RemoveRange(0, CohortBirthTimeStep.Count); CohortProportionTimeActive.RemoveRange(0, CohortProportionTimeActive.Count); CohortTrophicIndex.RemoveRange(0, CohortTrophicIndex.Count); List<double[,,]> StockIndividualBodyMass = new List<double[,,]>(); List<double[,,]> StockTotalBiomass = new List<double[,,]>(); double[,,,] tempData2 = new double[Latitude.Length, Longitude.Length, StockFunctionalGroup.Length,Stock.Length]; tempData2 = StateDataSet.GetData<double[,,,]>("StockIndividualBodyMass"); for (int la = 0; la < Latitude.Length; la++) { StockIndividualBodyMass.Add(new double[Longitude.Length, StockFunctionalGroup.Length, Stock.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < StockFunctionalGroup.Length; fg++) { for (int c = 0; c < Stock.Length; c++) { StockIndividualBodyMass[(int)cell[0]][cell[1], fg, c] = tempData2[ cell[0], cell[1], fg, c]; } } } tempData2 = StateDataSet.GetData<double[,,,]>("StockTotalBiomass"); for (int la = 0; la < Latitude.Length; la++) { StockTotalBiomass.Add(new double[Longitude.Length, StockFunctionalGroup.Length, Stock.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < StockFunctionalGroup.Length; fg++) { for (int c = 0; c < Stock.Length; c++) { StockTotalBiomass[(int)cell[0]][cell[1], fg, c] = tempData2[ cell[0], cell[1], fg, c]; } } } _GridCellStocks = new GridCellStockHandler[Latitude.Length, Longitude.Length]; for (int cell = 0; cell < cellList.Count; cell++) { _GridCellStocks[cellList[cell][0], cellList[cell][1]] = new GridCellStockHandler(StockFunctionalGroup.Length); for (int fg = 0; fg < StockFunctionalGroup.Length; fg++) { _GridCellStocks[cellList[cell][0], cellList[cell][1]][fg] = new List<Stock>(); for (int c = 0; c < Stock.Length; c++) { if (StockTotalBiomass[(int)cellList[cell][0]][cellList[cell][1], fg, c] > 0.0) { Stock TempStock = new Stock( (byte)fg, StockIndividualBodyMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], StockTotalBiomass[(int)cellList[cell][0]][cellList[cell][1], fg, c]); _GridCellStocks[cellList[cell][0], cellList[cell][1]][fg].Add(TempStock); } } } } }
/// <summary> /// Calculates the probability of advective dispersal given the grid cell /// </summary> /// <param name="madingleyGrid">The model grid</param> /// <param name="latIndex">The latitude index of the grid cell to check for dispersal</param> /// <param name="lonIndex">The longitude index of the grid cell to check for dispersal</param> /// <param name="currentMonth">The current model month</param> /// <returns>A six element array. /// The first element is the probability of dispersal. /// The second element is the probability of dispersing in the u (longitudinal) direction /// The third element is the probability of dispersing in the v (latitudinal) direction /// The fourth element is the probability of dispersing in the diagonal direction /// The fifth element is the distance travelled in the u direction (u velocity modified by the random diffusion component) /// The sixth element is the distance travelled in the v direction (v velocity modified by the random diffusion component) /// Note that the second, third, and fourth elements are always positive; thus, they do not indicate 'direction' in terms of dispersal.</returns> private double[] CalculateDispersalProbability(ModelGrid madingleyGrid, uint latIndex, uint lonIndex, uint currentMonth, double rescaleduSpeed, double rescaledvSpeed) { // Distance travelled in u (longitudinal) direction double uDistanceTravelled; // Distance travelled in v (latitudinal) direction double vDistanceTravelled; // U and V components of the diffusive velocity double[] DiffusiveUandVComponents = new double[2]; // Length in km of a cell boundary latitudinally double LatCellLength; // Length in km of a cell boundary longitudinally double LonCellLength; // Area of the grid cell that is outside in the diagonal direction after dispersal, in kilometres squared double AreaOutsideBoth; // Area of the grid cell that is outside in the u (longitudinal) direction after dispersal, in kilometres squared double AreaOutsideU; // Area of the grid cell that is outside in the v (latitudinal) direction after dispersal, in kilometres squared double AreaOutsideV; // Cell area, in kilometres squared double CellArea; // Probability of dispersal double DispersalProbability; // Calculate the diffusive movement speed, with a direction chosen at random DiffusiveUandVComponents = CalculateDiffusion(); // Calculate the distance travelled in this dispersal (not global) time step. both advective and diffusive speeds need to have been converted to km / advective model time step uDistanceTravelled = rescaleduSpeed + DiffusiveUandVComponents[0]; vDistanceTravelled = rescaledvSpeed + DiffusiveUandVComponents[1]; // Check that the u distance travelled and v distance travelled are not greater than the cell length LatCellLength = madingleyGrid.CellHeightsKm[latIndex]; LonCellLength = madingleyGrid.CellWidthsKm[latIndex]; if (Math.Abs(uDistanceTravelled) >= LonCellLength) { Debug.Fail("u velocity greater than cell width"); } if (Math.Abs(vDistanceTravelled) >= LatCellLength) { Debug.Fail("v velocity greater than cell width"); } // We assume that the whole grid cell moves at the given velocity and calculate the area that is then outside the original grid cell location. // This then becomes the probability of dispersal // Calculate the area of the grid cell that is now outside in the diagonal direction. AreaOutsideBoth = Math.Abs(uDistanceTravelled * vDistanceTravelled); // Calculate the area of the grid cell that is now outside in the u (longitudinal) direction (not including the diagonal) AreaOutsideU = Math.Abs(uDistanceTravelled * LatCellLength) - AreaOutsideBoth; // Calculate the proportion of the grid cell that is outside in the v (latitudinal) direction (not including the diagonal) AreaOutsideV = Math.Abs(vDistanceTravelled * LonCellLength) - AreaOutsideBoth; // Get the cell area, in kilometres squared CellArea = madingleyGrid.GetCellEnvironment(latIndex, lonIndex)["Cell Area"][0]; // Convert areas to a probability DispersalProbability = (AreaOutsideU + AreaOutsideV + AreaOutsideBoth) / CellArea; // Check that the whole cell hasn't moved out. Could this happen for the fastest currents in a month? Definitely, // if current speeds were not constrained if (DispersalProbability >= 1) { Debug.Fail("Dispersal probability in advection should always be <= 1"); } double[] NewArray = { DispersalProbability, AreaOutsideU / CellArea, AreaOutsideV / CellArea, AreaOutsideBoth / CellArea, uDistanceTravelled, vDistanceTravelled }; return NewArray; }
public InputModelState(string outputPath, string filename, ModelGrid ecosystemModelGrid, List <uint[]> cellList) { //Set the input state flag to be true _InputState = true; // Construct the string required to access the file using Scientific Dataset string _ReadFileString = "msds:nc?file=input/ModelStates/" + filename + ".nc&openMode=readOnly"; // Open the data file using Scientific Dataset DataSet StateDataSet = DataSet.Open(_ReadFileString); float[] Latitude = StateDataSet.GetData <float[]>("Latitude"); float[] Longitude = StateDataSet.GetData <float[]>("Longitude"); float[] CohortFunctionalGroup = StateDataSet.GetData <float[]>("Cohort Functional Group"); float[] Cohort = StateDataSet.GetData <float[]>("Cohort"); float[] StockFunctionalGroup = StateDataSet.GetData <float[]>("Stock Functional Group"); float[] Stock = StateDataSet.GetData <float[]>("Stock"); // Check that the longitudes and latitudes in the input state match the cell environment for (int la = 0; la < Latitude.Length; la++) { Debug.Assert(ecosystemModelGrid.GetCellEnvironment((uint)la, 0)["Latitude"][0] == Latitude[la], "Error: input-state grid doesn't match current model grid"); } for (int lo = 0; lo < Longitude.Length; lo++) { Debug.Assert(ecosystemModelGrid.GetCellEnvironment(0, (uint)lo)["Longitude"][0] == Longitude[lo], "Error: input-state grid doesn't match current model grid"); } List <double[, , ]> CohortJuvenileMass = new List <double[, , ]>(); List <double[, , ]> CohortAdultMass = new List <double[, , ]>(); List <double[, , ]> CohortIndividualBodyMass = new List <double[, , ]>(); List <double[, , ]> CohortCohortAbundance = new List <double[, , ]>(); List <double[, , ]> CohortLogOptimalPreyBodySizeRatio = new List <double[, , ]>(); List <double[, , ]> CohortBirthTimeStep = new List <double[, , ]>(); List <double[, , ]> CohortProportionTimeActive = new List <double[, , ]>(); List <double[, , ]> CohortTrophicIndex = new List <double[, , ]>(); double[,,,] tempData = new double[Latitude.Length, Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]; tempData = StateDataSet.GetData <double[, , , ]>("CohortJuvenileMass"); for (int la = 0; la < Latitude.Length; la++) { CohortJuvenileMass.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortJuvenileMass[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortAdultMass"); for (int la = 0; la < Latitude.Length; la++) { CohortAdultMass.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortAdultMass[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortIndividualBodyMass"); for (int la = 0; la < Latitude.Length; la++) { CohortIndividualBodyMass.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortIndividualBodyMass[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortCohortAbundance"); for (int la = 0; la < Latitude.Length; la++) { CohortCohortAbundance.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortCohortAbundance[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortLogOptimalPreyBodySizeRatio"); for (int la = 0; la < Latitude.Length; la++) { CohortLogOptimalPreyBodySizeRatio.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortLogOptimalPreyBodySizeRatio[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortBirthTimeStep"); for (int la = 0; la < Latitude.Length; la++) { CohortBirthTimeStep.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortBirthTimeStep[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortProportionTimeActive"); for (int la = 0; la < Latitude.Length; la++) { CohortProportionTimeActive.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortProportionTimeActive[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortTrophicIndex"); for (int la = 0; la < Latitude.Length; la++) { CohortTrophicIndex.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortTrophicIndex[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } _GridCellCohorts = new GridCellCohortHandler[Latitude.Length, Longitude.Length]; long temp = 0; for (int cell = 0; cell < cellList.Count; cell++) { _GridCellCohorts[cellList[cell][0], cellList[cell][1]] = new GridCellCohortHandler(CohortFunctionalGroup.Length); for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { _GridCellCohorts[cellList[cell][0], cellList[cell][1]][fg] = new List <Cohort>(); for (int c = 0; c < Cohort.Length; c++) { if (CohortCohortAbundance[(int)cellList[cell][0]][cellList[cell][1], fg, c] > 0.0) { Cohort TempCohort = new Cohort( (byte)fg, CohortJuvenileMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], CohortAdultMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], CohortIndividualBodyMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], CohortCohortAbundance[(int)cellList[cell][0]][cellList[cell][1], fg, c], Math.Exp(CohortLogOptimalPreyBodySizeRatio[(int)cellList[cell][0]][cellList[cell][1], fg, c]), Convert.ToUInt16(CohortBirthTimeStep[(int)cellList[cell][0]][cellList[cell][1], fg, c]), CohortProportionTimeActive[(int)cellList[cell][0]][cellList[cell][1], fg, c], ref temp, CohortTrophicIndex[(int)cellList[cell][0]][cellList[cell][1], fg, c], false); _GridCellCohorts[cellList[cell][0], cellList[cell][1]][fg].Add(TempCohort); } } } } CohortJuvenileMass.RemoveRange(0, CohortJuvenileMass.Count); CohortAdultMass.RemoveRange(0, CohortAdultMass.Count); CohortIndividualBodyMass.RemoveRange(0, CohortIndividualBodyMass.Count); CohortCohortAbundance.RemoveRange(0, CohortCohortAbundance.Count); CohortLogOptimalPreyBodySizeRatio.RemoveRange(0, CohortLogOptimalPreyBodySizeRatio.Count); CohortBirthTimeStep.RemoveRange(0, CohortBirthTimeStep.Count); CohortProportionTimeActive.RemoveRange(0, CohortProportionTimeActive.Count); CohortTrophicIndex.RemoveRange(0, CohortTrophicIndex.Count); List <double[, , ]> StockIndividualBodyMass = new List <double[, , ]>(); List <double[, , ]> StockTotalBiomass = new List <double[, , ]>(); double[,,,] tempData2 = new double[Latitude.Length, Longitude.Length, StockFunctionalGroup.Length, Stock.Length]; tempData2 = StateDataSet.GetData <double[, , , ]>("StockIndividualBodyMass"); for (int la = 0; la < Latitude.Length; la++) { StockIndividualBodyMass.Add(new double[Longitude.Length, StockFunctionalGroup.Length, Stock.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < StockFunctionalGroup.Length; fg++) { for (int c = 0; c < Stock.Length; c++) { StockIndividualBodyMass[(int)cell[0]][cell[1], fg, c] = tempData2[ cell[0], cell[1], fg, c]; } } } tempData2 = StateDataSet.GetData <double[, , , ]>("StockTotalBiomass"); for (int la = 0; la < Latitude.Length; la++) { StockTotalBiomass.Add(new double[Longitude.Length, StockFunctionalGroup.Length, Stock.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < StockFunctionalGroup.Length; fg++) { for (int c = 0; c < Stock.Length; c++) { StockTotalBiomass[(int)cell[0]][cell[1], fg, c] = tempData2[ cell[0], cell[1], fg, c]; } } } _GridCellStocks = new GridCellStockHandler[Latitude.Length, Longitude.Length]; for (int cell = 0; cell < cellList.Count; cell++) { _GridCellStocks[cellList[cell][0], cellList[cell][1]] = new GridCellStockHandler(StockFunctionalGroup.Length); for (int fg = 0; fg < StockFunctionalGroup.Length; fg++) { _GridCellStocks[cellList[cell][0], cellList[cell][1]][fg] = new List <Stock>(); for (int c = 0; c < Stock.Length; c++) { if (StockTotalBiomass[(int)cellList[cell][0]][cellList[cell][1], fg, c] > 0.0) { Stock TempStock = new Stock( (byte)fg, StockIndividualBodyMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], StockTotalBiomass[(int)cellList[cell][0]][cellList[cell][1], fg, c]); _GridCellStocks[cellList[cell][0], cellList[cell][1]][fg].Add(TempStock); } } } } }
/// <summary> /// Calculates the probability of responsive dispersal given average individual dispersal speed and grid cell /// </summary> /// <param name="madingleyGrid">The model grid</param> /// <param name="latIndex">The latitude index of the grid cell to check for dispersal</param> /// <param name="lonIndex">The longitude index of the grid cell to check for dispersal</param> /// <param name="dispersalSpeed">The average dispersal speed of individuals in the acting cohort</param> /// <returns>A six element array. /// The first element is the probability of dispersal. /// The second element is the probability of dispersing in the u (longitudinal) direction /// The third element is the probability of dispersing in the v (latitudinal) direction /// The fourth element is the probability of dispersing in the diagonal direction /// The fifth element is the u velocity /// The sixth element is the v velocity /// Note that the second, third, and fourth elements are always positive; thus, they do not indicate 'direction' in terms of dispersal.</returns> protected double[] CalculateDispersalProbability(ModelGrid madingleyGrid, uint latIndex, uint lonIndex, double dispersalSpeed) { double LatCellLength = madingleyGrid.CellHeightsKm[latIndex]; double LonCellLength = madingleyGrid.CellWidthsKm[latIndex]; // Pick a direction at random double RandomDirection = RandomNumberGenerator.GetUniform() * 2 * Math.PI; // Calculate the u and v components given the dispersal speed double uSpeed = dispersalSpeed * Math.Cos(RandomDirection); double vSpeed = dispersalSpeed * Math.Sin(RandomDirection); // Check that the whole cell hasn't moved out (i.e. that dispersal speed is not greater than cell length). // This could happen if dispersal speed was high enough; indicates a need to adjust the time step, or to slow dispersal if ((uSpeed > LonCellLength) || (vSpeed > LatCellLength)) { Debug.Fail("Dispersal probability should always be <= 1"); } // Calculate the area of the grid cell that is now outside in the diagonal direction double AreaOutsideBoth = Math.Abs(uSpeed * vSpeed); // Calculate the area of the grid cell that is now outside in the u direction (not including the diagonal) double AreaOutsideU = Math.Abs(uSpeed * LatCellLength) - AreaOutsideBoth; // Calculate the proportion of the grid cell that is outside in the v direction (not including the diagonal double AreaOutsideV = Math.Abs(vSpeed * LonCellLength) - AreaOutsideBoth; // Get the cell area, in kilometres squared double CellArea = madingleyGrid.GetCellEnvironment(latIndex, lonIndex)["Cell Area"][0]; // Convert areas to a probability double DispersalProbability = (AreaOutsideU + AreaOutsideV + AreaOutsideBoth) / CellArea; // Check that we don't have any issues if (DispersalProbability > 1) { //Debug.Fail("Dispersal probability should always be <= 1"); DispersalProbability = 1.0; } double[] NewArray = { DispersalProbability, AreaOutsideU / CellArea, AreaOutsideV / CellArea, AreaOutsideBoth / CellArea, uSpeed, vSpeed }; return NewArray; }