/// <summary> /// Create a simulations model /// </summary> /// <param name="children">The child models</param> public static Simulations Create(IEnumerable <IModel> children) { Simulations newSimulations = new Core.Simulations(); newSimulations.Children.AddRange(children.Cast <Model>()); // Parent all models. newSimulations.Parent = null; Apsim.ParentAllChildren(newSimulations); // Call OnCreated in all models. Apsim.ChildrenRecursively(newSimulations).ForEach(m => m.OnCreated()); return(newSimulations); }
/// <summary> /// /// </summary> /// <param name="rootNode"></param> /// <param name="recurse">Recurse through all child models?</param> public void Resolve(IModel rootNode, bool recurse = true) { if (recurse) { List <IModel> allModels = Apsim.ChildrenRecursively(rootNode); foreach (IModel modelNode in allModels) { ResolveInternal(modelNode, null); } } else { ResolveInternal(rootNode, null); } }
/// <summary> /// Call the specified event on the specified model and all child models. /// </summary> /// <param name="eventName">The name of the event</param> /// <param name="args">The event arguments. Can be null</param> internal void Publish(string eventName, object[] args) { List <IModel> allModels = new List <IModel>(); allModels.Add(relativeTo); allModels.AddRange(Apsim.ChildrenRecursively(relativeTo)); List <Events.Subscriber> subscribers = Events.Subscriber.FindAll(allModels); List <Subscriber> matches = subscribers.FindAll(subscriber => subscriber.Name == eventName && allModels.Contains(subscriber.Model as IModel)); foreach (Subscriber subscriber in matches) { subscriber.Invoke(args); } }
/// <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 }); }
/// <summary> /// Return all models within scope of the specified relative model. /// </summary> /// <param name="relativeTo">The model calling this method</param> /// <returns>The found models or an empty array if not found.</returns> public Model[] FindAll(Model relativeTo) { // Look in cache first. string cacheKey = "ALLINSCOPE"; object value = GetFromCache(cacheKey, relativeTo); if (value != null) { return(value as Model[]); } // Get all children first. List <Model> modelsInScope = new List <Model>(); foreach (Model child in Apsim.ChildrenRecursively(relativeTo)) { modelsInScope.Add(child); } // Add relativeTo. //modelsInScope.Add(relativeTo); // Get siblings and parents siblings and parents, parents siblings etc // until we reach a Simulations or Simulation model. if (!(relativeTo is Simulations)) { Model relativeToParent = relativeTo; do { foreach (IModel model in Apsim.Siblings(relativeToParent)) { modelsInScope.Add(model as Model); } relativeToParent = relativeToParent.Parent as Model; // Add in the top level model that we stopped on. if (relativeToParent != null) { modelsInScope.Add(relativeToParent); } }while (relativeToParent != null && !(relativeToParent is Simulation) && !(relativeToParent is Simulations)); } // Add the in scope models to the cache and return them AddToCache(cacheKey, relativeTo, modelsInScope.ToArray()); return(modelsInScope.ToArray()); }
/// <summary>Create a simulations object by reading the specified filename</summary> /// <param name="FileName">Name of the file.</param> /// <returns></returns> /// <exception cref="System.Exception">Simulations.Read() failed. Invalid simulation file.\n</exception> public static Simulations Read(string FileName) { // Run the converter. Converter.ConvertToLatestVersion(FileName); // Deserialise Simulations simulations = XmlUtilities.Deserialise(FileName, Assembly.GetExecutingAssembly()) as Simulations; if (simulations != null) { // Set the filename simulations.FileName = FileName; simulations.SetFileNameInAllSimulations(); // Call the OnDeserialised method in each model. object[] args = new object[] { true }; foreach (Model model in Apsim.ChildrenRecursively(simulations)) { Apsim.CallEventHandler(model, "Deserialised", args); } // Parent all models. simulations.Parent = null; Apsim.ParentAllChildren(simulations); // Call OnLoaded in all models. simulations.LoadErrors = new List <Exception>(); foreach (Model child in Apsim.ChildrenRecursively(simulations)) { try { Apsim.CallEventHandler(child, "Loaded", null); } catch (ApsimXException err) { simulations.LoadErrors.Add(err); } catch (Exception err) { err.Source = child.Name; simulations.LoadErrors.Add(err); } } } return(simulations); }
/// <summary> /// Set to null all link fields in the specified model. /// </summary> /// <param name="model">The model to look through for links</param> public void Unresolve(IModel model) { foreach (IModel modelNode in Apsim.ChildrenRecursively(model)) { // Go looking for private [Link]s foreach (IVariable declaration in GetAllDeclarations(model, model.GetType(), BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public)) { LinkAttribute link = declaration.GetAttribute(typeof(LinkAttribute)) as LinkAttribute; if (link != null) { declaration.Value = null; } } } }
/// <summary>Look through all models. For each simulation found set the filename.</summary> private void SetFileNameInAllSimulations() { foreach (Model child in Apsim.ChildrenRecursively(this)) { if (child is Simulation) { (child as Simulation).FileName = FileName; } else if (child is DataStore) { DataStore storage = child as DataStore; storage.Close(); storage.UpdateFileName(); storage.Open(); } } }
/// <summary> /// Set to null all link fields in the specified model. /// </summary> /// <param name="model">The model to look through for links</param> public void Unresolve(IModel model) { foreach (IModel modelNode in Apsim.ChildrenRecursively(model)) { // Go looking for private [Link]s foreach (FieldInfo field in ReflectionUtilities.GetAllFields( model.GetType(), BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public)) { LinkAttribute link = ReflectionUtilities.GetAttribute(field, typeof(LinkAttribute), false) as LinkAttribute; if (link != null) { field.SetValue(model, null); } } } }
/// <summary>Connect all events in the specified simulation.</summary> public void ConnectEvents() { // Get a complete list of all models in simulation (including the simulation itself). List <IModel> allModels = new List <IModel>(); allModels.Add(relativeTo); allModels.AddRange(Apsim.ChildrenRecursively(relativeTo)); List <Publisher> publishers = Publisher.FindAll(allModels); // Connect publishers to subscribers. foreach (Publisher publisher in publishers) { var subscribers = Subscriber.FindAll(publisher.Name, publisher.Model as IModel, scope); subscribers.ForEach(subscriber => publisher.ConnectSubscriber(subscriber)); } }
/// <summary>Determine the list of jobs to run</summary> private void FindListOfModelsToRun() { // Get a list of all models we're going to run. modelsToRun = Apsim.ChildrenRecursively(relativeTo, typeof(ISimulationGenerator)).Cast <ISimulationGenerator>().ToList(); if (relativeTo is ISimulationGenerator) { modelsToRun.Add(relativeTo as ISimulationGenerator); } // For each model, resolve any links. Simulations sims = Apsim.Parent(relativeTo, typeof(Simulations)) as Simulations; modelsToRun.ForEach(model => sims.Links.Resolve(model)); // For each model, get a list of simulation names. SimulationNamesBeingRun = new List <string>(); modelsToRun.ForEach(model => SimulationNamesBeingRun.AddRange(model.GetSimulationNames(false))); }
/// <summary>Gets a list of factors</summary> public List <ISimulationGeneratorFactors> GetFactors() { List <ISimulationGeneratorFactors> factors = new List <ISimulationGeneratorFactors>(); // Add top level simulation zone. This is needed if Report is in top level. factors.Add(new SimulationGeneratorFactors(new string[] { "SimulationName", "Zone" }, new string[] { Name, Name }, "Simulation", Name)); foreach (Zone zone in Apsim.ChildrenRecursively(this, typeof(Zone))) { var factor = new SimulationGeneratorFactors(new string[] { "SimulationName", "Zone" }, new string[] { Name, zone.Name }, "Simulation", Name); factors.Add(factor); factor.AddFactor("Zone", zone.Name); } return(factors); }
/// <summary> /// /// </summary> /// <param name="rootNode"></param> /// <param name="recurse">Recurse through all child models?</param> /// <param name="allLinks">Unresolve all links or just the non child links?</param> public void Resolve(IModel rootNode, bool allLinks, bool recurse = true) { if (recurse) { List <IModel> allModels = new List <IModel>() { rootNode }; allModels.AddRange(Apsim.ChildrenRecursively(rootNode)); foreach (IModel modelNode in allModels) { ResolveInternal(modelNode, null); } } else { ResolveInternal(rootNode, null); } }
/// <summary>Connect all events in the specified simulation.</summary> public void ConnectEvents() { // Get a complete list of all models in simulation (including the simulation itself). List <IModel> allModels = new List <IModel>(); allModels.Add(relativeTo); allModels.AddRange(Apsim.ChildrenRecursively(relativeTo)); List <Events.Publisher> publishers = Events.Publisher.FindAll(allModels); List <Events.Subscriber> subscribers = Events.Subscriber.FindAll(allModels); // Connect publishers to subscribers. Dictionary <IModel, List <Subscriber> > cache = new Dictionary <IModel, List <Subscriber> >(); foreach (Events.Publisher publisher in publishers) { ConnectPublisherToScriber(publisher, FilterSubscribersInScope(publisher, cache, scope, subscribers)); } }
/// <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); // 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 Simulation clonedSimulation = Apsim.Clone(simulation) as Simulation; // Make any substitutions. MakeSubstitutions(new Simulation[] { clonedSimulation }); // Now use the path to get the model we want to document. modelToDocument = Apsim.Get(clonedSimulation, pathOfModelToDocument) as IModel; // resolve all links in cloned simulation. Apsim.ResolveLinks(clonedSimulation); foreach (Model child in Apsim.ChildrenRecursively(clonedSimulation)) { Apsim.ResolveLinks(child); } // Document the model. modelToDocument.Document(tags, headingLevel, 0); // Unresolve links. Apsim.UnresolveLinks(clonedSimulation); foreach (Model child in Apsim.ChildrenRecursively(clonedSimulation)) { Apsim.UnresolveLinks(child); } } }
/// <summary>Write the specified simulation set to the specified 'stream'</summary> /// <param name="stream">The stream.</param> public void Write(TextWriter stream) { object[] args = new object[] { true }; foreach (Model model in Apsim.ChildrenRecursively(this)) { Apsim.CallEventHandler(model, "Serialising", args); } try { stream.Write(XmlUtilities.Serialise(this, true)); } finally { foreach (Model model in Apsim.ChildrenRecursively(this)) { Apsim.CallEventHandler(model, "Serialised", args); } } }
/// <summary>Cleanup after the run.</summary> public void CleanupRun() { _IsRunning = false; if (Completed != null) { Completed.Invoke(this, null); } Apsim.DisconnectEvents(this); Apsim.UnresolveLinks(this); foreach (Model child in Apsim.ChildrenRecursively(this)) { Apsim.DisconnectEvents(child); Apsim.UnresolveLinks(child); } timer.Stop(); Console.WriteLine("Completed: " + Path.GetFileNameWithoutExtension(FileName) + " - " + Name + " [" + timer.Elapsed.TotalSeconds.ToString("#.00") + " sec]"); }
/// <summary>Find all simulations under the specified parent model.</summary> /// <param name="parent">The parent.</param> /// <returns></returns> public static Simulation[] FindAllSimulationsToRun(Model parent) { List <Simulation> simulations = new List <Simulation>(); if (parent is Experiment) { simulations.AddRange((parent as Experiment).Create()); } else if (parent is Simulation) { Simulation clonedSim = Apsim.Clone(parent) as Simulation; CallOnLoaded(clonedSim); simulations.Add(clonedSim); } else { // Look for simulations. foreach (Model model in Apsim.ChildrenRecursively(parent)) { if (model is Experiment) { simulations.AddRange((model as Experiment).Create()); } else if (model is Simulation && !(model.Parent is Experiment)) { Simulation clonedSim = Apsim.Clone(model) as Simulation; CallOnLoaded(clonedSim); simulations.Add(clonedSim); } } } // Make sure each simulation has it's filename set correctly. foreach (Simulation simulation in simulations) { if (simulation.FileName == null) { simulation.FileName = RootSimulations(parent).FileName; } } return(simulations.ToArray()); }
/// <summary>Startup the run.</summary> public void StartRun() { timer = new Stopwatch(); timer.Start(); Apsim.ConnectEvents(this); Apsim.ResolveLinks(this); foreach (Model child in Apsim.ChildrenRecursively(this)) { Apsim.ConnectEvents(child); Apsim.ResolveLinks(child); } _IsRunning = true; Locater.Clear(); if (Commencing != null) { Commencing.Invoke(this, new EventArgs()); } }
/// <summary>Startup the run.</summary> public void StartRun() { timer = new Stopwatch(); timer.Start(); Apsim.ConnectEvents(this); Apsim.ResolveLinks(this); foreach (Model child in Apsim.ChildrenRecursively(this)) { Apsim.ConnectEvents(child); Apsim.ResolveLinks(child); } _IsRunning = true; Locater.Clear(); Console.WriteLine("Running: " + Path.GetFileNameWithoutExtension(FileName) + " - " + Name); if (Commencing != null) { Commencing.Invoke(this, new EventArgs()); } }
/// <summary>Connect all events in the specified simulation.</summary> internal void ConnectEvents() { // Get a complete list of all models in simulation (including the simulation itself). List <IModel> allModels = new List <IModel>(); allModels.Add(simulation); allModels.AddRange(Apsim.ChildrenRecursively(simulation)); if (publishers == null) { publishers = Events.Publisher.FindAll(allModels); } if (subscribers == null) { subscribers = Events.Subscriber.FindAll(allModels); } // Connect publishers to subscribers. foreach (Events.Publisher publisher in publishers) { ConnectPublisherToScriber(publisher, FilterSubscribersInScope(publisher)); } }
/// <summary>Connect all events in the specified simulation.</summary> public void ConnectEvents() { // Get a complete list of all models in simulation (including the simulation itself). List <IModel> allModels = new List <IModel>(); allModels.Add(relativeTo); allModels.AddRange(Apsim.ChildrenRecursively(relativeTo)); var publishers = Publisher.FindAll(allModels); var subscribers = Subscriber.FindAll(allModels); // Connect publishers to subscribers. foreach (Publisher publisher in publishers) { var modelsInScope = scope.FindAll(publisher.Model as IModel).ToList(); var subscribersForEvent = subscribers.Where(s => modelsInScope.Contains(s.Model) && s.Name.Equals(publisher.Name, StringComparison.InvariantCultureIgnoreCase)); //var subscribers = Subscriber.FindAll(publisher.Name, publisher.Model as IModel, scope); foreach (var subscriber in subscribersForEvent) { publisher.ConnectSubscriber(subscriber); } } }
/// <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 }); }
/// <summary> /// /// </summary> /// <param name="rootNode"></param> /// <param name="recurse">Recurse through all child models?</param> /// <param name="allLinks">Unresolve all links or just the non child links?</param> public void Resolve(IModel rootNode, bool allLinks, bool recurse = true) { var scope = new ScopingRules(); if (recurse) { List <IModel> allModels = new List <IModel>() { rootNode }; allModels.AddRange(Apsim.ChildrenRecursively(rootNode)); foreach (IModel modelNode in allModels) { if (modelNode.Enabled) { ResolveInternal(modelNode, scope); } } } else { ResolveInternal(rootNode, scope); } }
/// <summary> /// Set to null all link fields in the specified model. /// </summary> /// <param name="model">The model to look through for links</param> /// <param name="allLinks">Unresolve all links or just the non child links?</param> public void Unresolve(IModel model, bool allLinks) { List <IModel> allModels = new List <IModel>() { model }; allModels.AddRange(Apsim.ChildrenRecursively(model)); foreach (IModel modelNode in allModels) { // Go looking for private [Link]s foreach (IVariable declaration in GetAllDeclarations(modelNode, modelNode.GetType(), BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public, allLinks)) { LinkAttribute link = declaration.GetAttribute(typeof(LinkAttribute)) as LinkAttribute; if (link != null) { declaration.Value = null; } } } }
/// <summary> /// Runs the simulation on the current thread and waits for the simulation /// to complete before returning to caller. Simulation is NOT cloned before /// running. Use instance of Runner to get more options for running a /// simulation or groups of simulations. /// </summary> /// <param name="cancelToken">Is cancellation pending?</param> public void Run(CancellationTokenSource cancelToken = null) { // If the cancelToken is null then give it a default one. This can happen // when called from the unit tests. if (cancelToken == null) { cancelToken = new CancellationTokenSource(); } // Remove disabled models. RemoveDisabledModels(this); // If this simulation was not created from deserialisation then we need // to parent all child models correctly and call OnCreated for each model. bool hasBeenDeserialised = Children.Count > 0 && Children[0].Parent == this; if (!hasBeenDeserialised) { // Parent all models. Apsim.ParentAllChildren(this); // Call OnCreated in all models. Apsim.ChildrenRecursively(this).ForEach(m => m.OnCreated()); } if (Services == null || Services.Count < 1) { Services = new List <object>(); IDataStore storage = Apsim.Find(this, typeof(IDataStore)) as IDataStore; if (storage != null) { Services.Add(Apsim.Find(this, typeof(IDataStore))); } } var links = new Links(Services); var events = new Events(this); try { // Connect all events. events.ConnectEvents(); // Resolve all links links.Resolve(this, true); // Invoke our commencing event to let all models know we're about to start. Commencing?.Invoke(this, new EventArgs()); // Begin running the simulation. DoCommence?.Invoke(this, new CommenceArgs() { CancelToken = cancelToken }); } catch (Exception err) { // Exception occurred. Write error to summary. string errorMessage = "ERROR in file: " + FileName + Environment.NewLine + "Simulation name: " + Name + Environment.NewLine; errorMessage += err.ToString(); summary?.WriteError(this, errorMessage); // Rethrow exception throw new Exception(errorMessage, err); } finally { // Signal that the simulation is complete. Completed?.Invoke(this, new EventArgs()); // Disconnect our events. events.DisconnectEvents(); // Unresolve all links. links.Unresolve(this, true); } }
/// <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 Simulation clonedSimulation = Apsim.Clone(simulation) as Simulation; // Make any substitutions. MakeSubstitutions(clonedSimulation); // 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); modelToDocument.IncludeInDocumentation = true; foreach (IModel child in Apsim.ChildrenRecursively(modelToDocument)) { child.IncludeInDocumentation = true; } // Document the model. AutoDocumentation.DocumentModel(modelToDocument, tags, headingLevel, 0, documentAllChildren: true); // Unresolve links. Links.Unresolve(clonedSimulation); } } }
/// <summary>Run the jobs.</summary> /// <param name="sender"></param> /// <param name="e"></param> public void Run(object sender, System.ComponentModel.DoWorkEventArgs e) { JobManager jobManager = e.Argument as JobManager; List <JobManager.IRunnable> jobs = new List <JobManager.IRunnable>(); DataStore store = Apsim.Child(simulations, typeof(DataStore)) as DataStore; Simulation[] simulationsToRun; if (model is Simulations) { // As we are going to run all simulations, we can delete all tables in the DataStore. This // will clean up order of columns in the tables and removed unused ones. store.DeleteAllTables(); simulationsToRun = Simulations.FindAllSimulationsToRun(simulations); } else { store.RemoveUnwantedSimulations(simulations); if (model is Simulation) { if (model.Parent == null) { // model is already a cloned simulation, probably from user running a single // simulation from an experiment. simulationsToRun = new Simulation[1] { model as Simulation }; } else { simulationsToRun = new Simulation[1] { Apsim.Clone(model as Simulation) as Simulation }; Simulations.CallOnLoaded(simulationsToRun[0]); } } else { simulationsToRun = Simulations.FindAllSimulationsToRun(model); } } store.Disconnect(); simulations.MakeSubstitutions(simulationsToRun); foreach (Simulation simulation in simulationsToRun) { jobs.Add(simulation); jobManager.AddJob(simulation); } // Wait until all our jobs are all finished. while (AreSomeJobsRunning(jobs)) { Thread.Sleep(200); } // Collect all error messages. foreach (Simulation job in simulationsToRun) { if (job.ErrorMessage != null) { ErrorMessage += job.ErrorMessage + Environment.NewLine; } } // <summary>Call the all completed event in all models.</summary> object[] args = new object[] { this, new EventArgs() }; foreach (Model childModel in Apsim.ChildrenRecursively(simulations)) { try { Apsim.CallEventHandler(childModel, "AllCompleted", args); } catch (Exception err) { ErrorMessage += "Error in file: " + simulations.FileName + Environment.NewLine; ErrorMessage += err.ToString() + Environment.NewLine + Environment.NewLine; } } if (ErrorMessage != null) { throw new Exception(ErrorMessage); } }