Пример #1
0
        /// <summary>Called by the job runner when all jobs completed</summary>
        public void Completed()
        {
            var storage = Apsim.Find(simulations, typeof(IDataStore)) as IDataStore;

            storage.Writer.WaitForIdle();

            RunPostSimulationTools(simulations, storage);

            storage.Writer.Stop();

            // Optionally run the tests
            if (runTests)
            {
                foreach (ITest test in Apsim.ChildrenRecursively(simulations, typeof(ITest)))
                {
                    simulations.Links.Resolve(test);

                    // If we run into problems, we will want to include the name of the test in the
                    // exception's message. However, tests may be manager scripts, which always have
                    // a name of 'Script'. Therefore, if the test's parent is a Manager, we use the
                    // manager's name instead.
                    string testName = test.Parent is Manager ? test.Parent.Name : test.Name;
                    try
                    {
                        test.Run();
                    }
                    catch (Exception err)
                    {
                        throw new Exception("Encountered an error while running test " + testName, err);
                    }
                }
            }

            simulationEnumerator = null;
            storage.Reader.Refresh();
        }
Пример #2
0
        /// <summary>
        /// Constructor for an aggregated column.
        /// </summary>
        /// <param name="aggregationFunction">The aggregation function</param>
        /// <param name="variableName">The name of the APSIM variable to retrieve</param>
        /// <param name="columnName">The column name to write to the output</param>
        /// <param name="from">The beginning of the capture window</param>
        /// <param name="to">The end of the capture window</param>
        /// <param name="frequenciesFromReport">Reporting frequencies</param>
        /// <param name="parentModel">The parent model</param>
        /// <returns>The newly created ReportColumn</returns>
        private ReportColumn(string aggregationFunction, string variableName, string columnName, string from, string to, string[] frequenciesFromReport, IModel parentModel)
        {
            this.aggregationFunction = aggregationFunction;
            this.variableName        = variableName;
            this.heading             = columnName;
            this.parentModel         = parentModel;
            this.inCaptureWindow     = false;
            this.reportingFrequencies.AddRange(frequenciesFromReport);
            this.clock = Apsim.Find(parentModel, typeof(Clock)) as Clock;

            Apsim.Subscribe(parentModel, "[Clock].StartOfDay", this.OnStartOfDay);
            Apsim.Subscribe(parentModel, "[Clock].DoReportCalculations", this.OnEndOfDay);

            if (DateTime.TryParse(from, out this.fromDate))
            {
                this.fromHasNoYear = !from.Contains(this.fromDate.Year.ToString());
            }
            else
            {
                Apsim.Subscribe(parentModel, from, this.OnBeginCapture);
            }

            if (DateTime.TryParse(to, out this.toDate))
            {
                this.toHasNoYear = !to.Contains(this.toDate.Year.ToString());
            }
            else
            {
                Apsim.Subscribe(parentModel, to, this.OnEndCapture);
            }

            foreach (string frequency in this.reportingFrequencies)
            {
                Apsim.Subscribe(parentModel, frequency, this.OnReportFrequency);
            }
        }
Пример #3
0
 /// <summary>Set the scripts parameters from the 'xmlElement' passed in.</summary>
 /// <param name="script">The script.</param>
 /// <param name="xmlElement">The XML element.</param>
 private void SetParametersInObject(Model script, XmlElement xmlElement)
 {
     foreach (XmlElement element in xmlElement.ChildNodes)
     {
         PropertyInfo property = Script.GetType().GetProperty(element.Name);
         if (property != null)
         {
             object value;
             if (element.InnerText.StartsWith(".Simulations."))
             {
                 value = Apsim.Get(this, element.InnerText);
             }
             else if (property.PropertyType == typeof(IPlant))
             {
                 value = Apsim.Find(this, element.InnerText);
             }
             else
             {
                 value = ReflectionUtilities.StringToObject(property.PropertyType, element.InnerText);
             }
             property.SetValue(script, value, null);
         }
     }
 }
Пример #4
0
        /// <summary>
        /// Calculate the uptake for each plant across the layers, zones, bounds, and forms
        /// </summary>
        /// <param name="resourceToArbitrate"></param>
        private void CalculateUptake(string resourceToArbitrate)
        {
            // calculate uptake distributed over layers etc - for now bounds and forms = 1
            zones = -1;
            int maxPlants = 0;
            int maxLayers = 0;

            foreach (Zone zone in Apsim.FindAll(Simulation, typeof(Zone)))  //foreach (Zone zone in Simulation.FindAll(typeof(Zone)))
            {
                zones += 1;

                // Find plants in paddock.
                List <ICrop2> plants = zone.Plants;
                maxPlants = Math.Max(plants.Count, maxPlants);

                // Find soil in paddock.
                Soil Soil = (Soil)Apsim.Find(zone, typeof(Soil));
                maxLayers = Math.Max(Soil.Thickness.Length, maxLayers);

                for (int p = 0; p < maxPlants; p++)
                {
                    for (int l = 0; l < maxLayers; l++)
                    {
                        for (int b = 0; b < bounds; b++)
                        {
                            for (int f = 0; f < forms; f++)
                            {
                                // ramp everything back if the resource < demand - note that resource is already only that which can potententially be extracted (i.e. not necessarily the total amount in the soil
                                uptake[p, l, z, b, f] = MathUtilities.Constrain(MathUtilities.Divide(totalForResource[0, l, z, b, f], demandForResource[0, l, z, b, f], 0.0), 0.0, 1.0)
                                                        * demand[p, l, z, b, f];
                            }
                        }
                    }
                }
            }
        }
Пример #5
0
        public void DrawGraph()
        {
            graphView.Clear();
            if (storage == null)
            {
                storage = Apsim.Find(graph, typeof(IDataStore)) as IDataStore;
            }

            // Get a list of series definitions.
            try
            {
                SeriesDefinitions = graph.GetDefinitionsToGraph(storage.Reader, SimulationFilter);
            }
            catch (SQLiteException e)
            {
                explorerPresenter.MainPresenter.ShowError(new Exception("Error obtaining data from database: ", e));
            }
            catch (FirebirdException e)
            {
                explorerPresenter.MainPresenter.ShowError(new Exception("Error obtaining data from database: ", e));
            }

            DrawGraph(SeriesDefinitions);
        }
Пример #6
0
        /// <summary>Called to start the job.</summary>
        /// <param name="cancelToken">The token to check if job has been cancelled</param>
        public void Run(CancellationTokenSource cancelToken)
        {
            if (simulationEngine != null)
            {
                fileName = simulationEngine.FileName;
                Console.Write("File: " + Path.GetFileNameWithoutExtension(fileName) + ", ");
            }
            Console.WriteLine("Simulation " + simulationToRun.Name + " has commenced.");

            // Start timer to record how long it takes to run
            timer = new Stopwatch();
            timer.Start();

            Events events = null;
            Links  links  = null;

            try
            {
                // Clone simulation
                if (cloneSimulationBeforeRun)
                {
                    simulationToRun = Apsim.Clone(simulationToRun) as Simulation;
                    simulationEngine.MakeSubsAndLoad(simulationToRun);
                }
                else
                {
                    events = new Events(simulationToRun);
                }

                // Remove disabled models from simulation
                foreach (IModel model in Apsim.ChildrenRecursively(simulationToRun))
                {
                    if (!model.Enabled)
                    {
                        model.Parent.Children.Remove(model as Model);
                    }
                }

                // Get an event and links service
                if (simulationEngine != null)
                {
                    links = simulationEngine.Links;
                }
                else
                {
                    links = new Core.Links(Services);
                }

                // Resolve links and events.
                links.Resolve(simulationToRun);
                events.ConnectEvents();

                simulationToRun.ClearCaches();

                // Send a commence event so the simulation runs
                object[] args         = new object[] { null, new EventArgs() };
                object[] commenceArgs = new object[] { null, new CommenceArgs()
                                                       {
                                                           CancelToken = cancelToken
                                                       } };
                events.Publish("Commencing", args);
                events.Publish("DoCommence", commenceArgs);
            }
            catch (Exception err)
            {
                string errorMessage = "ERROR in file: " + fileName + "\r\n" +
                                      "Simulation name: " + simulationToRun.Name + "\r\n";
                if (err.InnerException == null)
                {
                    errorMessage += err.Message;
                }
                else
                {
                    errorMessage += err.InnerException.Message;
                }

                ISummary summary = Apsim.Find(simulationToRun, typeof(Summary)) as ISummary;
                if (summary != null)
                {
                    summary.WriteMessage(simulationToRun, errorMessage);
                }

                throw new Exception(errorMessage, err);
            }
            finally
            {
                events.Publish("Completed", new object[] { null, new EventArgs() });

                // Cleanup the simulation
                if (events != null)
                {
                    events.DisconnectEvents();
                }
                links.Unresolve(simulationToRun);

                timer.Stop();
                Console.WriteLine("File: " + Path.GetFileNameWithoutExtension(fileName) +
                                  ", Simulation " + simulationToRun.Name + " complete. Time: " + timer.Elapsed.TotalSeconds.ToString("0.00 sec"));
                simulationEngine = null;
                simulationToRun  = null;
            }
        }
Пример #7
0
        /// <summary>
        /// Returns soil Nitrogen uptake from each zone by the static tree model
        /// </summary>
        /// <param name="soilstate"></param>
        /// <returns></returns>
        public List <Soils.Arbitrator.ZoneWaterAndN> GetNUptakes(Soils.Arbitrator.SoilState soilstate)
        {
            Zone treeZone = ZoneList[0] as Zone;

            List <ZoneWaterAndN> Uptakes = new List <ZoneWaterAndN>();
            double PotNO3Supply          = 0; // Total N supply (kg)

            double NDemandkg = GetNDemandToday() * 10 * treeZone.Area * 10000;

            foreach (ZoneWaterAndN Z in soilstate.Zones)
            {
                foreach (Zone ZI in ZoneList)
                {
                    if (Z.Zone.Name == ZI.Name)
                    {
                        ZoneWaterAndN Uptake = new ZoneWaterAndN(ZI);
                        //Find the soil for this zone
                        Soils.Soil ThisSoil = null;

                        foreach (Zone SearchZ in forestryZones)
                        {
                            if (SearchZ.Name == Z.Zone.Name)
                            {
                                ThisSoil = Apsim.Find(SearchZ, typeof(Soils.Soil)) as Soils.Soil;
                                break;
                            }
                        }

                        double[] SW = Z.Water;

                        Uptake.NO3N  = new double[SW.Length];
                        Uptake.NH4N  = new double[SW.Length];
                        Uptake.Water = new double[SW.Length];
                        double[] LL15mm = MathUtilities.Multiply(ThisSoil.LL15, ThisSoil.Thickness);
                        double[] BD     = ThisSoil.BD;
                        double[] RLD    = GetRLD(ZI);

                        for (int i = 0; i <= SW.Length - 1; i++)
                        {
                            Uptake.NO3N[i] = PotentialNO3Uptake(ThisSoil.Thickness[i], Z.NO3N[i], Z.Water[i], RLD[i], RootRadius, BD[i], Kd);
                            PotNO3Supply  += Uptake.NO3N[i] * ZI.Area * 10000;
                        }
                        Uptakes.Add(Uptake);
                        break;
                    }
                }
            }
            // Now scale back uptakes if supply > demand
            double F = 0;  // Uptake scaling factor

            if (PotNO3Supply > 0)
            {
                F = NDemandkg / PotNO3Supply;
                if (F > 1)
                {
                    F = 1;
                }
            }
            else
            {
                F = 1;
            }
            NStress = Math.Min(1, Math.Max(0, PotNO3Supply / NDemandkg));

            List <double> uptakeList = new List <double>();

            foreach (ZoneWaterAndN Z in Uptakes)
            {
                Z.NO3N = MathUtilities.Multiply_Value(Z.NO3N, F);
                uptakeList.Add(Z.TotalNO3N);
            }

            NUptake = uptakeList.ToArray();
            return(Uptakes);
        }
Пример #8
0
        /// <summary>
        /// Attach the model
        /// </summary>
        public void AttachData()
        {
            if (!(forestryModel.Parent is AgroforestrySystem))
            {
                throw new ApsimXException(forestryModel, "Error: TreeProxy must be a child of ForestrySystem.");
            }

            Soil          soil;
            List <IModel> zones = Apsim.ChildrenRecursively(forestryModel.Parent, typeof(Zone));

            if (zones.Count == 0)
            {
                return;
            }

            // Setup tree heights.
            forestryViewer.SetupHeights(forestryModel.Dates, forestryModel.Heights, forestryModel.NDemands, forestryModel.ShadeModifiers);

            // Get the first soil. For now we're assuming all soils have the same structure.
            soil = Apsim.Find(zones[0], typeof(Soil)) as Soil;

            forestryViewer.SoilMidpoints = soil.DepthMidPoints;

            // Setup columns.
            List <string> colNames = new List <string>();

            colNames.Add("Parameter");
            colNames.Add("0");
            colNames.Add("0.5h");
            colNames.Add("1h");
            colNames.Add("1.5h");
            colNames.Add("2h");
            colNames.Add("2.5h");
            colNames.Add("3h");
            colNames.Add("4h");
            colNames.Add("5h");
            colNames.Add("6h");

            if (forestryModel.Table.Count == 0)
            {
                forestryModel.Table = new List <List <string> >();
                forestryModel.Table.Add(colNames);

                // Setup rows.
                List <string> rowNames = new List <string>();

                rowNames.Add("Shade (%)");
                rowNames.Add("Root Length Density (cm/cm3)");
                rowNames.Add("Depth (cm)");

                foreach (string s in APSIM.Shared.APSoil.SoilUtilities.ToDepthStrings(soil.Thickness))
                {
                    rowNames.Add(s);
                }

                forestryModel.Table.Add(rowNames);
                for (int i = 2; i < colNames.Count + 1; i++)
                {
                    forestryModel.Table.Add(Enumerable.Range(1, rowNames.Count).Select(x => "0").ToList());
                }

                for (int i = 2; i < forestryModel.Table.Count; i++)
                {
                    // Set Depth and RLD rows to empty strings.
                    forestryModel.Table[i][1] = string.Empty;
                    forestryModel.Table[i][2] = string.Empty;
                }
            }
            else
            {
                // add Zones not in the table
                IEnumerable <string> except = colNames.Except(forestryModel.Table[0]);
                foreach (string s in except)
                {
                    forestryModel.Table.Add(Enumerable.Range(1, forestryModel.Table[1].Count).Select(x => "0").ToList());
                }

                forestryModel.Table[0].AddRange(except);
                for (int i = 2; i < forestryModel.Table.Count; i++)
                {
                    // Set Depth and RLD rows to empty strings.
                    forestryModel.Table[i][2] = string.Empty;
                }

                // Remove Zones from table that don't exist in simulation.
                except = forestryModel.Table[0].Except(colNames);
                List <int> indexes = new List <int>();
                foreach (string s in except.ToArray())
                {
                    indexes.Add(forestryModel.Table[0].FindIndex(x => s == x));
                }

                indexes.Sort();
                indexes.Reverse();

                foreach (int i in indexes)
                {
                    forestryModel.Table[0].RemoveAt(i);
                    forestryModel.Table.RemoveAt(i + 1);
                }
            }
            forestryViewer.SpatialData = forestryModel.Table;
        }
Пример #9
0
        public void TestEditing()
        {
            string configFile = Path.GetTempFileName();

            File.WriteAllLines(configFile, new[]
            {
                // Modify an array
                "[Report].VariableNames = x,y,z",

                // Modify a date - try a few different formats.
                "[Clock].StartDate = 2000-01-01",
                "[Clock].EndDate = 2000-01-10T00:00:00",

                // Modify a string
                "[Weather].FileName = fdsa.met",
                @"[Weather2].FullFileName = .\jkl.met",

                // Replace a model with a model from another file.
                $"[Weather3] = {extFile}",
                $"[Weather4] = {extFile};[w2]",

                // Change a property of a resource model.
                "[Wheat].Leaf.Photosynthesis.RUE.FixedValue = 0.4",

                // Change a property of a manager script.
                "[Manager].Script.Amount = 1234",

                // Set an entire array.
                "[Physical].BD = 1, 2, 3, 4, 5",

                // Modify a single element of an array.
                "[Physical].AirDry[2] = 6",

                // Modify multiple elements of an array.
                "[Physical].LL15[3:4] = 7",
            });

            string models = typeof(IModel).Assembly.Location;
            string args   = $"{fileName} /Edit {configFile}";

            var proc = new ProcessUtilities.ProcessWithRedirectedOutput();

            proc.Start(models, args, Path.GetTempPath(), true, writeToConsole: true);
            proc.WaitForExit();

            // Children of simulation are, in order:
            // Clock, summary, zone, Weather, Weather2, w1, w2
            Assert.AreEqual(null, proc.StdOut);
            Assert.AreEqual(null, proc.StdErr);

            Simulations file = FileFormat.ReadFromFile <Simulations>(fileName, out List <Exception> errors);

            if (errors != null && errors.Count > 0)
            {
                throw errors[0];
            }

            var report = Apsim.Find(file, typeof(Models.Report)) as Models.Report;

            string[] variableNames = new[] { "x", "y", "z" };
            Assert.AreEqual(variableNames, report.VariableNames);

            IModel sim = Apsim.Child(file, typeof(Simulation));

            // Use an index-based lookup to locate child models.
            // When we replace an entire model, we want to ensure
            // that the replacement is inserted at the correct index.

            Clock clock = sim.Children[0] as Clock;

            Assert.AreEqual(new DateTime(2000, 1, 1), clock.StartDate);
            Assert.AreEqual(new DateTime(2000, 1, 10), clock.EndDate);

            var weather = sim.Children[3] as Models.Weather;

            Assert.NotNull(weather);
            Assert.AreEqual("Weather", weather.Name);
            Assert.AreEqual("fdsa.met", weather.FileName);

            var weather2 = sim.Children[4] as Models.Weather;

            Assert.NotNull(weather2);
            Assert.AreEqual("Weather2", weather2.Name);
            Assert.AreEqual(@".\jkl.met", weather2.FileName);

            // Weather3 and Weather4 should have been
            // renamed to w1 and w2, respectively.
            var weather3 = sim.Children[5] as Models.Weather;

            Assert.NotNull(weather3);
            Assert.AreEqual("w1", weather3.Name);
            Assert.AreEqual("w1.met", weather3.FileName);

            var weather4 = sim.Children[6] as Models.Weather;

            Assert.NotNull(weather4);
            Assert.AreEqual("w2", weather4.Name);
            Assert.AreEqual("w2.met", weather4.FileName);

            // The edit file operation should have changed RUE value to 0.4.
            var wheat = sim.Children[2].Children[2] as Plant;
            var rue   = wheat.Children[6].Children[5].Children[0] as Constant;

            Assert.AreEqual(0.4, rue.FixedValue);

            double amount = (double)Apsim.Get(sim, "[Manager].Script.Amount");

            Assert.AreEqual(1234, amount);

            Physical physical = sim.Children[2].Children[4] as Physical;

            Assert.AreEqual(new double[5] {
                1, 2, 3, 4, 5
            }, physical.BD);
            Assert.AreEqual(new double[5] {
                0, 6, 0, 0, 0
            }, physical.AirDry);
            Assert.AreEqual(new double[5] {
                0, 0, 7, 7, 0
            }, physical.LL15);
        }
Пример #10
0
        /// <summary>
        /// A new method for finding a model/object from a path in the simulations tree.
        /// Finds the node (whose name is surrounded by square brackets). From there, it looks for each
        /// successive period-delimited child or property given in the path string.
        /// </summary>
        /// <param name="relativeTo">Object in the simulations tree.</param>
        /// <param name="objectName">Name of the object or model for which we want completion options.</param>
        /// <returns></returns>
        private static object GetNodeFromPath(Model relativeTo, string objectName)
        {
            string modelNamePattern = @"\[[A-Za-z\s]+[A-Za-z0-9\s_]*\]";
            object node             = null;
            var    matches          = System.Text.RegularExpressions.Regex.Matches(objectName, modelNamePattern);

            if (matches.Count <= 0)
            {
                // object name doesn't contain square brackets.
                string textBeforeFirstDot = objectName;
                if (objectName.Contains("."))
                {
                    textBeforeFirstDot = textBeforeFirstDot.Substring(0, textBeforeFirstDot.IndexOf('.'));
                }
                node = Apsim.Find(relativeTo, textBeforeFirstDot);
            }
            else
            {
                // Get the raw model name without square brackets.
                string modelName = matches[0].Value.Replace("[", "").Replace("]", "");

                // Get the node in the simulations tree corresponding to the model name which was surrounded by square brackets.
                node = Apsim.ChildrenRecursively(Apsim.Parent(relativeTo, typeof(Simulations))).FirstOrDefault(child => child.Name == modelName);
            }

            // If the object name string does not contain any children/properties
            // (e.g. it doesn't contain any periods), we can return immediately.
            if (!objectName.Contains("."))
            {
                return(node);
            }

            objectName = objectName.Substring(objectName.IndexOf('.') + 1);

            // Iterate over the 'child' models/properties.
            // childName is the next child we're looking for. e.g. in "[Wheat].Leaf", the first childName will be "Leaf".
            string[] namePathBits = StringUtilities.SplitStringHonouringBrackets(objectName, '.', '[', ']');
            for (int i = 0; i < namePathBits.Length; i++)
            {
                if (node == null)
                {
                    return(null);
                }
                string childName = namePathBits[i];

                int squareBracketIndex = childName.IndexOf('[');
                if (squareBracketIndex == 0)
                {
                    // User has typed something like [Wheat].[...]
                    throw new Exception("Unable to parse child or property " + childName);
                }
                if (squareBracketIndex > 0) // childName contains square brackets - it may be an IList element
                {
                    childName = childName.Substring(0, squareBracketIndex);
                }

                // First, check the child models.
                if (node is IModel)
                {
                    node = (node as IModel).Children.FirstOrDefault(c => c.Name == childName) ?? node;
                }

                // If we couldn't find a matching child model, we check the model/object's properties.

                // This expression evaluates to true if node is not an IModel.
                if ((node as IModel)?.Name != childName)
                {
                    // Node cannot be null here.
                    try
                    {
                        Type         propertyType = node is Type ? node as Type : node.GetType();
                        PropertyInfo property     = propertyType.GetProperties(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(p => p.Name == childName);

                        // If we couldn't find any matching child models or properties, all we can do is return.
                        if (property == null)
                        {
                            return(null);
                        }

                        // Try to set node to the value of the property.
                        node = ReflectionUtilities.GetValueOfFieldOrProperty(childName, node);
                        if (node == null)
                        {
                            // This property has the correct name. If the property's type provides a parameterless constructor, we can use
                            // reflection to instantiate an object of that type and assign it to the node variable.
                            // Otherwise, we assign the type itself to node.
                            if (property.PropertyType.GetConstructor(Type.EmptyTypes) == null)
                            {
                                node = property.PropertyType;
                            }
                            else
                            {
                                node = Activator.CreateInstance(property.PropertyType);
                            }
                        }
                    }
                    catch
                    {
                        // Any 'real' errors should be displayed to the user, so they should be caught
                        // in a presenter which can access the explorer presenter.
                        // Because of this, any unhandled exceptions here will kill the intellisense
                        // generation operation, and we still have a few tricks up our sleeve.
                        return(null);
                    }
                }

                if (squareBracketIndex > 0)
                {
                    // We have found the node, but the node is an IList of some sort, and we are actually interested in a specific element.

                    int closingBracketIndex = namePathBits[i].IndexOf(']');
                    if (closingBracketIndex <= 0 || (closingBracketIndex - squareBracketIndex) < 1)
                    {
                        return(null);
                    }

                    string textBetweenBrackets = namePathBits[i].Substring(squareBracketIndex + 1, closingBracketIndex - squareBracketIndex - 1);
                    if (node is IList)
                    {
                        int index = -1;
                        if (Int32.TryParse(textBetweenBrackets, out index))
                        {
                            IList nodeList = node as IList;
                            if (index > nodeList.Count || index <= 0)
                            {
                                node = node.GetType().GetInterfaces().Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable <>)).Select(x => x.GetGenericArguments()[0]).FirstOrDefault();
                            }
                            else
                            {
                                node = nodeList[index - 1];
                            }
                        }
                        else
                        {
                            throw new Exception("Unable to access element \"" + textBetweenBrackets + "\" of list \"" + namePathBits[i] + "\"");
                        }
                    }
                    else if (node is IDictionary)
                    {
                        node = (node as IDictionary)[textBetweenBrackets];
                    }
                    else
                    {
                        throw new Exception("Unable to parse child or property name " + namePathBits[i]);
                    }
                }
                squareBracketIndex = -1;
            }
            return(node);
        }
Пример #11
0
 private void OnSimulationCommencing(object sender, EventArgs e)
 {
     NO3Solute = Apsim.Find(this, "NO3") as ISolute;
     NH4Solute = Apsim.Find(this, "NH4") as ISolute;
     Reset();
 }
Пример #12
0
        /// <summary>
        /// Calculate the amount that the plant could potentially exctract if it was the only plant in the simulation and demand > resource
        /// </summary>
        /// <param name="resourceToArbitrate"></param>
        private void CalculateExtractable(string resourceToArbitrate)
        {
            // calculate extractable
            zones = -1;
            int maxPlants = 0;
            int maxLayers = 0;

            foreach (Zone zone in Apsim.FindAll(Simulation, typeof(Zone)))  //foreach (Zone zone in Simulation.FindAll(typeof(Zone)))
            {
                zones += 1;

                // Find plants in paddock.
                List <ICrop2> plants = zone.Plants;
                maxPlants = Math.Max(plants.Count, maxPlants);

                // Find soil in paddock.
                Soil Soil = (Soil)Apsim.Find(zone, typeof(Soil));
                maxLayers = Math.Max(Soil.Thickness.Length, maxLayers);

                for (int p = 0; p < maxPlants; p++)
                {
                    for (int l = 0; l < Soil.Thickness.Length; l++)
                    {
                        for (int b = 0; b < bounds; b++)
                        {
                            for (int f = 0; f < forms; f++)
                            {
                                if (resourceToArbitrate.ToLower() == "water")
                                {
                                    extractable[p, l, z, b, f] = plants[p].RootProperties.UptakePreferenceByLayer[l]   // later add in zone
                                                                 * plants[p].RootProperties.RootExplorationByLayer[l]  // later add in zone
                                                                 * plants[p].RootProperties.KL[l]                      // later add in zone
                                                                 * resource[p, l, z, b, f];                            // the usage of 0 instead of p is intended - there is no actual p dimension in resource
                                    extractableByPlant[p] += extractable[p, l, z, b, f];
                                }
                                else if (resourceToArbitrate.ToLower() == "nitrogen")
                                {
                                    double relativeSoilWaterContent = MathUtilities.Constrain(MathUtilities.Divide((Soil.Water[l] - Soil.SoilWater.LL15mm[l]), (Soil.SoilWater.DULmm[l] - Soil.SoilWater.LL15mm[l]), 0.0), 0.0, 1.0);
                                    if (f == 0)
                                    {
                                        extractable[p, l, z, b, f] = relativeSoilWaterContent
                                                                     * plants[p].RootProperties.UptakePreferenceByLayer[l] // later add in zone
                                                                     * plants[p].RootProperties.RootExplorationByLayer[l]  // later add in zone
                                                                     * plants[p].RootProperties.KNO3                       // later add in zone
                                                                     * Soil.SoilNitrogen.NO3ppm[l]
                                                                     * resource[p, l, z, b, f];
                                    }
                                    else
                                    {
                                        extractable[p, l, z, b, f] = relativeSoilWaterContent
                                                                     * plants[p].RootProperties.UptakePreferenceByLayer[l] // later add in zone
                                                                     * plants[p].RootProperties.RootExplorationByLayer[l]  // later add in zone
                                                                     * plants[p].RootProperties.KNH4                       // later add in zone
                                                                     * Soil.SoilNitrogen.NH4ppm[l]
                                                                     * resource[p, l, z, b, f];
                                    }
                                    extractableByPlant[p] += extractable[p, l, z, b, f];
                                }
                            }
                        }
                    }
                }
            }
        }
Пример #13
0
        /// <summary>
        /// Calculate the number of lower bounds that exist in each layer-zone combination and assign value to those bounds
        /// This does not need to be done each day unless LL becomes dynamic
        /// Leave here for now but could be moved either to OnSimulationCommencing or test for bounds and only do when null
        /// </summary>
        /// <param name="resourceToArbitrate"></param>
        private void CalculateLowerBounds(string resourceToArbitrate)
        {
            // set up the bounds here
            // the tolerance is used to trmpoarily convert the double array of lower limits into an integer array.  This then allows the usage of Distinct to remove duplicates.
            // At present set tolerance to a low value - this will end up with more bounds but will be more accurate with the available water to plants
            double tolerance = 0.001;

            if (resourceToArbitrate.ToLower() == "water")
            {
                zones = -1;
                int maxPlants = 0;
                int maxLayers = 0;
                foreach (Zone zone in Apsim.FindAll(Simulation, typeof(Zone)))  //foreach (Zone zone in Simulation.FindAll(typeof(Zone)))
                {
                    zones += 1;

                    // Find plants in paddock.
                    List <ICrop2> plants = zone.Plants;
                    maxPlants = Math.Max(plants.Count, maxPlants);

                    // Find soil in paddock.
                    Soil Soil = (Soil)Apsim.Find(zone, typeof(Soil));
                    maxLayers = Math.Max(Soil.Thickness.Length, maxLayers);

                    int[] tempBoundsArray = new int[plants.Count];

                    for (int l = 0; l < maxLayers; l++)
                    {
                        // get the lower bounds from the plants and put them into a temporary array for sorting, comparison and shortening before assigning bounds
                        // for the unique values, divide each element by the tolerance (which is mm diference that is interesting) and convert to an integer
                        // then sort, reverse and then use the Distinct method to shorten the array into functionally different values
                        // lastly multiply by the tolerance again to get the bounds in mm
                        // this is redundant but non-troublesome for a single-plant simulation
                        for (int p = 0; p < maxPlants; p++)
                        {
                            tempBoundsArray[p] = Convert.ToInt32(Math.Round(plants[p].RootProperties.LowerLimitDep[l] / tolerance, 0));
                        }

                        var tempShortenedBoundsArray = tempBoundsArray.Distinct().ToArray();
                        // sort the shortened array and then put it into descending order - wettest first
                        Array.Sort(tempShortenedBoundsArray);
                        Array.Reverse(tempShortenedBoundsArray);
                        bounds = tempShortenedBoundsArray.Length;
                        for (int b = 0; b < bounds; b++)
                        {
                            lowerBound[0, l, z, b] = tempShortenedBoundsArray[b] * tolerance;
                        }
                    }
                }
            }
            else if (resourceToArbitrate.ToLower() == "nitrogen")
            {
                zones = -1;
                int maxPlants = 0;
                int maxLayers = 0;
                foreach (Zone zone in Apsim.FindAll(Simulation, typeof(Zone)))  //foreach (Zone zone in Simulation.FindAll(typeof(Zone)))
                {
                    zones += 1;

                    // Find plants in paddock.
                    List <ICrop2> plants = zone.Plants;
                    maxPlants = Math.Max(plants.Count, maxPlants);

                    // Find soil in paddock.
                    Soil Soil = (Soil)Apsim.Find(zone, typeof(Soil));
                    maxLayers = Math.Max(Soil.Thickness.Length, maxLayers);

                    for (int l = 0; l < Soil.Thickness.Length; l++)
                    {
                        bounds = 1;  // assume they are all have the same lower bound
                        lowerBound[0, l, z, 0] = 0.0;
                    }
                }
            }
        }
        /// <summary>
        /// Format the grid. (Just one column)
        /// </summary>
        private void FormatGrid(int propListIndex)
        {
            for (int i = 0; i < this.properties[propListIndex].Count; i++)
            {
                IGridCell cell = this.grid.GetCell(propListIndex + 1, i); //add one because of the Description column

                if (this.properties[propListIndex][i].Display != null && this.properties[propListIndex][i].Display.Type == DisplayType.TableName)
                {
                    cell.EditorType      = EditorTypeEnum.DropDown;
                    cell.DropDownStrings = this.storage.Reader.TableNames.ToArray();
                }
                else if (this.properties[propListIndex][i].Display != null && this.properties[propListIndex][i].Display.Type == DisplayType.CultivarName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    IPlant crop = this.GetCrop(this.properties[propListIndex]);
                    if (crop != null)
                    {
                        cell.DropDownStrings = this.GetCultivarNames(crop);
                    }
                }
                else if (this.properties[propListIndex][i].Display != null && this.properties[propListIndex][i].Display.Type == DisplayType.LifeCycleName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    Zone zone = Apsim.Find(model, typeof(Zone)) as Zone;
                    if (zone != null)
                    {
                        cell.DropDownStrings = this.GetLifeCycleNames(zone);
                    }
                }
                else if (this.properties[propListIndex][i].Display != null && this.properties[propListIndex][i].Display.Type == DisplayType.LifePhaseName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    LifeCycle lifeCycle = this.GetLifeCycle(this.properties[propListIndex]);
                    if (lifeCycle != null)
                    {
                        cell.DropDownStrings = this.GetPhaseNames(lifeCycle);
                    }
                }
                else if (this.properties[propListIndex][i].Display != null && this.properties[propListIndex][i].Display.Type == DisplayType.FileName)
                {
                    cell.EditorType = EditorTypeEnum.Button;
                }
                else if (this.properties[propListIndex][i].Display != null && this.properties[propListIndex][i].Display.Type == DisplayType.FieldName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    string[] fieldNames = this.GetFieldNames(propListIndex);
                    if (fieldNames != null)
                    {
                        cell.DropDownStrings = fieldNames;
                    }
                }
                else if (this.properties[propListIndex][i].Display != null && this.properties[propListIndex][i].Display.Type == DisplayType.ResidueName &&
                         this.model is SurfaceOrganicMatter)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    string[] fieldNames = this.GetResidueNames();
                    if (fieldNames != null)
                    {
                        cell.DropDownStrings = fieldNames;
                    }
                }
                else if (this.properties[propListIndex][i].Display != null && this.properties[propListIndex][i].Display.Type == DisplayType.CLEMResourceName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;

                    List <string> fieldNames = new List <string>();
                    fieldNames.AddRange(this.GetCLEMResourceNames(this.properties[propListIndex][i].Display.CLEMResourceNameResourceGroups));

                    // add any extras elements provided to the list.
                    if (this.properties[propListIndex][i].Display.CLEMExtraEntries != null)
                    {
                        fieldNames.AddRange(this.properties[propListIndex][i].Display.CLEMExtraEntries);
                    }

                    if (fieldNames.Count != 0)
                    {
                        cell.DropDownStrings = fieldNames.ToArray();
                    }
                }
                else
                {
                    object cellValue = this.properties[propListIndex][i].ValueWithArrayHandling;
                    if (cellValue is DateTime)
                    {
                        cell.EditorType = EditorTypeEnum.DateTime;
                    }
                    else if (cellValue is bool)
                    {
                        cell.EditorType = EditorTypeEnum.Boolean;
                    }
                    else if (cellValue.GetType().IsEnum)
                    {
                        cell.EditorType      = EditorTypeEnum.DropDown;
                        cell.DropDownStrings = StringUtilities.EnumToStrings(cellValue);
                    }
                    else if (cellValue.GetType() == typeof(IPlant))
                    {
                        cell.EditorType = EditorTypeEnum.DropDown;
                        List <string> cropNames = new List <string>();
                        foreach (Model crop in Apsim.FindAll(this.model, typeof(IPlant)))
                        {
                            cropNames.Add(crop.Name);
                        }

                        cell.DropDownStrings = cropNames.ToArray();
                    }
                    else if (this.properties[propListIndex][i].DataType == typeof(IPlant))
                    {
                        List <string> plantNames = Apsim.FindAll(this.model, typeof(IPlant)).Select(m => m.Name).ToList();
                        cell.EditorType      = EditorTypeEnum.DropDown;
                        cell.DropDownStrings = plantNames.ToArray();
                    }
                    else
                    {
                        cell.EditorType = EditorTypeEnum.TextBox;
                    }
                }
            }

            IGridColumn descriptionColumn = this.grid.GetColumn(0);

            descriptionColumn.Width    = -1;
            descriptionColumn.ReadOnly = true;

            IGridColumn valueColumn = this.grid.GetColumn(1);

            valueColumn.Width = -1;
        }
Пример #15
0
        /// <summary>
        /// Export to PDF
        /// </summary>
        public void DoExportPDF(string modelNameToExport)
        {
            // Create a temporary working directory.
            string workingDirectory = Path.Combine(Path.GetTempPath(), "autodoc");

            if (Directory.Exists(workingDirectory))
            {
                Directory.Delete(workingDirectory, true);
            }
            Directory.CreateDirectory(workingDirectory);

            Document document = new Document();

            CreatePDFSyles(document);
            Section section = document.AddSection();

            // write image files
            string png1 = Path.Combine(workingDirectory, "apsim_logo.png");

            using (FileStream file = new FileStream(png1, FileMode.Create, FileAccess.Write))
            {
                Assembly.GetExecutingAssembly().GetManifestResourceStream("UserInterface.Resources.apsim_logo.png").CopyTo(file);
            }

            string png2 = Path.Combine(workingDirectory, "hd_bg.png");

            using (FileStream file = new FileStream(png2, FileMode.Create, FileAccess.Write))
            {
                Assembly.GetExecutingAssembly().GetManifestResourceStream("UserInterface.Resources.hd_bg.png").CopyTo(file);
            }
            section.AddImage(png1);

            List <AutoDocumentation.ITag> tags = new List <AutoDocumentation.ITag>();

            // See if there is a title page. If so do it first.
            IModel titlePage = Apsim.Find(ExplorerPresenter.ApsimXFile, "TitlePage");

            if (titlePage != null)
            {
                titlePage.Document(tags, 1, 0);
            }

            // Document model description.
            tags.Add(new AutoDocumentation.Heading("Model description", 1));
            ExplorerPresenter.ApsimXFile.DocumentModel(modelNameToExport, tags, 2);

            // Document model validation.
            tags.Add(new AutoDocumentation.Heading("Validation", 1));
            AddValidationTags(tags, ExplorerPresenter.ApsimXFile, 1, workingDirectory);

            // Scan for citations.
            ScanForCitations(tags);

            // Create a bibliography.
            CreateBibliography(tags);

            // numebr all headings.
            NumberHeadings(tags);

            // Populate the PDF section.
            TagsToMigraDoc(section, tags, workingDirectory);

            // Write the PDF file.
            FileNameWritten = Path.Combine(Path.GetDirectoryName(ExplorerPresenter.ApsimXFile.FileName), modelNameToExport + ".pdf");
            PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(false, PdfSharp.Pdf.PdfFontEmbedding.Always);

            pdfRenderer.Document = document;
            pdfRenderer.RenderDocument();
            pdfRenderer.PdfDocument.Save(FileNameWritten);

            // Remove temporary working directory.
            Directory.Delete(workingDirectory, true);
        }
Пример #16
0
        public void AttachData()
        {
            if (!(ForestryModel.Parent is AgroforestrySystem))
            {
                throw new ApsimXException(ForestryModel, "Error: TreeProxy must be a child of ForestrySystem.");
            }

            Soil          Soil;
            List <IModel> Zones = Apsim.ChildrenRecursively(ForestryModel.Parent, typeof(Zone));

            if (Zones.Count == 0)
            {
                return;
            }

            // setup tree heights
            ForestryViewer.SetupHeights(ForestryModel.dates, ForestryModel.heights, ForestryModel.NDemands, ForestryModel.CanopyWidths, ForestryModel.TreeLeafAreas);

            /*      //get the distance of each Zone from Tree.
             *    double zoneWidth = 0;
             *    double[] ZoneWidths = new double[Zones.Count];
             *
             *    for (int i = 1; i < Zones.Count; i++) //skip first Zone with tree
             *    {
             *        if (Zones[i] is RectangularZone)
             *            zoneWidth = (Zones[i] as RectangularZone).Width;
             *        else if (Zones[i] is CircularZone)
             *            zoneWidth = (Zones[i] as CircularZone).Width;
             *
             *            ZoneWidths[i] = ZoneWidths[i - 1] + zoneWidth;
             *    }*/

            // get the first soil. For now we're assuming all soils have the same structure.
            Soil = Apsim.Find(Zones[0], typeof(Soil)) as Soil;

            ForestryViewer.SoilMidpoints = Soil.DepthMidPoints;
            // setup columns
            List <string> colNames = new List <string>();

            colNames.Add("Parameter");
            colNames.Add("0");
            colNames.Add("0.5h");
            colNames.Add("1h");
            colNames.Add("1.5h");
            colNames.Add("2h");
            colNames.Add("2.5h");
            colNames.Add("3h");
            colNames.Add("4h");
            colNames.Add("5h");
            colNames.Add("6h");

            if (ForestryModel.Table.Count == 0)
            {
                ForestryModel.Table = new List <List <String> >();
                ForestryModel.Table.Add(colNames);

                // setup rows
                List <string> rowNames = new List <string>();

                rowNames.Add("Shade (%)");
                rowNames.Add("Root Length Density (cm/cm3)");
                rowNames.Add("Depth (cm)");

                foreach (string s in Soil.Depth)
                {
                    rowNames.Add(s);
                }

                ForestryModel.Table.Add(rowNames);
                for (int i = 2; i < colNames.Count + 1; i++)
                {
                    ForestryModel.Table.Add(Enumerable.Range(1, rowNames.Count).Select(x => "0").ToList());
                }

                for (int i = 2; i < ForestryModel.Table.Count; i++) // set Depth and RLD rows to empty strings
                {
                    ForestryModel.Table[i][1] = string.Empty;
                    ForestryModel.Table[i][2] = string.Empty;
                }
            }
            else
            {
                // add Zones not in the table
                IEnumerable <string> except = colNames.Except(ForestryModel.Table[0]);
                foreach (string s in except)
                {
                    ForestryModel.Table.Add(Enumerable.Range(1, ForestryModel.Table[1].Count).Select(x => "0").ToList());
                }
                ForestryModel.Table[0].AddRange(except);
                for (int i = 2; i < ForestryModel.Table.Count; i++) // set Depth and RLD rows to empty strings
                {
                    ForestryModel.Table[i][2] = string.Empty;
                    // ForestryModel.Table[i][3] = string.Empty;
                }

                // remove Zones from table that don't exist in simulation
                except = ForestryModel.Table[0].Except(colNames);
                List <int> indexes = new List <int>();
                foreach (string s in except.ToArray())
                {
                    indexes.Add(ForestryModel.Table[0].FindIndex(x => s == x));
                }

                indexes.Sort();
                indexes.Reverse();

                foreach (int i in indexes)
                {
                    ForestryModel.Table[0].RemoveAt(i);
                    ForestryModel.Table.RemoveAt(i + 1);
                }
            }
            ForestryViewer.SetupGrid(ForestryModel.Table);
        }
Пример #17
0
        /// <summary>
        /// Calculate the potential N uptake for today. Should return null if crop is not in the ground (this is not true for old sorghum).
        /// </summary>
        public override List <Soils.Arbitrator.ZoneWaterAndN> GetNitrogenUptakeEstimates(SoilState soilstate)
        {
            if (Plant.IsEmerged)
            {
                var nSupply = 0.0;//NOTE: This is in kg, not kg/ha, to arbitrate N demands for spatial simulations.

                //this function is called 4 times as part of estimates
                //shouldn't set public variables in here

                var grainIndex = 0;
                var rootIndex  = 1;
                var leafIndex  = 2;
                var stemIndex  = 4;

                var rootDemand  = N.StructuralDemand[rootIndex] + N.MetabolicDemand[rootIndex];
                var stemDemand  = /*N.StructuralDemand[stemIndex] + */ N.MetabolicDemand[stemIndex];
                var leafDemand  = N.MetabolicDemand[leafIndex];
                var grainDemand = N.StructuralDemand[grainIndex] + N.MetabolicDemand[grainIndex];
                //have to correct the leaf demand calculation
                var leaf           = Organs[leafIndex] as SorghumLeaf;
                var leafAdjustment = leaf.calculateClassicDemandDelta();

                //double NDemand = (N.TotalPlantDemand - N.TotalReallocation) / kgha2gsm * Plant.Zone.Area; //NOTE: This is in kg, not kg/ha, to arbitrate N demands for spatial simulations.
                //old sorghum uses g/m^2 - need to convert after it is used to calculate actual diffusion
                // leaf adjustment is not needed here because it is an adjustment for structural demand - we only look at metabolic here.

                // dh - In old sorghum, root only has one type of NDemand - it doesn't have a structural/metabolic division.
                // In new apsim, root only uses structural, metabolic is always 0. Therefore, we have to include root's structural
                // NDemand in this calculation.

                // dh - In old sorghum, totalDemand is metabolic demand for all organs. However in new apsim, grain has no metabolic
                // demand, so we must include its structural demand in this calculation.
                double totalDemand         = N.TotalMetabolicDemand + N.StructuralDemand[rootIndex] + N.StructuralDemand[grainIndex];
                double nDemand             = Math.Max(0, totalDemand - grainDemand); // to replicate calcNDemand in old sorghum
                List <ZoneWaterAndN> zones = new List <ZoneWaterAndN>();

                foreach (ZoneWaterAndN zone in soilstate.Zones)
                {
                    ZoneWaterAndN UptakeDemands = new ZoneWaterAndN(zone.Zone);

                    UptakeDemands.NO3N = new double[zone.NO3N.Length];
                    UptakeDemands.NH4N = new double[zone.NH4N.Length];
                    UptakeDemands.PlantAvailableNO3N = new double[zone.NO3N.Length];
                    UptakeDemands.PlantAvailableNH4N = new double[zone.NO3N.Length];
                    UptakeDemands.Water = new double[UptakeDemands.NO3N.Length];

                    //only using Root to get Nitrogen from - temporary code for sorghum
                    var root = Organs[rootIndex] as Root;

                    //Get Nuptake supply from each organ and set the PotentialUptake parameters that are passed to the soil arbitrator

                    //at present these 2arrays arenot being used within the CalculateNitrogenSupply function
                    //sorghum uses Diffusion & Massflow variables currently
                    double[] organNO3Supply = new double[zone.NO3N.Length]; //kg/ha - dltNo3 in old apsim
                    double[] organNH4Supply = new double[zone.NH4N.Length];

                    ZoneState myZone = root.Zones.Find(z => z.Name == zone.Zone.Name);
                    if (myZone != null)
                    {
                        CalculateNitrogenSupply(myZone, zone);

                        //new code
                        double[] diffnAvailable = new double[myZone.Diffusion.Length];
                        for (var i = 0; i < myZone.Diffusion.Length; ++i)
                        {
                            diffnAvailable[i] = myZone.Diffusion[i] - myZone.MassFlow[i];
                        }
                        var totalMassFlow  = MathUtilities.Sum(myZone.MassFlow); //g/m^2
                        var totalDiffusion = MathUtilities.Sum(diffnAvailable);  //g/m^2

                        var potentialSupply   = totalMassFlow + totalDiffusion;
                        var actualDiffusion   = 0.0;
                        var actualMassFlow    = DltTT > 0 ? totalMassFlow : 0.0;
                        var maxDiffusionConst = root.MaxDiffusion.Value();

                        double NUptakeCease = (Apsim.Find(this, "NUptakeCease") as Functions.IFunction).Value();
                        if (TTFMFromFlowering > NUptakeCease)
                        {
                            totalMassFlow = 0;
                        }
                        actualMassFlow = totalMassFlow;

                        if (totalMassFlow < nDemand && TTFMFromFlowering < NUptakeCease) // fixme && ttElapsed < nUptakeCease
                        {
                            actualDiffusion = MathUtilities.Bound(nDemand - totalMassFlow, 0.0, totalDiffusion);
                            actualDiffusion = MathUtilities.Divide(actualDiffusion, maxDiffusionConst, 0.0);

                            var nsupplyFraction = root.NSupplyFraction.Value();
                            var maxRate         = root.MaxNUptakeRate.Value();

                            var maxUptakeRateFrac = Math.Min(1.0, (potentialSupply / root.NSupplyFraction.Value())) * root.MaxNUptakeRate.Value();
                            var maxUptake         = Math.Max(0, maxUptakeRateFrac * DltTT - actualMassFlow);
                            actualDiffusion = Math.Min(actualDiffusion, maxUptake);
                        }

                        NDiffusionSupply = actualDiffusion;
                        NMassFlowSupply  = actualMassFlow;

                        //adjust diffusion values proportionally
                        //make sure organNO3Supply is in kg/ha
                        for (int layer = 0; layer < organNO3Supply.Length; layer++)
                        {
                            var massFlowLayerFraction  = MathUtilities.Divide(myZone.MassFlow[layer], totalMassFlow, 0.0);
                            var diffusionLayerFraction = MathUtilities.Divide(diffnAvailable[layer], totalDiffusion, 0.0);
                            //organNH4Supply[layer] = massFlowLayerFraction * root.MassFlow[layer];
                            organNO3Supply[layer] = (massFlowLayerFraction * actualMassFlow +
                                                     diffusionLayerFraction * actualDiffusion) / kgha2gsm; //convert to kg/ha
                        }
                    }
                    //originalcode
                    UptakeDemands.NO3N = MathUtilities.Add(UptakeDemands.NO3N, organNO3Supply); //Add uptake supply from each organ to the plants total to tell the Soil arbitrator
                    if (UptakeDemands.NO3N.Any(n => MathUtilities.IsNegative(n)))
                    {
                        throw new Exception("-ve no3 uptake demand");
                    }
                    UptakeDemands.NH4N = MathUtilities.Add(UptakeDemands.NH4N, organNH4Supply);

                    N.UptakeSupply[rootIndex] += MathUtilities.Sum(organNO3Supply) * kgha2gsm * zone.Zone.Area / Plant.Zone.Area;  //g/m2
                    if (MathUtilities.IsNegative(N.UptakeSupply[rootIndex]))
                    {
                        throw new Exception($"-ve uptake supply for organ {(Organs[rootIndex] as IModel).Name}");
                    }
                    nSupply += MathUtilities.Sum(organNO3Supply) * zone.Zone.Area;
                    zones.Add(UptakeDemands);
                }

                return(zones);
            }
            return(null);
        }
Пример #18
0
        /// <summary>
        /// Send the nitrogen uptake arrays back to the plants and send the change in nitrogen back to the soil
        /// </summary>
        /// <param name="resourceToArbitrate"></param>
        private void SetNitrogenUptake(string resourceToArbitrate)
        {
            zones = -1;
            int maxPlants = 0;
            int maxLayers = 0;

            foreach (Zone zone in Apsim.FindAll(Simulation, typeof(Zone)))  //foreach (Zone zone in Simulation.FindAll(typeof(Zone)))
            {
                zones += 1;

                // Find plants in paddock.
                List <ICrop2> plants = zone.Plants;
                maxPlants = Math.Max(plants.Count, maxPlants);

                // Find soil in paddock.
                Soil Soil = (Soil)Apsim.Find(zone, typeof(Soil));
                maxLayers = Math.Max(Soil.Thickness.Length, maxLayers);

                double[] dummyArray1 = new double[Soil.Thickness.Length];  // have to create a new array for each plant to avoid the .NET pointer thing - will have to re-think this with when zones come in
                double[] dummyArray2 = new double[Soil.Thickness.Length];  // have to create a new array for each plant to avoid the .NET pointer thing - will have to re-think this with when zones come in

                // move this inside the zone loop - needs to get zeroed for each seperate zone
                NitrogenChangedType NUptakeType = new NitrogenChangedType();
                NUptakeType.Sender     = Name;
                NUptakeType.SenderType = "Plant";
                NUptakeType.DeltaNO3   = new double[Soil.Thickness.Length];
                NUptakeType.DeltaNH4   = new double[Soil.Thickness.Length];

                for (int p = 0; p < maxPlants; p++)
                {
                    for (int l = 0; l < maxLayers; l++)
                    {
                        for (int b = 0; b < bounds; b++)
                        {
                            for (int f = 0; f < forms; f++)
                            {
                                dummyArray1[l] += uptake[p, l, z, b, f];       // add the forms together to give the total nitrogen uptake
                                if (f == 0)
                                {
                                    NUptakeType.DeltaNO3[l] += -1.0 * uptake[p, l, z, b, f];
                                    dummyArray2[l]          += uptake[p, l, z, b, f]; // nitrate only uptake so can do the proportion before sending to the plant
                                }
                                else
                                {
                                    NUptakeType.DeltaNH4[l] += -1.0 * uptake[p, l, z, b, f];
                                }
                            }
                        }
                    }
                    // set uptakes in each plant
                    plants[p].uptakeNitrogen = dummyArray1;
                    for (int l = 0; l < Soil.Thickness.Length; l++)                                 // don't forget to deal with zones at some point
                    {
                        dummyArray2[l] = MathUtilities.Divide(dummyArray2[l], dummyArray1[l], 0.0); // would be nice to have a utility for this
                    }
                    plants[p].uptakeNitrogenPropNO3 = dummyArray2;
                }
                // and finally set the changed soil resources
                if (NitrogenChanged != null)
                {
                    NitrogenChanged.Invoke(NUptakeType);
                }
            }
        }
Пример #19
0
        /// <summary>Draw the graph on the screen.</summary>
        public void DrawGraph()
        {
            graphView.Clear();
            if (storage == null)
            {
                storage = Apsim.Find(graph, typeof(IDataStore)) as IDataStore;
            }
            if (graph != null && graph.Series != null)
            {
                // Get a list of series definitions.
                try
                {
                    seriesDefinitions = graph.GetDefinitionsToGraph(storage.Reader);
                }
                catch (SQLiteException e)
                {
                    explorerPresenter.MainPresenter.ShowError(new Exception("Error obtaining data from database: ", e));
                }

                foreach (SeriesDefinition definition in seriesDefinitions)
                {
                    DrawOnView(definition);
                }

                // Update axis maxima and minima
                graphView.UpdateView();

                // Get a list of series annotations.
                DrawOnView(graph.GetAnnotationsToGraph());

                // Format the axes.
                foreach (Models.Graph.Axis a in graph.Axis)
                {
                    FormatAxis(a);
                }

                // Format the legend.
                graphView.FormatLegend(graph.LegendPosition);

                // Format the title
                graphView.FormatTitle(graph.Name);

                // Format the footer
                if (string.IsNullOrEmpty(graph.Caption))
                {
                    graphView.FormatCaption("Double click to add a caption", true);
                }
                else
                {
                    graphView.FormatCaption(graph.Caption, false);
                }

                // Remove series titles out of the graph disabled series list when
                // they are no longer valid i.e. not on the graph.
                if (graph.DisabledSeries == null)
                {
                    graph.DisabledSeries = new List <string>();
                }
                IEnumerable <string> validSeriesTitles  = this.seriesDefinitions.Select(s => s.title);
                List <string>        seriesTitlesToKeep = new List <string>(validSeriesTitles.Intersect(this.graph.DisabledSeries));
                this.graph.DisabledSeries.Clear();
                this.graph.DisabledSeries.AddRange(seriesTitlesToKeep);

                graphView.Refresh();
            }
        }
Пример #20
0
        /// <summary>Constructor, initialise tissues for the roots.</summary>
        /// <param name="nameOfSpecies">Name of the pasture species</param>
        /// <param name="numTissues">Number of tissues in this organ</param>
        /// <param name="initialDM">Initial dry matter weight</param>
        /// <param name="initialDepth">Initial root depth</param>
        /// <param name="optNconc">The optimum N concentration</param>
        /// <param name="minNconc">The minimum N concentration</param>
        /// <param name="maxNconc">The maximum N concentration</param>
        /// <param name="minLiveDM">The minimum biomass for this organ</param>
        /// <param name="specificRootLength">The specific root length (m/g)</param>
        /// <param name="rootDepthMaximum">The maximum root depth</param>
        /// <param name="rootDistributionDepthParam">Parameter to compute root distribution, depth with constant root</param>
        /// <param name="rootBottomDistributionFactor">Parameter to compute root distribution, </param>
        /// <param name="rootDistributionExponent">Parameter to compute root distribution, exponent for root decrease</param>
        /// <param name="waterAvailableMethod">Method to compute water available</param>
        /// <param name="nitrogenAvailableMethod">Method to compute N available</param>
        /// <param name="kNH4">Parameter to compute NN4 available, default method</param>
        /// <param name="kNO3">Parameter to compute NO3 available, default method</param>
        /// <param name="maxNUptake">Parameter to compute N uptake, default method</param>
        /// <param name="kuNH4">Parameter to compute NH4 available, alternative method</param>
        /// <param name="kuNO3">Parameter to compute NO3 available, alternative method</param>
        /// <param name="referenceKSuptake">Parameter to compute available water, conductivity</param>
        /// <param name="referenceRLD">Parameter to compute available water, roots</param>
        /// <param name="exponentSoilMoisture">Parameter to compute available water</param>
        /// <param name="theSoil">Reference to the soil in the zone these roots are in</param>
        public PastureBelowGroundOrgan(string nameOfSpecies, int numTissues,
                                       double initialDM, double initialDepth,
                                       double optNconc, double minNconc, double maxNconc,
                                       double minLiveDM,
                                       double specificRootLength, double rootDepthMaximum,
                                       double rootDistributionDepthParam, double rootDistributionExponent,
                                       double rootBottomDistributionFactor,
                                       PastureSpecies.PlantAvailableWaterMethod waterAvailableMethod,
                                       PastureSpecies.PlantAvailableNitrogenMethod nitrogenAvailableMethod,
                                       double kNH4, double kNO3, double maxNUptake,
                                       double kuNH4, double kuNO3, double referenceKSuptake,
                                       double referenceRLD, double exponentSoilMoisture,
                                       Soil theSoil)
        {
            mySoil       = theSoil;
            SoilNitrogen = Apsim.Find(mySoil, typeof(INutrient)) as INutrient;
            if (SoilNitrogen == null)
            {
                throw new Exception("Cannot find SoilNitrogen in zone");
            }

            // Typically two tissues below ground, one live and one dead
            Tissue  = new RootTissue[numTissues];
            nLayers = theSoil.Thickness.Length;
            for (int t = 0; t < Tissue.Length; t++)
            {
                Tissue[t] = new RootTissue(nameOfSpecies, SoilNitrogen, nLayers);
            }

            // save the parameters for this organ
            mySpeciesName                  = nameOfSpecies;
            NConcOptimum                   = optNconc;
            NConcMinimum                   = minNconc;
            NConcMaximum                   = maxNconc;
            MinimumLiveDM                  = minLiveDM;
            mySpecificRootLength           = specificRootLength;
            myRootDepthMaximum             = rootDepthMaximum;
            myRootDistributionDepthParam   = rootDistributionDepthParam;
            myRootDistributionExponent     = rootDistributionExponent;
            myRootBottomDistributionFactor = rootBottomDistributionFactor;
            myWaterAvailableMethod         = waterAvailableMethod;
            myNitrogenAvailableMethod      = nitrogenAvailableMethod;
            myKNO3                 = kNO3;
            myKNH4                 = kNH4;
            myMaximumNUptake       = maxNUptake;
            myKuNH4                = kuNH4;
            myKuNO3                = kuNO3;
            myReferenceKSuptake    = referenceKSuptake;
            myReferenceRLD         = referenceRLD;
            myExponentSoilMoisture = exponentSoilMoisture;

            // Link to soil and initialise variables
            myZoneName         = mySoil.Parent.Name;
            mySoilNH4Available = new double[nLayers];
            mySoilNO3Available = new double[nLayers];
            NO3 = Apsim.Find(mySoil, "NO3") as ISolute;
            NH4 = Apsim.Find(mySoil, "NH4") as ISolute;

            // Initialise root DM, N, depth, and distribution
            Depth = initialDepth;
            TargetDistribution = RootDistributionTarget();
            double[] iniRootFraction = CurrentRootDistributionTarget();
            for (int layer = 0; layer < nLayers; layer++)
            {
                Tissue[0].DMLayer[layer]      = initialDM * iniRootFraction[layer];
                Tissue[0].NamountLayer[layer] = NConcOptimum * Tissue[0].DMLayer[layer];
            }
        }
Пример #21
0
        public void CreateGraphs()
        {
            Simulations sims = CreateTemplate();

            sims.FileName = Path.ChangeExtension(Path.GetTempFileName(), ".apsimx");

            DataStore storage = Apsim.Find(sims, typeof(DataStore)) as DataStore;

            storage.FileName = Path.ChangeExtension(sims.FileName, ".db");

            // Run the file to populate the datastore.
            Runner           runner = new Runner(sims);
            List <Exception> errors = runner.Run();

            if (errors != null && errors.Count > 0)
            {
                throw errors[0];
            }

            // Open the .apsimx file in the GUI.
            sims.Write(sims.FileName);
            ExplorerPresenter explorer = UITestsMain.MasterPresenter.OpenApsimXFileInTab(sims.FileName, true);

            GtkUtilities.WaitForGtkEvents();

            // Create a graphs folder under the zone.
            IModel paddock = Apsim.Find(sims, typeof(Zone));
            Folder graphs  = new Folder();

            graphs.Name = "Graphs";

            var command = new AddModelCommand(Apsim.FullPath(paddock),
                                              graphs,
                                              explorer);

            explorer.CommandHistory.Add(command, true);

            // Add an empty graph to the folder.
            Models.Graph graph = new Models.Graph();
            graph.Name = "Graph";
            command    = new AddModelCommand(Apsim.FullPath(graphs),
                                             graph,
                                             explorer);
            explorer.CommandHistory.Add(command, true);

            // Add an empty series to the graph.
            Models.Series series = new Models.Series();
            series.Name = "Series";
            command     = new AddModelCommand(Apsim.FullPath(graph),
                                              series,
                                              explorer);
            explorer.CommandHistory.Add(command, true);

            // click on the series node.
            explorer.SelectNode(Apsim.FullPath(series));
            GtkUtilities.WaitForGtkEvents();

            // Get a reference to the OxyPlot PlotView via reflection.
            SeriesView seriesView = explorer.CurrentRightHandView as SeriesView;
            GraphView  view       = seriesView?.GraphView as GraphView;

            Assert.NotNull(view);

            PlotView plot = ReflectionUtilities.GetValueOfFieldOrProperty("plot1", view) as PlotView;

            Assert.NotNull(plot);

            // Series has no table name or x/y series names yet, so there should
            // be nothing shown on the graph.
            Assert.AreEqual(0, plot.Model.Series.Count);

            // Now draw some data on the graph.
            seriesView.DataSource.SelectedValue = "Report";
            seriesView.X.SelectedValue          = "n";
            seriesView.Y.SelectedValue          = "n2";
            seriesView.SeriesType.SelectedValue = "Scatter";

            GtkUtilities.WaitForGtkEvents();

            // There should now be one series showing.
            Assert.AreEqual(1, plot.Model.Series.Count);

            // It should be a line series.
            Assert.True(plot.Model.Series[0] is LineSeries, "Graph series type is set to scatter, but the series object is not a LineSeries.");

            // Series colour should not be white, and should not be the same as the background colour.
            LineSeries line = plot.Model.Series[0] as LineSeries;

            OxyPlot.OxyColor empty = OxyPlot.OxyColor.FromArgb(0, 0, 0, 0);
            OxyPlot.OxyColor white = OxyPlot.OxyColor.FromArgb(0, 255, 255, 255);
            Assert.AreNotEqual(empty, line.Color, "Graph line series default colour is white on white.");
            Assert.AreNotEqual(white, line.Color, "Graph line series default colour is white on white.");

            // Legend should be visible but empty by default.
            Assert.True(plot.Model.IsLegendVisible);
            // todo - ensure legend is empty

            // Next, we want to change the legend position and ensure that the legend actually moves.

            // Click on the 'show in legend' checkbox.
            seriesView.ShowInLegend.IsChecked = true;
            GtkUtilities.WaitForGtkEvents();

            // Double click on the middle of the legend.
            Cairo.Rectangle legendRect = plot.Model.LegendArea.ToRect(true);
            double          x          = (legendRect.X + (legendRect.X + legendRect.Width)) / 2;
            double          y          = (legendRect.Y + (legendRect.Y + legendRect.Height)) / 2;

            GtkUtilities.DoubleClick(plot, x, y, wait: true);

            // Default legend position should be top-left.
            Assert.AreEqual(plot.Model.LegendPosition, OxyPlot.LegendPosition.TopLeft);

            // Now we want to change the legend position. First, get a reference to the legend view
            // via the legend presenter, via the graph presenter, via the series presenter, via the explorer presenter.
            Assert.True(explorer.CurrentPresenter is SeriesPresenter);
            SeriesPresenter seriesPresenter = explorer.CurrentPresenter as SeriesPresenter;
            LegendPresenter legendPresenter = seriesPresenter.GraphPresenter.CurrentPresenter as LegendPresenter;

            // todo: should we add something like a GetView() method to the IPresenter interface?
            // It might be a bit of work to set up but would save us having to use reflection
            LegendView legendView = ReflectionUtilities.GetValueOfFieldOrProperty("view", legendPresenter) as LegendView;

            // The legend options are inside a Gtk expander.
            Assert.IsTrue(legendView.MainWidget.Parent is Expander);
            Expander expander = legendView.MainWidget.Parent as Expander;

            // The expander should be expanded and the options visible.
            Assert.IsTrue(expander.Expanded);
            Assert.IsTrue(legendView.MainWidget.Visible);

            // The legend view contains a combo box with the legend position options (top-right, bottom-left, etc).
            // This should really be refactored to use a public IDropDownView, which is much more convenient to use.
            // First, get a reference to the combo box via reflection.
            ComboBox combo = ReflectionUtilities.GetValueOfFieldOrProperty("combobox1", legendView) as ComboBox;

            // fixme - we should support all valid OxyPlot legend position types.
            foreach (Models.Graph.LegendPositionType legendPosition in Enum.GetValues(typeof(Models.Graph.LegendPositionType)))
            {
                string name = legendPosition.ToString();
                GtkUtilities.SelectComboBoxItem(combo, name, wait: true);

                OxyPlot.LegendPosition oxyPlotEquivalent = (OxyPlot.LegendPosition)Enum.Parse(typeof(OxyPlot.LegendPosition), name);
                Assert.AreEqual(plot.Model.LegendPosition, oxyPlotEquivalent);
            }

            // If we change the graph to a box plot then the several unused properties should be disabled.
            // These are x variable dropdown, x cumulative, x on top, marker size/type checkboxes.

            // First, make sure that these options are sensitive to input and can be changed.
            Assert.IsTrue(seriesView.X.IsSensitive);
            Assert.IsTrue(seriesView.XCumulative.IsSensitive);
            Assert.IsTrue(seriesView.XOnTop.IsSensitive);
            Assert.IsTrue(seriesView.MarkerSize.IsSensitive);
            Assert.IsTrue(seriesView.MarkerType.IsSensitive);

            // Now change series type to box plot.
            GtkUtilities.SelectComboBoxItem(seriesView.SeriesType, "Box", wait: true);
            Assert.AreEqual(SeriesType.Box, series.Type);

            // Ensure the box plot is not white in light theme.
            plot = ReflectionUtilities.GetValueOfFieldOrProperty("plot1", view) as PlotView;
            Assert.NotNull(plot);
            BoxPlotSeries boxPlot = plot.Model.Series.OfType <BoxPlotSeries>().FirstOrDefault();

            Assert.NotNull(boxPlot);

            Assert.AreNotEqual(empty, boxPlot.Fill);
            Assert.AreNotEqual(white, boxPlot.Fill);
            Assert.AreNotEqual(empty, boxPlot.Stroke);
            Assert.AreNotEqual(white, boxPlot.Stroke);

            // The controls should no longer be sensitive.
            Assert.IsFalse(seriesView.XCumulative.IsSensitive);
            Assert.IsFalse(seriesView.XOnTop.IsSensitive);
            Assert.IsFalse(seriesView.MarkerSize.IsSensitive);
            Assert.IsFalse(seriesView.MarkerType.IsSensitive);

            // Change the series type back to scatter.
            GtkUtilities.SelectComboBoxItem(seriesView.SeriesType, "Scatter", wait: true);

            // The controls should be sensitive once more.
            Assert.IsTrue(seriesView.X.IsSensitive);
            Assert.IsTrue(seriesView.XCumulative.IsSensitive);
            Assert.IsTrue(seriesView.XOnTop.IsSensitive);
            Assert.IsTrue(seriesView.MarkerSize.IsSensitive);
            Assert.IsTrue(seriesView.MarkerType.IsSensitive);
        }
Пример #22
0
        /// <summary>
        /// Export to PDF
        /// </summary>
        public void DoExportPDF(string modelNameToExport)
        {
            // Create a temporary working directory.
            string workingDirectory = Path.Combine(Path.GetTempPath(), "autodoc");

            if (Directory.Exists(workingDirectory))
            {
                Directory.Delete(workingDirectory, true);
            }
            Directory.CreateDirectory(workingDirectory);

            Document document = new Document();

            CreatePDFSyles(document);
            document.DefaultPageSetup.LeftMargin   = MigraDoc.DocumentObjectModel.Unit.FromCentimeter(1);
            document.DefaultPageSetup.TopMargin    = MigraDoc.DocumentObjectModel.Unit.FromCentimeter(1);
            document.DefaultPageSetup.BottomMargin = MigraDoc.DocumentObjectModel.Unit.FromCentimeter(1);
            Section section = document.AddSection();

            // write image files
            string png1 = Path.Combine(workingDirectory, "AIBanner.png");

            using (FileStream file = new FileStream(png1, FileMode.Create, FileAccess.Write))
            {
                Assembly.GetExecutingAssembly().GetManifestResourceStream("UserInterface.Resources.AIBanner.png").CopyTo(file);
            }
            section.AddImage(png1);

            List <AutoDocumentation.ITag> tags = new List <AutoDocumentation.ITag>();

            // See if there is a title page. If so do it first.
            IModel titlePage = Apsim.Find(ExplorerPresenter.ApsimXFile, "TitlePage");

            if (titlePage != null)
            {
                titlePage.Document(tags, 1, 0);
            }
            AddBackground(tags);

            // See if there is a title page. If so do it first.
            IModel introductionPage = Apsim.Find(ExplorerPresenter.ApsimXFile, "Introduction");

            if (introductionPage != null)
            {
                tags.Add(new AutoDocumentation.Heading("Introduction", 1));
                introductionPage.Document(tags, 1, 0);
            }

            AddUserDocumentation(tags, modelNameToExport);

            // Document model description.
            tags.Add(new AutoDocumentation.Heading("Model description", 1));
            ExplorerPresenter.ApsimXFile.DocumentModel(modelNameToExport, tags, 1);

            // Document model validation.
            AddValidationTags(tags, ExplorerPresenter.ApsimXFile, 1, workingDirectory);

            // Move cultivars to end.
            MoveCultivarsToEnd(tags);

            // Strip all blank sections i.e. two headings with nothing between them.
            StripEmptySections(tags);

            // Scan for citations.
            ScanForCitations(tags);

            // Create a bibliography.
            CreateBibliography(tags);

            // numebr all headings.
            NumberHeadings(tags);

            // Populate the PDF section.
            TagsToMigraDoc(section, tags, workingDirectory);

            // Write the PDF file.
            FileNameWritten = Path.Combine(Path.GetDirectoryName(ExplorerPresenter.ApsimXFile.FileName), modelNameToExport + ".pdf");
            PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(false, PdfSharp.Pdf.PdfFontEmbedding.Always);

            pdfRenderer.Document = document;
            pdfRenderer.RenderDocument();
            pdfRenderer.PdfDocument.Save(FileNameWritten);

            // Remove temporary working directory.
            Directory.Delete(workingDirectory, true);
        }
Пример #23
0
        public void Initialise()
        {
            Simulations basicFile = Utilities.GetRunnableSim();

            IModel simulation = Apsim.Find(basicFile, typeof(Simulation));
            IModel paddock    = Apsim.Find(basicFile, typeof(Zone));

            // Add a weather component.
            Models.Weather weather = new Models.Weather();
            weather.Name     = "Weather";
            weather.FileName = "asdf.met";
            Structure.Add(weather, simulation);

            // Add a second weather component.
            Models.Weather weather2 = new Models.Weather();
            weather2.FileName = "asdf.met";
            weather2.Name     = "Weather2";
            Structure.Add(weather2, simulation);

            // Add a third weather component.
            Models.Weather weather3 = new Models.Weather();
            weather3.FileName = "asdf.met";
            weather3.Name     = "Weather3";
            Structure.Add(weather3, simulation);

            // Add a third weather component.
            Models.Weather weather4 = new Models.Weather();
            weather4.FileName = "asdf.met";
            weather4.Name     = "Weather4";
            Structure.Add(weather4, simulation);

            // Add a report.
            Models.Report report = new Models.Report();
            report.Name = "Report";
            Structure.Add(report, paddock);

            // Add the wheat model.
            string json  = ReflectionUtilities.GetResourceAsString(typeof(IModel).Assembly, "Models.Resources.Wheat.json");
            Plant  wheat = FileFormat.ReadFromString <IModel>(json, out _).Children[0] as Plant;

            wheat.ResourceName = "Wheat";
            Structure.Add(wheat, paddock);

            Manager manager = new Manager();

            manager.Code = @"using Models.PMF;
using Models.Core;
using System;
namespace Models
{
    [Serializable]
    public class Script : Model
    {
        [Description(""an amount"")]
        public double Amount { get; set; }
    }
}";
            Structure.Add(manager, paddock);

            Physical physical = new Physical();

            physical.BD     = new double[5];
            physical.AirDry = new double[5];
            physical.LL15   = new double[5];
            Structure.Add(physical, paddock);

            basicFile.Write(basicFile.FileName);
            fileName = basicFile.FileName;

            // Create a new .apsimx file containing two weather nodes.
            Simulations test = Utilities.GetRunnableSim();
            IModel      sim  = Apsim.Find(test, typeof(Simulation));

            Models.Weather w1 = new Models.Weather();
            w1.FileName = "w1.met";
            w1.Name     = "w1";
            Structure.Add(w1, sim);

            Models.Weather w2 = new Models.Weather();
            w2.Name     = "w2";
            w2.FileName = "w2.met";
            Structure.Add(w2, sim);

            extFile = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".apsimx");
            test.Write(extFile);
        }
Пример #24
0
 private void OnSimulationCommencing(object sender, EventArgs e)
 {
     sourceSolute      = Apsim.Find(this, Parent.Name) as ISolute;
     destinationSolute = Apsim.Find(this, destinationName) as ISolute;
 }
Пример #25
0
        /// <summary>
        /// Returns soil water uptake from each zone by the static tree model
        /// </summary>
        /// <param name="soilstate"></param>
        /// <returns></returns>
        public List <Soils.Arbitrator.ZoneWaterAndN> GetSWUptakes(Soils.Arbitrator.SoilState soilstate)
        {
            double Etz = treeZoneWater.Eo; //Eo of Tree Zone

            SWDemand = 0;
            foreach (Zone ZI in ZoneList)
            {
                SWDemand += Etz * GetShade(ZI) / 100 * ZI.Area * 10000;
            }

            IndividualTreeWaterDemand = SWDemand / NumberOfTrees;

            List <ZoneWaterAndN> Uptakes = new List <ZoneWaterAndN>();
            double PotSWSupply           = 0; // Total water supply (L)

            foreach (ZoneWaterAndN Z in soilstate.Zones)
            {
                foreach (Zone ZI in ZoneList)
                {
                    if (Z.Zone.Name == ZI.Name)
                    {
                        ZoneWaterAndN Uptake = new ZoneWaterAndN(ZI);
                        //Find the soil for this zone
                        Soils.Soil ThisSoil = null;

                        foreach (Zone SearchZ in forestryZones)
                        {
                            if (SearchZ.Name == Z.Zone.Name)
                            {
                                ThisSoil = Apsim.Find(SearchZ, typeof(Soils.Soil)) as Soils.Soil;
                                break;
                            }
                        }

                        double[] SW = Z.Water;
                        Uptake.NO3N  = new double[SW.Length];
                        Uptake.NH4N  = new double[SW.Length];
                        Uptake.Water = new double[SW.Length];
                        double[] LL15mm = MathUtilities.Multiply(ThisSoil.LL15, ThisSoil.Thickness);
                        double[] RLD    = GetRLD(ZI);

                        for (int i = 0; i <= SW.Length - 1; i++)
                        {
                            Uptake.Water[i] = Math.Max(SW[i] - LL15mm[i], 0.0) * BaseKL * RLD[i];
                            PotSWSupply    += Uptake.Water[i] * ZI.Area * 10000;
                        }
                        Uptakes.Add(Uptake);
                        break;
                    }
                }
            }
            // Now scale back uptakes if supply > demand
            double F = 0;  // Uptake scaling factor

            if (PotSWSupply > 0)
            {
                F = SWDemand / PotSWSupply;
                if (F > 1)
                {
                    F = 1;
                }
            }
            else
            {
                F = 1;
            }
            WaterStress = Math.Min(1, Math.Max(0, PotSWSupply / SWDemand));

            List <double> uptakeList = new List <double>();

            foreach (ZoneWaterAndN Z in Uptakes)
            {
                Z.Water = MathUtilities.Multiply_Value(Z.Water, F);
                uptakeList.Add(Z.TotalWater);
            }

            WaterUptake = uptakeList.ToArray();
            return(Uptakes);
        }
Пример #26
0
        /// <summary>
        /// Refreshes the data in the gridview when a change is made to one of the view options
        /// </summary>
        /// <param name="sender">The sending object</param>
        /// <param name="e">The event arguments</param>
        private void OnUpdateData(object sender, EventArgs e)
        {
            // The process of initially setting up the view will trigger the event early.
            // This statement catches early triggers to prevent errors/needless computation
            if (view.Pivot.Text == null)
            {
                return;
            }

            var       store = Apsim.Find(table, typeof(IDataStore)) as IDataStore;
            DataTable input = store.Reader.GetData(view.Ledger.Text);

            // Don't try to update if data source isn't found
            if (input == null)
            {
                return;
            }

            // Find distinct values in the chosen pivot
            table.Pivots = new List <string>(
                input
                .AsEnumerable()
                .Select(r => r.Field <object>(view.Pivot.Text).ToString())
                .Distinct()
                .ToList());

            // Reset the table ID if the new pivot list is too short
            if (table.Pivots.Count <= table.ID)
            {
                table.ID = 0;
            }

            // Determine the row/column values
            var rows = input.AsEnumerable().Select(r => r.Field <object>(view.Row.Text)).Distinct();
            var cols = input.AsEnumerable().Select(r => r.Field <object>(view.Column.Text)).Distinct();

            DataTable output = new DataTable($"{view.Expression.Text}Of{table.GetPivot()}{view.Value.Text}");

            // Attach columns to the output table
            foreach (var col in cols)
            {
                output.Columns.Add(col.ToString(), typeof(double));
            }

            // Attach a column for the row titles
            string name = "Pivot: " + table.GetPivot();

            output.Columns.Add(name, typeof(string)).SetOrdinal(0);

            // Populate the table with rows
            foreach (var row in rows)
            {
                DataRow data = output.NewRow();
                data[name] = row;

                foreach (var col in cols)
                {
                    // Search DataTable for all values that match the current row/column
                    var items =
                        from item in input.AsEnumerable()
                        where item.Field <object>(view.Column.Text).ToString() == col.ToString()
                        where item.Field <object>(view.Row.Text).ToString() == row.ToString()
                        select item;

                    // Selects the values based on the current pivot
                    var values =
                        from item in items
                        where item.Field <object>(view.Pivot.Text).ToString() == table.GetPivot()
                        select item.Field <double>(view.Value.Text);

                    // Evaluate the expression on selected values
                    data[col.ToString()] = Aggregate(values);
                }
                output.Rows.Add(data);
                output.AcceptChanges();
            }

            view.gridview.DataSource = output;
        }
Пример #27
0
 /// <summary>
 /// Gets a reference to the data store.
 /// </summary>
 private IStorageReader GetStorage()
 {
     return((Apsim.Find(panel, typeof(IDataStore)) as IDataStore).Reader);
 }
Пример #28
0
        /// <summary>
        /// Export to PDF
        /// </summary>
        public void DoExportPDF(string modelNameToExport)
        {
            // Create a temporary working directory.
            string workingDirectory = Path.Combine(Path.GetTempPath(), "autodoc");

            if (Directory.Exists(workingDirectory))
            {
                Directory.Delete(workingDirectory, true);
            }
            Directory.CreateDirectory(workingDirectory);

            Document document = new Document();

            CreatePDFSyles(document);
            Section section = document.AddSection();

            // write image files
            string png1 = Path.Combine(workingDirectory, "AIBanner.png");

            using (FileStream file = new FileStream(png1, FileMode.Create, FileAccess.Write))
            {
                Assembly.GetExecutingAssembly().GetManifestResourceStream("ApsimNG.Resources.AIBanner.png").CopyTo(file);
            }
            section.AddImage(png1);

            List <AutoDocumentation.ITag> tags = new List <AutoDocumentation.ITag>();

            // See if there is a title page. If so do it first.
            IModel titlePage = Apsim.Find(ExplorerPresenter.ApsimXFile, "TitlePage");

            if (titlePage != null)
            {
                titlePage.Document(tags, 1, 0);
            }
            AddBackground(tags);

            // See if there is a title page. If so do it first.
            IModel introductionPage = Apsim.Find(ExplorerPresenter.ApsimXFile, "Introduction");

            if (introductionPage != null)
            {
                tags.Add(new AutoDocumentation.Heading("Introduction", 1));
                introductionPage.Document(tags, 1, 0);
            }

            // Document model description.
            tags.Add(new AutoDocumentation.Heading("Model description", 1));
            ExplorerPresenter.ApsimXFile.DocumentModel(modelNameToExport, tags, 1);

            // Document model validation.
            AddValidationTags(tags, ExplorerPresenter.ApsimXFile, 1, workingDirectory);

            // Move cultivars to end.
            MoveCultivarsToEnd(tags);

            // Strip all blank sections i.e. two headings with nothing between them.
            StripEmptySections(tags);

            // Scan for citations.
            ScanForCitations(tags);

            // Create a bibliography.
            CreateBibliography(tags);

            // numebr all headings.
            NumberHeadings(tags);

            // Populate the PDF section.
            TagsToMigraDoc(section, tags, workingDirectory);

            // Write the PDF file.
            FileNameWritten = Path.Combine(Path.GetDirectoryName(ExplorerPresenter.ApsimXFile.FileName), modelNameToExport + ".pdf");
            PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(false, PdfSharp.Pdf.PdfFontEmbedding.Always);

            pdfRenderer.Document = document;
            /// Fails on non-Windows platforms. It's trying to get a Windows DC for associated font information
            /// See https://alex-maz.info/pdfsharp_150 for a sort of work-around
            /// See also http://stackoverflow.com/questions/32726223/pdfsharp-migradoc-font-resolver-for-embedded-fonts-system-argumentexception
            pdfRenderer.RenderDocument();
            pdfRenderer.PdfDocument.Save(FileNameWritten);

            // Remove temporary working directory.
            Directory.Delete(workingDirectory, true);
        }
Пример #29
0
 /// <summary>Constructor</summary>
 public OutputLayers()
 {
     NO3Solute  = Apsim.Find(this, "NO3") as ISolute;
     NH4Solute  = Apsim.Find(this, "NH4") as ISolute;
     UreaSolute = Apsim.Find(this, "Urea") as ISolute;
 }
Пример #30
0
        /// <summary>Add user documentation, based on the example.</summary>
        /// <param name="tags">The tags to add to.</param>
        /// <param name="modelName">Name of model to document.</param>
        private void AddUserDocumentation(List <AutoDocumentation.ITag> tags, string modelName)
        {
            // Look for some instructions on which models in the example file we should write.
            // Instructions will be in a memo in the validation .apsimx file

            IModel userDocumentation = Apsim.Get(ExplorerPresenter.ApsimXFile, ".Simulations.UserDocumentation") as IModel;
            string exampleFileName   = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "..", "Examples", modelName + ".apsimx");

            if (userDocumentation != null && userDocumentation.Children.Count > 0 && File.Exists(exampleFileName))
            {
                // Write heading.
                tags.Add(new AutoDocumentation.Heading("User documentation", 1));

                // Open the related example .apsimx file and get its presenter.
                ExplorerPresenter examplePresenter = ExplorerPresenter.MainPresenter.OpenApsimXFileInTab(exampleFileName, onLeftTabControl: true);

                Memo     instructionsMemo = userDocumentation.Children[0] as Memo;
                string[] instructions     = instructionsMemo.MemoText.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                foreach (string instruction in instructions)
                {
                    IModel model = Apsim.Find(examplePresenter.ApsimXFile, instruction);
                    if (model != null)
                    {
                        examplePresenter.SelectNode(Apsim.FullPath(model));
                        while (Gtk.Application.EventsPending())
                        {
                            Gtk.Application.RunIteration();
                        }
                        if (model is Memo)
                        {
                            AutoDocumentation.DocumentModel(model, tags, 1, 0);
                        }
                        else
                        {
                            System.Drawing.Image image = null;

                            if (model is Manager)
                            {
                                image = (examplePresenter.CurrentPresenter as ManagerPresenter).GetScreenshot();
                            }
                            else
                            {
                                image = examplePresenter.GetScreenhotOfRightHandPanel();
                            }

                            if (image != null)
                            {
                                string name = "Example" + instruction;
                                tags.Add(new AutoDocumentation.Image()
                                {
                                    name = name, image = image
                                });
                            }
                        }
                    }
                }

                // Close the tab
                examplePresenter.MainPresenter.CloseTabContaining(examplePresenter.GetView().MainWidget);
                while (Gtk.Application.EventsPending())
                {
                    Gtk.Application.RunIteration();
                }
            }
        }