/// <summary>Checks validity of soil water parameters. /// This method is called from the Context Menu by Selecting "Check Soil" /// So you need to standardise it before doing the comparisons</summary> /// <param name="soilToCheck">The soil to check.</param> /// <returns>Error messages.</returns> public static string CheckWithStandardisation(Soil soilToCheck) { var soil = Apsim.Clone(soilToCheck) as Soil; SoilStandardiser.Standardise(soil); return(Check(soilToCheck, soil)); }
/// <summary> /// Checks validity of soil parameters. Throws if soil is invalid. /// Standardises the soil before performing tests. /// </summary> /// <param name="soilToCheck">The soil to check.</param> public static void CheckWithStandardisation(Soil soilToCheck) { var soil = Apsim.Clone(soilToCheck) as Soil; SoilStandardiser.Standardise(soil); Check(soil); }
/// <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>(); clonedSimulation = Apsim.Clone(simulation) as Simulation; sims.Add(clonedSimulation); explorerPresenter.ApsimXFile.MakeSubstitutions(clonedSimulation); 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); } } }
private new void OnSimulationCommencing(object sender, EventArgs e) { // locate AE relationship adultEquivalentRelationship = this.FindAllChildren <Relationship>().FirstOrDefault(a => a.Name.ToUpper().Contains("AE")); Items = new List <LabourType>(); foreach (LabourType labourChildModel in this.FindAllChildren <LabourType>()) { IndividualAttribute att = new IndividualAttribute() { StoredValue = labourChildModel.Name }; if (UseCohorts) { LabourType labour = new LabourType() { Sex = labourChildModel.Sex, Individuals = labourChildModel.Individuals, Parent = this, InitialAge = labourChildModel.InitialAge, AgeInMonths = labourChildModel.InitialAge * 12, LabourAvailability = labourChildModel.LabourAvailability, Name = labourChildModel.Name, Hired = labourChildModel.Hired }; labour.Attributes.Add("Group", att); labour.TransactionOccurred += Resource_TransactionOccurred; Items.Add(labour); } else { for (int i = 0; i < labourChildModel.Individuals; i++) { // get the availability from provided list LabourType labour = new LabourType() { Sex = labourChildModel.Sex, Individuals = 1, Parent = this, InitialAge = labourChildModel.InitialAge, AgeInMonths = labourChildModel.InitialAge * 12, LabourAvailability = labourChildModel.LabourAvailability, Name = labourChildModel.Name + ((labourChildModel.Individuals > 1) ? "_" + (i + 1).ToString() : ""), Hired = labourChildModel.Hired }; labour.Attributes.Add("Group", att); labour.TransactionOccurred += Resource_TransactionOccurred; Items.Add(labour); } } } // clone pricelist so model can modify if needed and not affect initial parameterisation if (this.FindAllChildren <LabourPricing>().Count() > 0) { PayList = Apsim.Clone(this.FindAllChildren <LabourPricing>().FirstOrDefault()); } }
/// <summary> /// Convert the simulation decription to a simulation. /// path. /// </summary> public Simulation ToSimulation() { try { AddReplacements(); Simulation newSimulation; if (doClone) { newSimulation = Apsim.Clone(baseSimulation) as Simulation; // After a binary clone, we need to force all managers to // recompile their scripts. This is to work around an issue // where scripts will change during deserialization. See issue // #4463 and the TestMultipleChildren test inside ReportTests. Apsim.ChildrenRecursively(newSimulation, typeof(Manager)).ForEach(m => m.OnCreated()); } else { newSimulation = baseSimulation; } if (string.IsNullOrWhiteSpace(Name)) { newSimulation.Name = baseSimulation.Name; } else { newSimulation.Name = Name; } newSimulation.Parent = null; Apsim.ParentAllChildren(newSimulation); replacementsToApply.ForEach(r => r.Replace(newSimulation)); // Give the simulation the descriptors. newSimulation.Descriptors = Descriptors; newSimulation.Services = GetServices(); // Standardise the soil. var soils = Apsim.ChildrenRecursively(newSimulation, typeof(Soils.Soil)); foreach (Soils.Soil soil in soils) { SoilStandardiser.Standardise(soil); } newSimulation.ClearCaches(); return(newSimulation); } catch (Exception err) { var message = "Error in file: " + baseSimulation.FileName + " Simulation: " + Name; throw new Exception(message, err); } }
/// <summary>Perform the actual replacement.</summary> private void ReplaceModel(IModel match) { IModel newModel = Apsim.Clone(replacement); int index = match.Parent.Children.IndexOf(match as Model); match.Parent.Children.Insert(index, newModel as Model); newModel.Parent = match.Parent; newModel.Name = match.Name; match.Parent.Children.Remove(match as Model); newModel.OnCreated(); }
/// <summary> /// Convert the simulation decription to a simulation. /// path. /// </summary> public Simulation ToSimulation() { try { AddReplacements(); Simulation newSimulation; if (doClone) { newSimulation = Apsim.Clone(baseSimulation) as Simulation; // After a binary clone, we need to force all managers to // recompile their scripts. This is to work around an issue // where scripts will change during deserialization. See issue // #4463 and the TestMultipleChildren test inside ReportTests. foreach (Manager script in newSimulation.FindAllDescendants <Manager>()) { script.OnCreated(); } } else { newSimulation = baseSimulation; } if (string.IsNullOrWhiteSpace(Name)) { newSimulation.Name = baseSimulation.Name; } else { newSimulation.Name = Name; } newSimulation.Parent = null; newSimulation.ParentAllDescendants(); replacementsToApply.ForEach(r => r.Replace(newSimulation)); // Give the simulation the descriptors. if (newSimulation.Descriptors == null || Descriptors.Count > 0) { newSimulation.Descriptors = Descriptors; } newSimulation.Services = GetServices(); newSimulation.ClearCaches(); return(newSimulation); } catch (Exception err) { var message = "Error in file: " + baseSimulation.FileName + " Simulation: " + Name; throw new Exception(message, err); } }
private void OnCLEMInitialiseResource(object sender, EventArgs e) { // clone pricelist so model can modify if needed and not affect initial parameterisation if (this.FindAllChildren <AnimalPricing>().Count() > 0) { PriceList = Apsim.Clone(this.FindAllChildren <AnimalPricing>().FirstOrDefault()) as AnimalPricing; priceGroups = PriceList.FindAllChildren <AnimalPriceGroup>().Cast <AnimalPriceGroup>().ToList(); } // get conception parameters and rate calculation method ConceptionModel = this.FindAllChildren <Model>().Where(a => typeof(IConceptionModel).IsAssignableFrom(a.GetType())).Cast <IConceptionModel>().FirstOrDefault(); }
/// <summary> /// Generates an .apsimx file containing replacements model (if it /// exists), a datastore, and all children of this model. Saves the /// file to disk and returns the absolute path to the file. /// </summary> private string GenerateApsimXFile() { Simulations rootNode = FindAncestor <Simulations>(); string apsimxFileName = GetTempFileName($"apsimx_file_{id}", ".apsimx"); Simulations sims = new Simulations(); sims.Children.AddRange(Children.Select(c => Apsim.Clone(c))); sims.Children.RemoveAll(c => c is IDataStore); IModel replacements = this.FindInScope <Replacements>(); if (replacements != null && !sims.Children.Any(c => c is Replacements)) { sims.Children.Add(Apsim.Clone(replacements)); } // Search for IDataStore, not DataStore - to allow for StorageViaSockets. IDataStore storage = this.FindInScope <IDataStore>(); IModel newDataStore = new DataStore(); if (storage != null && storage is IModel m) { newDataStore.Children.AddRange(m.Children.Select(c => Apsim.Clone(c))); } sims.Children.Add(newDataStore); sims.ParentAllDescendants(); sims.Write(apsimxFileName); string originalFile = rootNode?.FileName; if (string.IsNullOrEmpty(originalFile)) { originalFile = storage?.FileName; } // Copy files across. foreach (IReferenceExternalFiles fileReference in sims.FindAllDescendants <IReferenceExternalFiles>().Cast <IReferenceExternalFiles>()) { foreach (string file in fileReference.GetReferencedFileNames()) { string absoluteFileName = PathUtilities.GetAbsolutePath(file, originalFile); string fileName = Path.GetFileName(absoluteFileName); string newPath = Path.GetDirectoryName(sims.FileName); File.Copy(absoluteFileName, Path.Combine(newPath, fileName), true); } } return(apsimxFileName); }
/// <summary> /// Generates an .apsimx file containing replacements model (if it /// exists), a datastore, and all children of this model. Saves the /// file to disk and returns the absolute path to the file. /// </summary> private string GenerateApsimXFile() { Simulations rootNode = (Apsim.Parent(this, typeof(Simulations)) as Simulations); string apsimxFileName = GetTempFileName($"apsimx_file_{id}", ".apsimx"); Simulations sims = new Simulations(); sims.Children.AddRange(Children.Select(c => Apsim.Clone(c))); sims.Children.RemoveAll(c => c is IDataStore); IModel replacements = Apsim.Find(this, typeof(Replacements)); if (replacements != null && !sims.Children.Any(c => c is Replacements)) { sims.Children.Add(Apsim.Clone(replacements)); } IModel storage = Apsim.Find(this, typeof(IDataStore)); IModel newDataStore = new DataStore(); if (storage != null) { newDataStore.Children.AddRange(storage.Children.Select(c => Apsim.Clone(c))); } sims.Children.Add(newDataStore); Apsim.ParentAllChildren(sims); sims.Write(apsimxFileName); string originalFile = rootNode?.FileName; if (string.IsNullOrEmpty(originalFile)) { originalFile = (storage as IDataStore)?.FileName; } // Copy files across. foreach (IReferenceExternalFiles fileReference in Apsim.ChildrenRecursively(sims, typeof(IReferenceExternalFiles)).Cast <IReferenceExternalFiles>()) { foreach (string file in fileReference.GetReferencedFileNames()) { string absoluteFileName = PathUtilities.GetAbsolutePath(file, originalFile); string fileName = Path.GetFileName(absoluteFileName); string newPath = Path.GetDirectoryName(sims.FileName); File.Copy(absoluteFileName, Path.Combine(newPath, fileName), true); } } return(apsimxFileName); }
/// <summary> /// Convert the simulation decription to a simulation. /// path. /// </summary> public Simulation ToSimulation() { try { AddReplacements(); Simulation newSimulation; if (doClone) { newSimulation = Apsim.Clone(baseSimulation) as Simulation; } else { newSimulation = baseSimulation; } if (string.IsNullOrWhiteSpace(Name)) { newSimulation.Name = baseSimulation.Name; } else { newSimulation.Name = Name; } newSimulation.Parent = null; Apsim.ParentAllChildren(newSimulation); replacementsToApply.ForEach(r => r.Replace(newSimulation)); // Give the simulation the descriptors. newSimulation.Descriptors = Descriptors; newSimulation.Services = GetServices(); // Standardise the soil. var soils = Apsim.ChildrenRecursively(newSimulation, typeof(Soils.Soil)); foreach (Soils.Soil soil in soils) { SoilStandardiser.Standardise(soil); } newSimulation.ClearCaches(); return(newSimulation); } catch (Exception err) { var message = "Error in file: " + baseSimulation.FileName + " Simulation: " + Name; throw new Exception(message, err); } }
/// <summary>Called to start the job.</summary> /// <param name="jobManager">The job manager running this job.</param> /// <param name="workerThread">The thread this job is running on.</param> public void Run(JobManager jobManager, BackgroundWorker workerThread) { Simulation clonedSim = Apsim.Clone(simulation) as Simulation; Simulations simulations = Apsim.Parent(simulation, typeof(Simulations)) as Simulations; simulation.FileName = simulations.FileName; Simulations.MakeSubstitutions(simulations, new List <Simulation> { clonedSim }); Simulations.CallOnLoaded(clonedSim); jobManager.AddChildJob(this, clonedSim); }
/// <summary>Copy constructor.</summary> public NutrientPatch(NutrientPatch from) { soilThickness = from.soilThickness; patchManager = from.patchManager; Nutrient = Apsim.Clone(from.Nutrient) as Nutrient; Structure.Add(Nutrient, from.Nutrient.Parent); // Find all solutes. foreach (ISolute solute in Nutrient.FindAllChildren <ISolute>()) { solutes.Add(solute.Name, solute); } lignin = from.lignin; cellulose = from.cellulose; carbohydrate = from.carbohydrate; }
/// <summary> /// Returns the link to the matching resource in the market place if found or creates a new clone copy for future transactions /// This allows this action to be performed once to store the link rather than at every transaction /// This functionality allows resources not in the market at the start of the simulation to be traded. /// </summary> /// <param name="resourceType">The resource type to trade</param> /// <returns>Whether the search was successful</returns> public IResourceWithTransactionType LinkToMarketResourceType(CLEMResourceTypeBase resourceType) { if (!this.Parent.GetType().Name.Contains("Market")) { throw new ApsimXException(this, "ooops"); } // find parent group type ResourceBaseWithTransactions parent = (resourceType as Model).Parent as ResourceBaseWithTransactions; ResourceBaseWithTransactions resGroup = GetResourceGroupByType(parent.GetType()) as ResourceBaseWithTransactions; if (resGroup is null) { // add warning the market is not currently trading in this resource string zoneName = Apsim.Parent(this, typeof(Zone)).Name; Warnings.Add($"[{zoneName}] is currently not accepting resources of type [r={parent.GetType().ToString()}]\nOnly resources groups provided in the [r=ResourceHolder] in the simulation tree will be traded."); return(null); } // TODO: do some group checks. land units, currency // TODO: if market and looking for finance only return or create "Bank" // find resource type in group object resType = resGroup.GetByName((resourceType as IModel).Name) as IResourceWithTransactionType; if (resType is null) { // clone resource resType = Apsim.Clone(resourceType); if (resType is null) { // add warning the market does not have the resource string zoneName = Apsim.Parent(this, typeof(Zone)).Name; Warnings.Add($"The resource [r={resourceType.Name}] does not exist in the market and the resource of type [r={resourceType.GetType().ToString()}] cannot be cloned\nAdd resource and associated components to the market."); return(null); } else { (resType as IModel).Parent = resGroup; // add new resource type resGroup.AddNewResourceType(resType as IResourceWithTransactionType); } } return(resType as IResourceWithTransactionType); }
/// <summary>Perform the actual replacement.</summary> private void ReplaceModel(IModel match) { IModel newModel = Apsim.Clone(replacement); int index = match.Parent.Children.IndexOf(match as Model); match.Parent.Children.Insert(index, newModel as Model); newModel.Parent = match.Parent; newModel.Name = match.Name; newModel.Enabled = match.Enabled; match.Parent.Children.Remove(match as Model); newModel.Parent.OnCreated(); foreach (var model in Apsim.ChildrenRecursively(newModel.Parent)) { model.OnCreated(); } }
/// <summary> /// Create a specific simulation. /// </summary> public Simulation CreateSpecificSimulation(string name) { List <List <FactorValue> > allCombinations = AllCombinations(); Simulation baseSimulation = Apsim.Child(this, typeof(Simulation)) as Simulation; Simulations parentSimulations = Apsim.Parent(this, typeof(Simulations)) as Simulations; foreach (List <FactorValue> combination in allCombinations) { string newSimulationName = Name; foreach (FactorValue value in combination) { newSimulationName += value.Name; } if (newSimulationName == name) { Simulation newSimulation = Apsim.Clone(baseSimulation) as Simulation; newSimulation.Name = newSimulationName; newSimulation.Parent = null; newSimulation.FileName = parentSimulations.FileName; Apsim.ParentAllChildren(newSimulation); // Make substitutions. Simulations.MakeSubstitutions(parentSimulations, new List <Simulation> { newSimulation }); // Connect events and links in our new simulation. Events events = new Events(); events.AddModelEvents(newSimulation); events.CallEventHandler(newSimulation, "Loaded", null); foreach (FactorValue value in combination) { value.ApplyToSimulation(newSimulation); } PushFactorsToReportModels(newSimulation, combination); return(newSimulation); } } return(null); }
/// <summary>Perform the actual replacement.</summary> private void ReplaceModel(IModel match) { IModel newModel = Apsim.Clone(replacement); int index = match.Parent.Children.IndexOf(match as Model); match.Parent.Children.Insert(index, newModel as Model); newModel.Parent = match.Parent; newModel.Name = match.Name; newModel.Enabled = match.Enabled; match.Parent.Children.Remove(match as Model); // Don't call newModel.Parent.OnCreated(), because if we're replacing // a child of a resource model, the resource model's OnCreated event // will make it reread the resource string and replace this child with // the 'official' child from the resource. foreach (var model in Apsim.ChildrenRecursively(newModel.Parent)) { model.OnCreated(); } }
/// <summary> /// User has clicked the add soil button. /// </summary> /// <param name="sender">The event sender.</param> /// <param name="e">The event arguments.</param> private void OnAddSoilButtonClicked(object sender, EventArgs e) { foreach (int selectedIndex in dataView.SelectedIndicies) { var values = dataView.GetRow(selectedIndex); var soilName = (string)values[0]; Soil matchingSoil = Apsim.Clone <Soil>(allSoils.First(s => s.Soil.Name == soilName).Soil); if (!matchingSoil.Children.Any(c => c is INutrient)) { matchingSoil.Children.Add(new Nutrient() { ResourceName = "Nutrient" }); } ICommand addSoil = new AddModelCommand(model, matchingSoil, explorerPresenter.GetNodeDescription); explorerPresenter.CommandHistory.Add(addSoil); } explorerPresenter.Populate(); }
/// <summary>Get the next job to run. Needs to be thread safe.</summary> /// <returns>The job to run or NULL if no more jobs to be run.</returns> private MultiProcessJob GetJobToRun() { var jobKey = Guid.NewGuid(); MultiProcessJob job = null; SpinWait.SpinUntil(() => jobsToRun.TryDequeue(out job) || jobQueueFillerTask.IsCompleted); if (job == null) { return(null); } else if (job.RunnableJob is SimulationDescription) { job.DataStore = (job.RunnableJob as SimulationDescription).Storage; job.JobSentToClient = (job.RunnableJob as SimulationDescription).ToSimulation(); (job.JobSentToClient as Simulation).Services = null; } else { job.JobSentToClient = job.RunnableJob; if (job.JobSentToClient is IModel m) { job.JobSentToClient = Apsim.Clone(m) as IRunnable; } if (job.RunnableJob is IModel model) { IModel replacements = model.FindInScope <Replacements>(); if (replacements != null) { (job.JobSentToClient as IModel).Children.Add(Apsim.Clone(replacements)); } job.DataStore = model.FindInScope <IDataStore>(); if (job.DataStore != null) { (job.JobSentToClient as IModel).Children.Add(Apsim.Clone(job.DataStore as IModel)); } } } return(job); }
/// <summary> /// Replace the object specified by 'path' in 'newSimulation' with the specified 'value' /// </summary> private static void ApplyModelReplacement(Simulation newSimulation, string path, IModel value) { IModel newModel = Apsim.Clone(value); IModel modelToReplace = newSimulation.Get(path) as IModel; if (modelToReplace == null) { throw new Exception("Cannot find model to replace. Model path: " + path); } int index = modelToReplace.Parent.Children.IndexOf(modelToReplace as Model); if (index == -1) { throw new Exception("Cannot find model to replace. Model path: " + path); } modelToReplace.Parent.Children.RemoveAt(index); modelToReplace.Parent.Children.Insert(index, newModel as Model); newModel.Name = modelToReplace.Name; newModel.Parent = modelToReplace.Parent; }
public void Runner_CreateSimulations() { // Create a tree with a root node for our models. Simulation simulation = new Simulation(); Clock clock = new Clock(); clock.StartDate = new DateTime(2015, 1, 1); clock.EndDate = new DateTime(2015, 1, 1); simulation.Children.Add(clock); simulation.Children.Add(new MockSummary()); simulation.Children.Add(new MockStorage()); Experiment experiment = new Experiment(); Factors factors = new Factors(); Factor factor1 = new Factor(); factor1.Specifications = new List <string>(); factor1.Specifications.Add("[Clock].StartDate = 2003-11-01, 2003-12-20"); experiment.Children.Add(simulation); factors.Children.Add(factor1); experiment.Children.Add(factors); Simulations topLevelSimulationsModel = Simulations.Create(new IModel[] { experiment, Apsim.Clone(simulation) }); Runner.SimulationCreator simulationCreator = Runner.AllSimulations(topLevelSimulationsModel); string[] simulationNames = simulationCreator.Select(sim => sim.Name).ToArray(); Assert.AreEqual(simulationNames, new string[] { "ExperimentFactor2003-11-01", "ExperimentFactor2003-12-20", "Simulation" }); Assert.AreEqual(simulationCreator.SimulationNamesBeingRun, new string[] { "ExperimentFactor2003-11-01", "ExperimentFactor2003-12-20", "Simulation" }); }
/// <summary> /// Document the specified model. /// </summary> /// <param name="tags">Document tags to add to.</param> /// <param name="modelToDocument">The model to document.</param> private void DocumentModel(List <AutoDocumentation.ITag> tags, IModel modelToDocument) { var childParent = Apsim.Parent(modelToDocument, typeof(Simulation)); if (childParent == null || childParent is Simulations) { AutoDocumentation.DocumentModel(modelToDocument, tags, headingLevel: 1, indent: 0); } else { var clonedModel = Apsim.Clone(modelToDocument); try { explorerPresenter.ApsimXFile.Links.Resolve(clonedModel, true); AutoDocumentation.DocumentModel(clonedModel, tags, headingLevel: 1, indent: 0); } finally { explorerPresenter.ApsimXFile.Links.Unresolve(clonedModel, true); } } }
/// <summary> /// Create a specific simulation. /// </summary> public Simulation CreateSpecificSimulation(string name) { List <List <FactorValue> > allCombinations = AllCombinations(); Simulation baseSimulation = Apsim.Child(this, typeof(Simulation)) as Simulation; foreach (List <FactorValue> combination in allCombinations) { string newSimulationName = Name; foreach (FactorValue value in combination) { newSimulationName += value.Name; } if (newSimulationName == name) { Simulation newSimulation = Apsim.Clone(baseSimulation) as Simulation; newSimulation.Name = newSimulationName; newSimulation.Parent = null; Apsim.ParentAllChildren(newSimulation); // Connect events and links in our new simulation. foreach (Model child in Apsim.ChildrenRecursively(newSimulation)) { Apsim.CallEventHandler(child, "Loaded", null); } foreach (FactorValue value in combination) { value.ApplyToSimulation(newSimulation); } PushFactorsToReportModels(newSimulation, combination); return(newSimulation); } } return(null); }
/// <summary> /// Create a specific simulation. /// </summary> public Simulation CreateSpecificSimulation(string name) { List <List <FactorValue> > allCombinations = AllCombinations(); Simulation baseSimulation = Apsim.Child(this, typeof(Simulation)) as Simulation; Simulations parentSimulations = Apsim.Parent(this, typeof(Simulations)) as Simulations; foreach (List <FactorValue> combination in allCombinations) { string newSimulationName = Name; foreach (FactorValue value in combination) { newSimulationName += value.Name; } if (newSimulationName == name) { Simulation newSimulation = Apsim.Clone(baseSimulation) as Simulation; newSimulation.Name = newSimulationName; newSimulation.Parent = null; newSimulation.FileName = parentSimulations.FileName; Apsim.ParentAllChildren(newSimulation); // Make substitutions and issue "Loaded" event parentSimulations.MakeSubsAndLoad(newSimulation); foreach (FactorValue value in combination) { value.ApplyToSimulation(newSimulation); } PushFactorsToReportModels(newSimulation, combination); return(newSimulation); } } return(null); }
/// <summary> /// Create all simulations. /// </summary> public Simulation[] Create() { List <List <FactorValue> > allCombinations = AllCombinations(); Simulation baseSimulation = Apsim.Child(this, typeof(Simulation)) as Simulation; List <Simulation> simulations = new List <Simulation>(); foreach (List <FactorValue> combination in allCombinations) { string newSimulationName = Name; foreach (FactorValue value in combination) { newSimulationName += value.Name; } Simulation newSimulation = Apsim.Clone(baseSimulation) as Simulation; newSimulation.Name = newSimulationName; newSimulation.Parent = null; Apsim.ParentAllChildren(newSimulation); // Call OnLoaded in all models. foreach (Model child in Apsim.ChildrenRecursively(newSimulation)) { Apsim.CallEventHandler(child, "Loaded", null); } foreach (FactorValue value in combination) { value.ApplyToSimulation(newSimulation); } PushFactorsToReportModels(newSimulation, combination); simulations.Add(newSimulation); } return(simulations.ToArray()); }
/// <summary>Checks validity of soil water parameters</summary> /// <param name="soilToCheck">The soil to check.</param> /// <returns>Error messages.</returns> public static string Check(Soil soilToCheck) { const double min_sw = 0.0; const double specific_bd = 2.65; // (g/cc) string Msg = ""; var soil = Apsim.Clone(soilToCheck) as Soil; SoilStandardiser.Standardise(soil); foreach (var soilCrop in soilToCheck.Crops) { if (soilCrop != null) { double[] LL = soilCrop.LL; double[] KL = soilCrop.KL; double[] XF = soilCrop.XF; if (!MathUtilities.ValuesInArray(LL) || !MathUtilities.ValuesInArray(KL) || !MathUtilities.ValuesInArray(XF)) { Msg += "Values for LL, KL or XF are missing for crop " + soilCrop.Name + "\r\n"; } else { for (int layer = 0; layer != soil.Thickness.Length; layer++) { int RealLayerNumber = layer + 1; if (KL[layer] == MathUtilities.MissingValue) { Msg += soilCrop.Name + " KL value missing" + " in layer " + RealLayerNumber.ToString() + "\r\n"; } else if (MathUtilities.GreaterThan(KL[layer], 1, 3)) { Msg += soilCrop.Name + " KL value of " + KL[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is greater than 1" + "\r\n"; } if (XF[layer] == MathUtilities.MissingValue) { Msg += soilCrop.Name + " XF value missing" + " in layer " + RealLayerNumber.ToString() + "\r\n"; } else if (MathUtilities.GreaterThan(XF[layer], 1, 3)) { Msg += soilCrop.Name + " XF value of " + XF[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is greater than 1" + "\r\n"; } if (LL[layer] == MathUtilities.MissingValue) { Msg += soilCrop.Name + " LL value missing" + " in layer " + RealLayerNumber.ToString() + "\r\n"; } else if (MathUtilities.LessThan(LL[layer], soil.AirDry[layer], 3)) { Msg += soilCrop.Name + " LL of " + LL[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is below air dry value of " + soil.AirDry[layer].ToString("f3") + "\r\n"; } else if (MathUtilities.GreaterThan(LL[layer], soil.DUL[layer], 3)) { Msg += soilCrop.Name + " LL of " + LL[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is above drained upper limit of " + soil.DUL[layer].ToString("f3") + "\r\n"; } } } } } // Check other profile variables. for (int layer = 0; layer != soil.Thickness.Length; layer++) { double max_sw = MathUtilities.Round(1.0 - soil.BD[layer] / specific_bd, 3); int RealLayerNumber = layer + 1; if (soil.AirDry[layer] == MathUtilities.MissingValue) { Msg += " Air dry value missing" + " in layer " + RealLayerNumber.ToString() + "\r\n"; } else if (MathUtilities.LessThan(soil.AirDry[layer], min_sw, 3)) { Msg += " Air dry lower limit of " + soil.AirDry[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is below acceptable value of " + min_sw.ToString("f3") + "\r\n"; } if (soil.LL15[layer] == MathUtilities.MissingValue) { Msg += "15 bar lower limit value missing" + " in layer " + RealLayerNumber.ToString() + "\r\n"; } else if (MathUtilities.LessThan(soil.LL15[layer], soil.AirDry[layer], 3)) { Msg += "15 bar lower limit of " + soil.LL15[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is below air dry value of " + soil.AirDry[layer].ToString("f3") + "\r\n"; } if (soil.DUL[layer] == MathUtilities.MissingValue) { Msg += "Drained upper limit value missing" + " in layer " + RealLayerNumber.ToString() + "\r\n"; } else if (MathUtilities.LessThan(soil.DUL[layer], soil.LL15[layer], 3)) { Msg += "Drained upper limit of " + soil.DUL[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is at or below lower limit of " + soil.LL15[layer].ToString("f3") + "\r\n"; } if (soil.SAT[layer] == MathUtilities.MissingValue) { Msg += "Saturation value missing" + " in layer " + RealLayerNumber.ToString() + "\r\n"; } else if (MathUtilities.LessThan(soil.SAT[layer], soil.DUL[layer], 3)) { Msg += "Saturation of " + soil.SAT[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is at or below drained upper limit of " + soil.DUL[layer].ToString("f3") + "\r\n"; } else if (MathUtilities.GreaterThan(soil.SAT[layer], max_sw, 3)) { double max_bd = (1.0 - soil.SAT[layer]) * specific_bd; Msg += "Saturation of " + soil.SAT[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is above acceptable value of " + max_sw.ToString("f3") + ". You must adjust bulk density to below " + max_bd.ToString("f3") + " OR saturation to below " + max_sw.ToString("f3") + "\r\n"; } if (soil.BD[layer] == MathUtilities.MissingValue) { Msg += "BD value missing" + " in layer " + RealLayerNumber.ToString() + "\r\n"; } else if (MathUtilities.GreaterThan(soil.BD[layer], 2.65, 3)) { Msg += "BD value of " + soil.BD[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is greater than the theoretical maximum of 2.65" + "\r\n"; } } if (soil.Initial.OC.Length == 0) { throw new Exception("Cannot find OC values in soil"); } for (int layer = 0; layer != soil.Thickness.Length; layer++) { int RealLayerNumber = layer + 1; if (soil.Initial.OC[layer] == MathUtilities.MissingValue) { Msg += "OC value missing" + " in layer " + RealLayerNumber.ToString() + "\r\n"; } else if (MathUtilities.LessThan(soil.Initial.OC[layer], 0.01, 3)) { Msg += "OC value of " + soil.Initial.OC[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is less than 0.01" + "\r\n"; } if (soil.Initial.PH[layer] == MathUtilities.MissingValue) { Msg += "PH value missing" + " in layer " + RealLayerNumber.ToString() + "\r\n"; } else if (MathUtilities.LessThan(soil.Initial.PH[layer], 3.5, 3)) { Msg += "PH value of " + soil.Initial.PH[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is less than 3.5" + "\r\n"; } else if (MathUtilities.GreaterThan(soil.Initial.PH[layer], 11, 3)) { Msg += "PH value of " + soil.Initial.PH[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is greater than 11" + "\r\n"; } } if (!MathUtilities.ValuesInArray(soil.Initial.SW)) { Msg += "No starting soil water values found.\r\n"; } else { for (int layer = 0; layer != soil.Thickness.Length; layer++) { int RealLayerNumber = layer + 1; if (soil.Initial.SW[layer] == MathUtilities.MissingValue) { Msg += "Soil water value missing" + " in layer " + RealLayerNumber.ToString() + "\r\n"; } else if (MathUtilities.GreaterThan(soil.Initial.SW[layer], soil.SAT[layer], 3)) { Msg += "Soil water of " + soil.Initial.SW[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is above saturation of " + soil.SAT[layer].ToString("f3") + "\r\n"; } else if (MathUtilities.LessThan(soil.Initial.SW[layer], soil.AirDry[layer], 3)) { Msg += "Soil water of " + soil.Initial.SW[layer].ToString("f3") + " in layer " + RealLayerNumber.ToString() + " is below air-dry value of " + soil.AirDry[layer].ToString("f3") + "\r\n"; } } } if (!MathUtilities.ValuesInArray(soil.Initial.NO3N)) { Msg += "No starting NO3 values found.\r\n"; } if (!MathUtilities.ValuesInArray(soil.Initial.NH4N)) { Msg += "No starting NH4 values found.\r\n"; } return(Msg); }
/// <summary> /// Convert the simulation decription to a simulation. /// path. /// </summary> public Simulation ToSimulation() { try { AddReplacements(); Simulation newSimulation; if (doClone) { newSimulation = Apsim.Clone(baseSimulation) as Simulation; // If there is a child DataStore // remove it and use the same one as in baseSimulation. This is // because we want to use the same DataStore for all simulations // and not have a separate DataStore instance for each simulation. Model goodStorage; if (topLevelModel == null) { goodStorage = Apsim.Child(newSimulation, typeof(IDataStore)) as Model; } else { goodStorage = Apsim.Child(topLevelModel, typeof(IDataStore)) as Model; } var unwantedStorage = Apsim.Child(newSimulation, typeof(IDataStore)) as Model; if (unwantedStorage != null) { Apsim.Delete(unwantedStorage); } if (goodStorage != null) { newSimulation.Children.Add(goodStorage); } } else { newSimulation = baseSimulation; } if (Name == null) { newSimulation.Name = baseSimulation.Name; } else { newSimulation.Name = Name; } newSimulation.Parent = null; Apsim.ParentAllChildren(newSimulation); replacementsToApply.ForEach(r => r.Replace(newSimulation)); // Give the simulation the descriptors. newSimulation.Descriptors = Descriptors; return(newSimulation); } catch (Exception err) { var message = "Error in file: " + baseSimulation.FileName + " Simulation: " + Name; throw new Exception(message, err); } }
public void Run() { while (PipeUtilities.GetObjectFromPipe(pipeRead) is IRunnable runnable) { job = runnable; Exception error = null; StorageViaSockets storage = new StorageViaSockets(); try { if (runnable is Simulation sim) { storage = new StorageViaSockets(sim.FileName); // Remove existing DataStore sim.Children.RemoveAll(model => model is Models.Storage.DataStore); // Add in a socket datastore to satisfy links. sim.Children.Add(storage); if (sim.Services != null) { sim.Services.RemoveAll(s => s is Models.Storage.IDataStore); sim.Services.Add(storage); } // Initialise the model so that Simulation.Run doesn't call OnCreated. // We don't need to recompile any manager scripts and a simulation // should be ready to run at this point following a binary // deserialisation. sim.ParentAllDescendants(); } else if (runnable is IModel model) { IDataStore oldStorage = model.FindInScope <IDataStore>(); if (oldStorage != null) { storage = new StorageViaSockets(oldStorage.FileName); } storage.Parent = model; storage.Children.AddRange(model.Children.OfType <DataStore>().SelectMany(d => d.Children).Select(m => Apsim.Clone(m))); model.Children.RemoveAll(m => m is DataStore); model.Children.Add(storage); model.ParentAllDescendants(); } // Initiate progress updates. lock (timerLock) timer.Start(); // Run the job. runnable.Run(new CancellationTokenSource()); // Stop progress updates. lock (timerLock) timer.Stop(); } catch (Exception err) { error = err; } // Signal end of job. lock (timerLock) { PipeUtilities.SendObjectToPipe(pipeWrite, new JobOutput { ErrorMessage = error, ReportData = storage.reportDataThatNeedsToBeWritten, DataTables = storage.dataTablesThatNeedToBeWritten }); pipeWrite.WaitForPipeDrain(); } } }
/// <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; } }
public void TestTablesModified() { IModel sim1 = new Simulation() { Name = "sim1", Children = new List <IModel>() { new Report() { Name = "Report1", VariableNames = new[] { "[Clock].Today" }, EventNames = new[] { "[Clock].DoReport" }, }, new MockSummary(), new Clock() { StartDate = new DateTime(2020, 1, 1), EndDate = new DateTime(2020, 1, 2), }, } }; IModel sim2 = Apsim.Clone(sim1); sim2.Name = "sim2"; sim2.Children[0].Name = "Report2"; TestPostSim testPostSim = new TestPostSim(); sim1.Children.Add(testPostSim); Simulations sims = Simulations.Create(new[] { sim1, sim2, new DataStore() }); Utilities.InitialiseModel(sims); Runner runner = new Runner(sims, simulationNamesToRun: new[] { "sim1" }); List <Exception> errors = runner.Run(); if (errors != null && errors.Count > 0) { throw errors[0]; } List <string> tablesMod = new List <string>() { "_Factors", "Report1", "_Simulations", "_Checkpoints", }; Assert.AreEqual(tablesMod.OrderBy(x => x), testPostSim.TablesModified.OrderBy(x => x)); runner = new Runner(sims, simulationNamesToRun: new[] { "sim2" }); errors = runner.Run(); if (errors != null && errors.Count > 0) { throw errors[0]; } tablesMod = new List <string>() { "_Factors", "Report2", "_Simulations", "_Checkpoints", }; Assert.AreEqual(tablesMod.OrderBy(x => x), testPostSim.TablesModified.OrderBy(x => x)); // Now run both sims runner = new Runner(sims); errors = runner.Run(); if (errors != null && errors.Count > 0) { throw errors[0]; } tablesMod = new List <string>() { "_Factors", "Report2", "Report1", "_Simulations", "_Checkpoints", }; Assert.AreEqual(tablesMod.OrderBy(x => x), testPostSim.TablesModified.OrderBy(x => x)); }