/// <summary>Adds a new model (as specified by the xml node) to the specified parent.</summary> /// <param name="parent">The parent to add the model to</param> /// <param name="node">The XML representing the new model</param> /// <returns>The newly created model.</returns> public static IModel Add(IModel parent, XmlNode node) { IModel modelToAdd = XmlUtilities.Deserialise(node, Assembly.GetExecutingAssembly()) as Model; // Call deserialised Events events = new Events(modelToAdd); object[] args = new object[] { true }; events.Publish("Deserialised", args); // Correctly parent all models. Add(parent, modelToAdd); // Ensure the model name is valid. Apsim.EnsureNameIsUnique(modelToAdd); // Call OnLoaded LoadedEventArgs loadedArgs = new LoadedEventArgs(); events.Publish("Loaded", new object[] { modelToAdd, loadedArgs }); Locator(parent).Clear(); return(modelToAdd); }
/// <summary>Create a simulations object by reading the specified filename</summary> /// <param name="node">The node.</param> /// <returns></returns> /// <exception cref="System.Exception">Simulations.Read() failed. Invalid simulation file.\n</exception> public static Simulations Read(XmlNode node) { // Run the converter. APSIMFileConverter.ConvertToLatestVersion(node, null); // Deserialise Simulations simulations = XmlUtilities.Deserialise(node, Assembly.GetExecutingAssembly()) as Simulations; if (simulations != null) { // Set the filename simulations.SetFileNameInAllSimulations(); // Call the OnSerialised method in each model. object[] args = new object[] { true }; Events events = new Events(simulations); events.Publish("Deserialised", args); // Parent all models. simulations.Parent = null; Apsim.ParentAllChildren(simulations); events.Publish("Loaded", null); } else { throw new Exception("Simulations.Read() failed. Invalid simulation file.\n"); } return(simulations); }
/// <summary>Make model substitutions if necessary.</summary> /// <param name="model">The model to make substitutions in.</param> public void MakeSubstitutions(IModel model) { IModel replacements = Apsim.Child(this, "Replacements"); if (replacements != null) { foreach (IModel replacement in replacements.Children) { foreach (IModel match in Apsim.FindAll(model)) { if (!(match is Simulation) && match.Name.Equals(replacement.Name, StringComparison.InvariantCultureIgnoreCase)) { // Do replacement. 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; match.Parent.Children.Remove(match as Model); // If we're doing substitutions for an entire Simulation, // the Loaded event will be issued later. Otherwise, issue one now if (!(model is Simulation)) { Events events = new Events(newModel); LoadedEventArgs loadedArgs = new LoadedEventArgs(); events.Publish("Loaded", new object[] { newModel, loadedArgs }); } } } } } }
/// <summary>Make model substitutions if necessary.</summary> /// <param name="model">The model to make substitutions in.</param> public void MakeSubstitutions(IModel model) { IModel replacements = Apsim.Child(this, "Replacements"); if (replacements != null) { foreach (IModel replacement in replacements.Children) { foreach (IModel match in Apsim.FindAll(model)) { if (!(match is Simulation) && match.Name.Equals(replacement.Name, StringComparison.InvariantCultureIgnoreCase)) { // Do replacement. 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; match.Parent.Children.Remove(match as Model); Events events = new Events(newModel); events.Publish("Loaded", null); } } } } }
/// <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 }; Events events = new Events(this); events.Publish("Serialising", args); try { stream.Write(XmlUtilities.Serialise(this, true)); } finally { events.Publish("Serialised", args); } }
/// <summary> /// Perform model substitutions, if necessary, then issue a "Loaded" event /// </summary> public void MakeSubsAndLoad(Simulation simulation) { MakeSubstitutions(simulation); // Call OnLoaded in all models. Events events = new Events(simulation); LoadedEventArgs loadedArgs = new LoadedEventArgs(); events.Publish("Loaded", new object[] { simulation, loadedArgs }); }
/// <summary> /// Serialize the model to a string and return the string. /// </summary> /// <param name="model">The model to serialize</param> /// <returns>The string version of the model</returns> public static string Serialise(IModel model) { Events events = new Events(model); // Let all models know that we're about to serialise. object[] args = new object[] { true }; events.Publish("Serialising", args); // Do the serialisation StringWriter writer = new StringWriter(); writer.Write(XmlUtilities.Serialise(model, false)); // Let all models know that we have completed serialisation. events.Publish("Serialised", args); // Set the clipboard text. return(writer.ToString()); }
/// <summary>Gets the next job to run</summary> public Simulation NextSimulationToRun(bool doFullFactorial = true) { if (Parent is ISimulationGenerator || hasRun) { return(null); } hasRun = true; Simulation simulationToRun; if (this.Parent == null) { simulationToRun = this; } else { Simulations simulationEngine = Apsim.Parent(this, typeof(Simulations)) as Simulations; simulationToRun = Apsim.Clone(this) as Simulation; // We are breaking.NET naming rules with our manager scripts.All our manager scripts are class // Script in the Models namespace.This is OK until we do a clone(binary serialise/deserialise). // When this happens, the serialisation engine seems to choose the first assembly it can find // that has the 'right' code.It seems that if the script c# is close to an existing assembly then // it chooses that assembly. In the attached .apsimx, it chooses the wrong temporary assembly for // SowingRule2. It chooses SowingRule assembly even though the script for the 2 manager files is // different. I'm not sure how to fix this yet. A brute force way is to recompile all manager // scripts after cloning. // https://github.com/APSIMInitiative/ApsimX/issues/2603 Events events = new Events(simulationToRun); LoadedEventArgs loadedArgs = new LoadedEventArgs(); events.Publish("Loaded", new object[] { simulationToRun, loadedArgs }); simulationEngine.MakeSubstitutions(simulationToRun); } return(simulationToRun); }
/// <summary> /// Prepare the simulation for running. /// </summary> public void Prepare() { // Remove disabled models. RemoveDisabledModels(this); // Standardise the soil. var soils = FindAllDescendants <Soils.Soil>(); foreach (Soils.Soil soil in soils) { SoilStandardiser.Standardise(soil); } // 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. this.ParentAllDescendants(); // Call OnCreated in all models. foreach (IModel model in FindAllDescendants().ToList()) { model.OnCreated(); } } // Call OnPreLink in all models. // Note the ToList(). This is important because some models can // add/remove models from the simulations tree in their OnPreLink() // method, and FindAllDescendants() is lazy. FindAllDescendants().ToList().ForEach(model => model.OnPreLink()); if (Services == null || Services.Count < 1) { var simulations = FindAncestor <Simulations>(); if (simulations != null) { Services = simulations.GetServices(); } else { Services = new List <object>(); IDataStore storage = this.FindInScope <IDataStore>(); if (storage != null) { Services.Add(this.FindInScope <IDataStore>()); } Services.Add(new ScriptCompiler()); } } var links = new Links(Services); var events = new Events(this); try { // Connect all events. events.ConnectEvents(); // Resolve all links links.Resolve(this, true); events.Publish("SubscribeToEvents", new object[] { this, EventArgs.Empty }); } catch (Exception err) { throw new SimulationException("", err, Name, FileName); } }