コード例 #1
0
        /// <summary>Documents the specified model.</summary>
        /// <param name="modelNameToDocument">The model name to document.</param>
        /// <param name="tags">The auto doc tags.</param>
        /// <param name="headingLevel">The starting heading level.</param>
        public void DocumentModel(string modelNameToDocument, List <AutoDocumentation.ITag> tags, int headingLevel)
        {
            Simulation simulation = Apsim.Find(this, typeof(Simulation)) as Simulation;

            if (simulation != null)
            {
                // Find the model of the right name.
                IModel modelToDocument = Apsim.Find(simulation, modelNameToDocument);

                // If not found then find a model of the specified type.
                if (modelToDocument == null)
                {
                    modelToDocument = Apsim.Get(simulation, "[" + modelNameToDocument + "]") as IModel;
                }

                // If the simulation has the same name as the model we want to document, dig a bit deeper
                if (modelToDocument == simulation)
                {
                    modelToDocument = Apsim.ChildrenRecursivelyVisible(simulation).FirstOrDefault(m => m.Name.Equals(modelNameToDocument, StringComparison.OrdinalIgnoreCase));
                }

                // If still not found throw an error.
                if (modelToDocument != null)
                {
                    // Get the path of the model (relative to parentSimulation) to document so that
                    // when replacements happen below we will point to the replacement model not the
                    // one passed into this method.
                    string pathOfSimulation      = Apsim.FullPath(simulation) + ".";
                    string pathOfModelToDocument = Apsim.FullPath(modelToDocument).Replace(pathOfSimulation, "");

                    // Clone the simulation
                    SimulationDescription simDescription = new SimulationDescription(simulation);

                    Simulation clonedSimulation = simDescription.ToSimulation();

                    // Now use the path to get the model we want to document.
                    modelToDocument = Apsim.Get(clonedSimulation, pathOfModelToDocument) as IModel;

                    if (modelToDocument == null)
                    {
                        throw new Exception("Cannot find model to document: " + modelNameToDocument);
                    }

                    // resolve all links in cloned simulation.
                    //Links.Resolve(clonedSimulation, true);

                    modelToDocument.IncludeInDocumentation = true;
                    foreach (IModel child in Apsim.ChildrenRecursively(modelToDocument))
                    {
                        child.IncludeInDocumentation = true;
                    }
                    Links.Resolve(modelToDocument, true, true);
                    // Document the model.
                    AutoDocumentation.DocumentModel(modelToDocument, tags, headingLevel, 0, documentAllChildren: true);

                    // Unresolve links.
                    Links.Unresolve(clonedSimulation, true);
                }
            }
        }
コード例 #2
0
        /// <summary>Gets a list of simulation descriptions.</summary>
        public List <SimulationDescription> GenerateSimulationDescriptions()
        {
            var baseSimulation = Apsim.Child(this, typeof(Simulation)) as Simulation;

            // Calculate all combinations.
            CalculateFactors();

            // Loop through all combinations and add a simulation description to the
            // list of simulations descriptions being returned to the caller.
            var simulationDescriptions = new List <SimulationDescription>();
            int simulationNumber       = 1;

            foreach (var combination in allCombinations)
            {
                // Create a simulation.
                var simulationName = Name + "Simulation" + simulationNumber;
                var simDescription = new SimulationDescription(baseSimulation, simulationName);
                simDescription.Descriptors.Add(new SimulationDescription.Descriptor("SimulationName", simulationName));

                // Apply each composite factor of this combination to our simulation description.
                combination.ForEach(c => c.ApplyToSimulation(simDescription));

                // Add simulation description to the return list of descriptions
                simulationDescriptions.Add(simDescription);

                simulationNumber++;
            }

            return(simulationDescriptions);
        }
コード例 #3
0
        /// <summary>Gets a list of simulation descriptions.</summary>
        public List <SimulationDescription> GenerateSimulationDescriptions()
        {
            var baseSimulation = this.FindChild <Simulation>();

            // Calculate all combinations.
            CalculateFactors();

            // Loop through all combinations and add a simulation description to the
            // list of simulations descriptions being returned to the caller.
            var simulationDescriptions = new List <SimulationDescription>();
            int simulationNumber       = 1;

            foreach (var combination in allCombinations)
            {
                // Create a simulation.
                var simulationName = Name + "Simulation" + simulationNumber;
                var simDescription = new SimulationDescription(baseSimulation, simulationName);

                // Add some descriptors
                int path = (simulationNumber - 1) / (Parameters.Count + 1) + 1;
                simDescription.Descriptors.Add(new SimulationDescription.Descriptor("SimulationName", simulationName));
                simDescription.Descriptors.Add(new SimulationDescription.Descriptor("Path", path.ToString()));

                // Apply each composite factor of this combination to our simulation description.
                combination.ForEach(c => c.ApplyToSimulation(simDescription));

                // Add simulation description to the return list of descriptions
                simulationDescriptions.Add(simDescription);

                simulationNumber++;
            }

            Console.WriteLine($"Simulation names generated by morris:\n{string.Join("\n", simulationDescriptions.Select(s => s.Name))}");
            return(simulationDescriptions);
        }
コード例 #4
0
        public void EnsurePropertyReplacementsWork()
        {
            var sim = new Simulation()
            {
                Name     = "BaseSimulation",
                Children = new List <Model>()
                {
                    new MockWeather()
                    {
                        Name      = "Weather",
                        MaxT      = 1,
                        StartDate = DateTime.MinValue
                    },
                }
            };

            Apsim.ParentAllChildren(sim);

            var simulationDescription = new SimulationDescription(sim, "CustomName");

            simulationDescription.AddOverride(new PropertyReplacement("Weather.MaxT", 2));

            var newSim = simulationDescription.ToSimulation();

            var weather = newSim.Children[0] as MockWeather;

            Assert.AreEqual(weather.MaxT, 2);
        }
コード例 #5
0
        /// <summary>Documents the specified model.</summary>
        /// <param name="modelNameToDocument">The model name to document.</param>
        /// <param name="tags">The auto doc tags.</param>
        /// <param name="headingLevel">The starting heading level.</param>
        public void DocumentModel(string modelNameToDocument, List <AutoDocumentation.ITag> tags, int headingLevel)
        {
            Simulation simulation = this.FindInScope <Simulation>();

            if (simulation != null)
            {
                // Find the model of the right name.
                IModel modelToDocument = simulation.FindInScope(modelNameToDocument);

                // If not found then find a model of the specified type.
                if (modelToDocument == null)
                {
                    modelToDocument = simulation.FindByPath("[" + modelNameToDocument + "]")?.Value as IModel;
                }

                // If the simulation has the same name as the model we want to document, dig a bit deeper
                if (modelToDocument == simulation)
                {
                    modelToDocument = simulation.FindAllDescendants().Where(m => !m.IsHidden).ToList().FirstOrDefault(m => m.Name.Equals(modelNameToDocument, StringComparison.OrdinalIgnoreCase));
                }

                // If still not found throw an error.
                if (modelToDocument != null)
                {
                    // Get the path of the model (relative to parentSimulation) to document so that
                    // when replacements happen below we will point to the replacement model not the
                    // one passed into this method.
                    string pathOfSimulation      = simulation.FullPath + ".";
                    string pathOfModelToDocument = modelToDocument.FullPath.Replace(pathOfSimulation, "");

                    // Clone the simulation
                    SimulationDescription simDescription = new SimulationDescription(simulation);

                    Simulation clonedSimulation = simDescription.ToSimulation();

                    // Prepare the simulation for running - this perform misc cleanup tasks such
                    // as removing disabled models, standardising the soil, resolving links, etc.
                    clonedSimulation.Prepare();
                    FindInScope <IDataStore>().Writer.Stop();
                    // Now use the path to get the model we want to document.
                    modelToDocument = clonedSimulation.FindByPath(pathOfModelToDocument)?.Value as IModel;

                    if (modelToDocument == null)
                    {
                        throw new Exception("Cannot find model to document: " + modelNameToDocument);
                    }

                    // resolve all links in cloned simulation.
                    Links.Resolve(clonedSimulation, true);

                    // Document the model.
                    AutoDocumentation.DocumentModel(modelToDocument, tags, headingLevel, 0, documentAllChildren: true);

                    // Unresolve links.
                    Links.Unresolve(clonedSimulation, true);
                }
            }
        }
コード例 #6
0
        /// <summary>
        /// Perform the command
        /// </summary>
        public void Do(CommandHistory commandHistory)
        {
            Simulation clonedSimulation = null;
            IEvent     events           = null;

            try
            {
                List <Simulation> sims = new List <Models.Core.Simulation>();
                var sim = new SimulationDescription(simulation);
                sims.Add(sim.ToSimulation(explorerPresenter.ApsimXFile));

                events = explorerPresenter.ApsimXFile.GetEventService(clonedSimulation);
                events.ConnectEvents();
                explorerPresenter.ApsimXFile.Links.Resolve(clonedSimulation);

                List <ModelDoc> models = new List <ModelDoc>();
                foreach (IModel model in Apsim.ChildrenRecursively(clonedSimulation))
                {
                    ModelDoc newModelDoc = DocumentModel(model);
                    newModelDoc.Name = Apsim.FullPath(model);
                    models.Add(newModelDoc);
                }

                StringWriter  rawXML     = new StringWriter();
                XmlSerializer serialiser = new XmlSerializer(typeof(List <ModelDoc>));
                serialiser.Serialize(rawXML, models);
                rawXML.Close();

                // Load the XSL transform from the resource
                Stream s         = Assembly.GetExecutingAssembly().GetManifestResourceStream("ApsimNG.Resources.DebugDoc.xsl");
                var    transform = new XslCompiledTransform();
                using (XmlReader reader = XmlReader.Create(s))
                {
                    transform.Load(reader);
                }

                // Apply the transform to the reader and write it to a temporary file.
                string tempFileName = Path.GetTempFileName();
                File.Delete(tempFileName);
                string htmlFileName = Path.ChangeExtension(tempFileName, ".html");
                using (XmlReader reader = XmlReader.Create(new StringReader(rawXML.ToString())))
                    using (XmlWriter htmlWriter = XmlWriter.Create(htmlFileName))
                    {
                        transform.Transform(reader, htmlWriter);
                    }
                Process.Start(htmlFileName);
            }
            finally
            {
                if (clonedSimulation != null)
                {
                    events.DisconnectEvents();
                    explorerPresenter.ApsimXFile.Links.Unresolve(clonedSimulation, allLinks: true);
                }
            }
        }
コード例 #7
0
        public void EnsureReplacementsNodeWorks()
        {
            var simulations = new Simulations()
            {
                Children = new List <Model>()
                {
                    new Folder()
                    {
                        Name     = "Replacements",
                        Children = new List <Model>()
                        {
                            new MockWeather()
                            {
                                Name      = "Weather",
                                MaxT      = 2,
                                StartDate = DateTime.MinValue
                            }
                        }
                    },

                    new Simulation()
                    {
                        Name     = "BaseSimulation",
                        Children = new List <Model>()
                        {
                            new MockWeather()
                            {
                                Name      = "Weather",
                                MaxT      = 1,
                                StartDate = DateTime.MinValue
                            },
                        }
                    }
                }
            };

            Apsim.ParentAllChildren(simulations);

            var sim = simulations.Children[1] as Simulation;
            var simulationDescription = new SimulationDescription(sim);

            var newSim  = simulationDescription.ToSimulation();
            var weather = newSim.Children[0] as MockWeather;

            Assert.AreEqual(weather.MaxT, 2);

            // Make sure any property overrides happens after a model replacement.
            simulationDescription.AddOverride(new PropertyReplacement("Weather.MaxT", 3));
            newSim  = simulationDescription.ToSimulation();
            weather = newSim.Children[0] as MockWeather;
            Assert.AreEqual(weather.MaxT, 3);
        }
コード例 #8
0
        /// <summary>Gets a list of simulation descriptions.</summary>
        public IEnumerable <SimulationDescription> GetSimulationDescriptions()
        {
            // Calculate all combinations.
            var allCombinations = CalculateAllCombinations();

            if (allCombinations != null)
            {
                // Find base simulation.
                var baseSimulation = this.FindChild <Simulation>();

                // Loop through all combinations and add a simulation description to the
                // list of simulations descriptions being returned to the caller.
                foreach (var combination in allCombinations)
                {
                    // Create a simulation.
                    var simulationName = GetName(combination);
                    var simDescription = new SimulationDescription(baseSimulation, simulationName, true);

                    // Add an experiment descriptor.
                    simDescription.Descriptors.Add(new SimulationDescription.Descriptor("Experiment", Name));

                    // Add a simulation descriptor.
                    simDescription.Descriptors.Add(new SimulationDescription.Descriptor("SimulationName", simulationName));

                    // Don't need to add a folderName descriptor, as this will be added by the base simulation.
                    IEnumerable <SimulationDescription> descriptions = baseSimulation?.GenerateSimulationDescriptions();
                    if (descriptions == null)
                    {
                        descriptions = Enumerable.Empty <SimulationDescription>();
                    }
                    foreach (var simulationDescriptor in descriptions)
                    {
                        foreach (var descriptor in simulationDescriptor.Descriptors)
                        {
                            if (descriptor.Name != "SimulationName")
                            {
                                simDescription.Descriptors.Add(descriptor);
                            }
                        }
                    }

                    // Apply each composite factor of this combination to our simulation description.
                    combination.ForEach(c => c.ApplyToSimulation(simDescription));

                    // Add simulation description to the return list of descriptions
                    yield return(simDescription);
                }
            }
        }
コード例 #9
0
            public SimulationDescription ToSimulationDescription()
            {
                var description = new SimulationDescription(null, name);

                description.Descriptors.Add(new SimulationDescription.Descriptor(descriptorName1, descriptorValue1));
                if (descriptorName2 != null)
                {
                    description.Descriptors.Add(new SimulationDescription.Descriptor(descriptorName2, descriptorValue2));
                }
                if (descriptorName3 != null)
                {
                    description.Descriptors.Add(new SimulationDescription.Descriptor(descriptorName3, descriptorValue3));
                }
                return(description);
            }
コード例 #10
0
ファイル: Experiment.cs プロジェクト: mpandreucci/ApsimX
        /// <summary>Gets a list of simulation descriptions.</summary>
        public List <SimulationDescription> GenerateSimulationDescriptions()
        {
            var simulationDescriptions = new List <SimulationDescription>();

            // Calculate all combinations.
            var allCombinations = CalculateAllCombinations();

            if (allCombinations != null)
            {
                // Find base simulation.
                var baseSimulation = Apsim.Child(this, typeof(Simulation)) as Simulation;

                // Loop through all combinations and add a simulation description to the
                // list of simulations descriptions being returned to the caller.
                foreach (var combination in allCombinations)
                {
                    // Create a simulation.
                    var simulationName = GetName(combination);
                    var simDescription = new SimulationDescription(baseSimulation, simulationName, true);

                    // Add an experiment descriptor.
                    simDescription.Descriptors.Add(new SimulationDescription.Descriptor("Experiment", Name));

                    // Add a simulation descriptor.
                    simDescription.Descriptors.Add(new SimulationDescription.Descriptor("SimulationName", simulationName));

                    // Add in simulation descriptors.
                    foreach (var simulationDescriptor in baseSimulation.GenerateSimulationDescriptions())
                    {
                        foreach (var descriptor in simulationDescriptor.Descriptors)
                        {
                            if (descriptor.Name != "SimulationName")
                            {
                                simDescription.Descriptors.Add(descriptor);
                            }
                        }
                    }

                    // Apply each composite factor of this combination to our simulation description.
                    combination.ForEach(c => c.ApplyToSimulation(simDescription));

                    // Add simulation description to the return list of descriptions
                    simulationDescriptions.Add(simDescription);
                }
            }

            return(simulationDescriptions);
        }
コード例 #11
0
        /// <summary>
        /// Apply this CompositeFactor to the specified simulation
        /// </summary>
        /// <param name="simulationDescription">A description of a simulation.</param>
        public void ApplyToSimulation(SimulationDescription simulationDescription)
        {
            ParseAllSpecifications(out List <string> allPaths, out List <object> allValues);

            if (allPaths.Count > 1 && allPaths.Count != allValues.Count)
            {
                throw new Exception("The number of factor paths does not match the number of factor values");
            }

            // Add a simulation override for each path / value combination.
            for (int i = 0; i != allPaths.Count; i++)
            {
                if (allValues[i] is IModel)
                {
                    simulationDescription.AddOverride(new ModelReplacement(allPaths[i], allValues[i] as IModel));
                }
                else
                {
                    simulationDescription.AddOverride(new PropertyReplacement(allPaths[i], allValues[i]));
                }
            }

            if (!(Parent is Factors))
            {
                // Set descriptors in simulation.
                string descriptorName = Name;
                if (Parent != null)
                {
                    descriptorName = Parent.Name;
                }
                if (Specifications != null && Specifications.Count > 0)
                {
                    // compound factor value ie. one that has multiple specifications.
                    simulationDescription.Descriptors.Add(new SimulationDescription.Descriptor(descriptorName, Name));
                }
                else
                {
                    if (allValues[0] is IModel)
                    {
                        simulationDescription.Descriptors.Add(new SimulationDescription.Descriptor(descriptorName, (allValues[0] as IModel).Name));
                    }
                    else
                    {
                        simulationDescription.Descriptors.Add(new SimulationDescription.Descriptor(descriptorName, allValues[0].ToString()));
                    }
                }
            }
        }
コード例 #12
0
        /// <summary>Gets the next job to run</summary>
        public List <SimulationDescription> GenerateSimulationDescriptions()
        {
            var simulationDescription = new SimulationDescription(this);

            simulationDescription.Descriptors.Add(new SimulationDescription.Descriptor("SimulationName", Name));

            foreach (var zone in Apsim.ChildrenRecursively(this, typeof(Zone)))
            {
                simulationDescription.Descriptors.Add(new SimulationDescription.Descriptor("Zone", zone.Name));
            }

            return(new List <SimulationDescription>()
            {
                simulationDescription
            });
        }
コード例 #13
0
        public void EnsureReplacementWithInvalidNameDoesntMatch()
        {
            var simulations = new Simulations()
            {
                Children = new List <Model>()
                {
                    new Folder()
                    {
                        Name     = "Replacements",
                        Children = new List <Model>()
                        {
                            new MockWeather()
                            {
                                Name      = "Dummy name",
                                MaxT      = 2,
                                StartDate = DateTime.MinValue
                            }
                        }
                    },

                    new Simulation()
                    {
                        Name     = "BaseSimulation",
                        Children = new List <Model>()
                        {
                            new MockWeather()
                            {
                                Name      = "Weather",
                                MaxT      = 1,
                                StartDate = DateTime.MinValue
                            },
                        }
                    }
                }
            };

            Apsim.ParentAllChildren(simulations);

            var sim = simulations.Children[1] as Simulation;
            var simulationDescription = new SimulationDescription(sim);

            var newSim  = simulationDescription.ToSimulation();
            var weather = newSim.Children[0] as MockWeather;

            // Name ('Dummy name') didn't match so property should still be 1.
            Assert.AreEqual(weather.MaxT, 1);
        }
コード例 #14
0
ファイル: Series.cs プロジェクト: BrianCollinss/ApsimNG
        /// <summary>
        /// Create and return a list of series definitions for each group by field.
        /// </summary>
        /// <param name="varyByFieldNames">The vary by fields</param>
        /// <param name="checkpointName">Checkpoint name.</param>
        /// <param name="colourModifier">Checkpoint colour modifier.</param>
        /// <param name="markerModifier">Checkpoint marker size modifier.</param>
        /// <param name="simulationDescriptions">The simulation descriptions that are in scope.</param>
        /// <param name="whereClauseForInScopeData">An SQL WHERE clause for rows that are in scope.</param>
        private List <SeriesDefinition> CreateDefinitionsUsingVaryBy(List <string> varyByFieldNames,
                                                                     string checkpointName,
                                                                     double colourModifier,
                                                                     double markerModifier,
                                                                     List <SimulationDescription> simulationDescriptions,
                                                                     string whereClauseForInScopeData)
        {
            SplitDescriptionsWithSameDescriptors(simulationDescriptions);

            var definitions = new List <SeriesDefinition>();

            foreach (var simulationDescription in simulationDescriptions)
            {
                // Determine the descriptors to pass to the new definition that will
                // be created below. We only want to pass the 'vary by' descriptors.
                var descriptorsForDefinition = new List <SimulationDescription.Descriptor>();
                foreach (var descriptor in simulationDescription.Descriptors)
                {
                    if (varyByFieldNames.Contains(descriptor.Name))
                    {
                        descriptorsForDefinition.Add(descriptor);
                    }
                }

                // Try and find a definition that has the same descriptors.
                var foundDefinition = definitions.Find(d => SimulationDescription.Equals(d.Descriptors, descriptorsForDefinition));

                // Only create a definition if there are descriptors and there isn't
                // already a definition with the same descriptors.
                if (descriptorsForDefinition.Count > 0 && foundDefinition == null)
                {
                    // Create the definition.
                    definitions.Add(new SeriesDefinition(this,
                                                         checkpointName,
                                                         colourModifier,
                                                         markerModifier,
                                                         whereClauseForInScopeData,
                                                         Filter,
                                                         descriptorsForDefinition));
                }
            }

            return(definitions);
        }
コード例 #15
0
        public void EnsureModelOverrideWork()
        {
            var sim = new Simulation()
            {
                Name     = "BaseSimulation",
                Children = new List <Model>()
                {
                    new MockWeather()
                    {
                        Name      = "Weather",
                        MaxT      = 1,
                        StartDate = DateTime.MinValue
                    },
                }
            };

            Apsim.ParentAllChildren(sim);

            var replacementWeather = new MockWeather()
            {
                Name      = "Weather2",
                MaxT      = 2,
                StartDate = DateTime.MinValue
            };

            var simulationDescription = new SimulationDescription(sim, "CustomName");

            simulationDescription.AddOverride(new ModelReplacement("Weather", replacementWeather));

            var newSim = simulationDescription.ToSimulation();

            Assert.AreEqual(newSim.Name, "CustomName");

            var weather = newSim.Children[0] as MockWeather;

            Assert.AreEqual(weather.MaxT, 2);

            // The name of the new model should be the same as the original model.
            Assert.AreEqual(weather.Name, "Weather");
        }
コード例 #16
0
        /// <summary>Gets the next job to run</summary>
        public List <SimulationDescription> GenerateSimulationDescriptions()
        {
            var simulationDescription = new SimulationDescription(this);

            // Add a folderName descriptor.
            var folderNode = Apsim.Parent(this, typeof(Folder));

            if (folderNode != null)
            {
                simulationDescription.Descriptors.Add(new SimulationDescription.Descriptor("FolderName", folderNode.Name));
            }

            simulationDescription.Descriptors.Add(new SimulationDescription.Descriptor("SimulationName", Name));

            foreach (var zone in Apsim.ChildrenRecursively(this, typeof(Zone)))
            {
                simulationDescription.Descriptors.Add(new SimulationDescription.Descriptor("Zone", zone.Name));
            }

            return(new List <SimulationDescription>()
            {
                simulationDescription
            });
        }
コード例 #17
0
        /// <summary>Gets the next job to run</summary>
        public List <SimulationDescription> GenerateSimulationDescriptions()
        {
            var simulationDescription = new SimulationDescription(this);

            // Add a folderName descriptor.
            var folderNode = FindAncestor <Folder>();

            if (folderNode != null)
            {
                simulationDescription.Descriptors.Add(new SimulationDescription.Descriptor("FolderName", folderNode.Name));
            }

            simulationDescription.Descriptors.Add(new SimulationDescription.Descriptor("SimulationName", Name));

            foreach (var zone in this.FindAllDescendants <Zone>())
            {
                simulationDescription.Descriptors.Add(new SimulationDescription.Descriptor("Zone", zone.Name));
            }

            return(new List <SimulationDescription>()
            {
                simulationDescription
            });
        }
コード例 #18
0
        public void EnsureSoilIsStandardised()
        {
            var sim = new Simulation()
            {
                Name     = "Simulation",
                Children = new List <Model>()
                {
                    new Soil
                    {
                        Children = new List <Model>()
                        {
                            new Physical()
                            {
                                Thickness = new double[] { 100, 300, 300 },
                                BD        = new double[] { 1.36, 1.216, 1.24 },
                                AirDry    = new double[] { 0.135, 0.214, 0.261 },
                                LL15      = new double[] { 0.27, 0.267, 0.261 },
                                DUL       = new double[] { 0.365, 0.461, 0.43 },
                                SAT       = new double[] { 0.400, 0.481, 0.45 },

                                Children = new List <Model>()
                                {
                                    new SoilCrop
                                    {
                                        Name = "Wheat",
                                        KL   = new double[] { 0.06, 0.060, 0.060 },
                                        LL   = new double[] { 0.27, 0.267, 0.261 }
                                    }
                                }
                            },
                            new SoilWater(),
                            new Organic
                            {
                                Thickness = new double[] { 100, 300 },
                                Carbon    = new double[] { 2, 1 }
                            },
                            new Chemical
                            {
                                Thickness = new double[] { 100, 200 },
                                CL        = new double[] { 38, double.NaN }
                            },
                            new Sample
                            {
                                Thickness = new double[] { 500 },
                                SW        = new double[] { 0.103 },
                                OC        = new double[] { 1.35 },
                                SWUnits   = Sample.SWUnitsEnum.Gravimetric
                            },
                            new Sample
                            {
                                Thickness = new double[] { 1000 },
                                NO3N      = new double[] { 27 },
                                OC        = new double[] { 1.35 },
                                SWUnits   = Sample.SWUnitsEnum.Volumetric
                            },
                            new CERESSoilTemperature(),
                        }
                    }
                }
            };

            Apsim.ParentAllChildren(sim);

            var originalSoil  = sim.Children[0] as Soil;
            var originalWater = originalSoil.Children[0] as Physical;

            originalSoil.OnCreated();

            var simulationDescription = new SimulationDescription(sim);

            var newSim = simulationDescription.ToSimulation();

            var water             = newSim.Children[0].Children[0] as Physical;
            var soilOrganicMatter = newSim.Children[0].Children[2] as Organic;
            var sample            = newSim.Children[0].Children[4] as Sample;

            // Make sure layer structures have been standardised.
            Assert.AreEqual(water.Thickness, originalWater.Thickness);
            Assert.AreEqual(soilOrganicMatter.Thickness, originalWater.Thickness);
            Assert.AreEqual(sample.Thickness, originalWater.Thickness);

            // Make sure sample units are volumetric.
            Assert.AreEqual(sample.SWUnits, Sample.SWUnitsEnum.Volumetric);
        }