diff --git a/ApsimNG/Presenters/PropertyPresenter.cs b/ApsimNG/Presenters/PropertyPresenter.cs index ffde86bf79..986b2d9484 100644 --- a/ApsimNG/Presenters/PropertyPresenter.cs +++ b/ApsimNG/Presenters/PropertyPresenter.cs @@ -235,7 +235,7 @@ public void UpdateModel(Model model) if (this.properties[i].DisplayType == DisplayAttribute.DisplayTypeEnum.CultivarName) { - ICrop crop = this.GetCrop(this.properties); + IPlant crop = this.GetCrop(this.properties); if (crop != null) { cell.DropDownStrings = this.GetCultivarNames(crop); @@ -302,7 +302,7 @@ private void FormatGrid() else if (this.properties[i].DisplayType == DisplayAttribute.DisplayTypeEnum.CultivarName) { cell.EditorType = EditorTypeEnum.DropDown; - ICrop crop = this.GetCrop(this.properties); + IPlant crop = this.GetCrop(this.properties); if (crop != null) { cell.DropDownStrings = this.GetCultivarNames(crop); @@ -337,20 +337,20 @@ private void FormatGrid() cell.EditorType = EditorTypeEnum.DropDown; cell.DropDownStrings = StringUtilities.EnumToStrings(cellValue); } - else if (cellValue.GetType() == typeof(ICrop)) + else if (cellValue.GetType() == typeof(IPlant)) { cell.EditorType = EditorTypeEnum.DropDown; List cropNames = new List(); - foreach (Model crop in Apsim.FindAll(this.model, typeof(ICrop))) + foreach (Model crop in Apsim.FindAll(this.model, typeof(IPlant))) { cropNames.Add(crop.Name); } cell.DropDownStrings = cropNames.ToArray(); } - else if (this.properties[i].DataType == typeof(ICrop)) + else if (this.properties[i].DataType == typeof(IPlant)) { - List plantNames = Apsim.FindAll(this.model, typeof(ICrop)).Select(m => m.Name).ToList(); + List plantNames = Apsim.FindAll(this.model, typeof(IPlant)).Select(m => m.Name).ToList(); cell.EditorType = EditorTypeEnum.DropDown; cell.DropDownStrings = plantNames.ToArray(); } @@ -372,7 +372,7 @@ private void FormatGrid() /// Get a list of cultivars for crop. /// The crop. /// A list of cultivars. - private string[] GetCultivarNames(ICrop crop) + private string[] GetCultivarNames(IPlant crop) { if (crop.CultivarNames.Length == 0) { @@ -380,7 +380,7 @@ private string[] GetCultivarNames(ICrop crop) Replacements replacements = Apsim.Child(simulations, typeof(Replacements)) as Replacements; if (replacements != null) { - ICrop replacementCrop = Apsim.Child(replacements, (crop as IModel).Name) as ICrop; + IPlant replacementCrop = Apsim.Child(replacements, (crop as IModel).Name) as IPlant; if (replacementCrop != null) { return replacementCrop.CultivarNames; @@ -428,13 +428,13 @@ private string[] GetFieldNames() /// /// The list of properties to look through. /// The found crop or null if none found. - private ICrop GetCrop(List properties) + private IPlant GetCrop(List properties) { foreach (VariableProperty property in properties) { - if (property.DataType == typeof(ICrop)) + if (property.DataType == typeof(IPlant)) { - ICrop plant = property.Value as ICrop; + IPlant plant = property.Value as IPlant; if (plant != null) { return plant; @@ -443,7 +443,7 @@ private ICrop GetCrop(List properties) } // Not found so look for one in scope. - return Apsim.Find(this.model, typeof(ICrop)) as ICrop; + return Apsim.Find(this.model, typeof(IPlant)) as IPlant; } /// @@ -501,9 +501,9 @@ private void SetPropertyValue(VariableProperty property, object value) throw new ApsimXException(this.model, "Invalid property type: " + property.DataType.ToString()); } } - else if (typeof(ICrop).IsAssignableFrom(property.DataType)) + else if (typeof(IPlant).IsAssignableFrom(property.DataType)) { - value = Apsim.Find(this.model, value.ToString()) as ICrop; + value = Apsim.Find(this.model, value.ToString()) as IPlant; } else if (property.DataType == typeof(DateTime)) { diff --git a/ApsimNG/Resources/Toolboxes/ManagementToolbox.apsimx b/ApsimNG/Resources/Toolboxes/ManagementToolbox.apsimx index 7ae6fed169..4450b31c92 100644 --- a/ApsimNG/Resources/Toolboxes/ManagementToolbox.apsimx +++ b/ApsimNG/Resources/Toolboxes/ManagementToolbox.apsimx @@ -32,7 +32,7 @@ namespace Models Accumulator accumulatedRain; [Description("Crop")] - public ICrop Crop { get; set; } + public IPlant Crop { get; set; } [Description("Sowing date (d-mmm)")] public string SowDate { get; set; } [Display(DisplayType = DisplayAttribute.DisplayTypeEnum.CultivarName)] @@ -98,7 +98,7 @@ namespace Models Accumulator accumulatedRain; [Description("Crop")] - public ICrop Crop { get; set; } + public IPlant Crop { get; set; } [Description("Start of sowing window (d-mmm)")] public string StartDate { get; set; } [Description("End of sowing window (d-mmm)")] @@ -166,7 +166,7 @@ namespace Models public class Script : Model { [Description("Crop")] - public ICrop Crop { get; set; } + public IPlant Crop { get; set; } [EventSubscribe("DoManagement")] private void OnDoManagement(object sender, EventArgs e) @@ -242,7 +242,7 @@ namespace Models [Link] Fertiliser Fertiliser; [Description("Crop to be fertilised")] - public ICrop Crop { get; set; } + public IPlant Crop { get; set; } [Description("Amount of fertiliser to be applied (kg/ha)")] public double Amount { get; set; } diff --git a/ApsimNG/Views/ActivityLedgerGridView.cs b/ApsimNG/Views/ActivityLedgerGridView.cs index 11606a0bbf..75119909cf 100644 --- a/ApsimNG/Views/ActivityLedgerGridView.cs +++ b/ApsimNG/Views/ActivityLedgerGridView.cs @@ -565,7 +565,7 @@ public bool ReadOnly private string AsString(object obj) { string result; - if (obj is ICrop) + if (obj is IPlant) result = (obj as IModel).Name; else result = obj.ToString(); diff --git a/ApsimNG/Views/GridView.cs b/ApsimNG/Views/GridView.cs index 50836f5899..fa268d5262 100644 --- a/ApsimNG/Views/GridView.cs +++ b/ApsimNG/Views/GridView.cs @@ -1420,7 +1420,7 @@ public IGridCell GetCell(int columnIndex, int rowIndex) private string AsString(object obj) { string result; - if (obj is ICrop) + if (obj is IPlant) result = (obj as IModel).Name; else result = obj.ToString(); diff --git a/Models/AgPasture/AgPasture.PastureSpecies.Organs.cs b/Models/AgPasture/AgPasture.PastureSpecies.Organs.cs index fcc32ce3a3..1082c530d4 100644 --- a/Models/AgPasture/AgPasture.PastureSpecies.Organs.cs +++ b/Models/AgPasture/AgPasture.PastureSpecies.Organs.cs @@ -19,12 +19,17 @@ namespace Models.AgPasture { /// Describes a generic above ground organ of a pasture species. [Serializable] - public class PastureAboveGroundOrgan : AboveGround + public class PastureAboveGroundOrgan : IRemovableBiomass { + /// Parent plant for this organ + private PastureSpecies parentPlant; + /// Constructor, initialise tissues. + /// Parent plant for the organ /// The number of tissues in the organ - public PastureAboveGroundOrgan(int numTissues) + public PastureAboveGroundOrgan(PastureSpecies parentPlant, int numTissues) { + this.parentPlant = parentPlant; // Typically four tissues above ground, three live and one dead TissueCount = numTissues; Tissue = new GenericTissue[TissueCount]; @@ -36,7 +41,7 @@ public PastureAboveGroundOrgan(int numTissues) internal GenericTissue[] Tissue { get; set; } /// Return live biomass. Used by STOCK - Biomass Live + public Biomass Live { get { @@ -49,7 +54,7 @@ Biomass Live } /// Return dead biomass. Used by STOCK - Biomass Dead + public Biomass Dead { get { @@ -61,7 +66,18 @@ Biomass Dead } } + /// Gets a value indicating whether the biomass is above ground or not + public bool IsAboveGround { get { return true; } } + /// + /// Biomass removal logic for this organ. + /// + /// Name of event that triggered this biomass remove call. + /// Biomass to remove + public void RemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType biomassToRemove) + { + throw new NotImplementedException(); + } #region Organ specific characteristics ---------------------------------------------------------------------------- diff --git a/Models/AgPasture/AgPasture.PastureSpecies.cs b/Models/AgPasture/AgPasture.PastureSpecies.cs index c32756582a..b7e57701a5 100644 --- a/Models/AgPasture/AgPasture.PastureSpecies.cs +++ b/Models/AgPasture/AgPasture.PastureSpecies.cs @@ -26,7 +26,7 @@ namespace Models.AgPasture [PresenterName("UserInterface.Presenters.PropertyPresenter")] [ValidParent(ParentType = typeof(Zone))] [ValidParent(ParentType = typeof(Sward))] - public class PastureSpecies : Model, ICrop, ICanopy, IUptake + public class PastureSpecies : Model, IPlant, ICanopy, IUptake { #region Links, events and delegates ------------------------------------------------------------------------------- @@ -211,6 +211,21 @@ public CanopyEnergyBalanceInterceptionlayerType[] LightProfile #region ICrop implementation -------------------------------------------------------------------------------------- + /// Gets a value indicating how leguminous a plant is + public double Legumosity + { + get + { + if (SpeciesFamily == PastureSpecies.PlantFamilyType.Legume) + return 1; + else + return 0; + } + } + + /// Gets a value indicating whether the biomass is from a c4 plant or not + public bool IsC4 { get { return PhotosyntheticPathway == PastureSpecies.PhotosynthesisPathwayType.C4; } } + /// Gets a list of cultivar names (not used by AgPasture). public string[] CultivarNames { @@ -3608,9 +3623,9 @@ private void OnSimulationCommencing(object sender, EventArgs e) nLayers = mySoil.Thickness.Length; // set up the organs (use 4 or 2 tissues, the last is dead) - leaves = new PastureAboveGroundOrgan(4); - stems = new PastureAboveGroundOrgan(4); - stolons = new PastureAboveGroundOrgan(4); + leaves = new PastureAboveGroundOrgan(this, 4); + stems = new PastureAboveGroundOrgan(this, 4); + stolons = new PastureAboveGroundOrgan(this, 4); rootZones = new List(); plantZoneRoots = new PastureBelowGroundOrgan(2, nLayers, myWaterAvailableMethod, myNitrogenAvailableMethod, diff --git a/Models/AgPasture/AgPasture.Sward.cs b/Models/AgPasture/AgPasture.Sward.cs index a42b0d3a16..79560c54fe 100644 --- a/Models/AgPasture/AgPasture.Sward.cs +++ b/Models/AgPasture/AgPasture.Sward.cs @@ -25,7 +25,7 @@ namespace Models.AgPasture [ViewName("UserInterface.Views.GridView")] [PresenterName("UserInterface.Presenters.PropertyPresenter")] [ValidParent(ParentType = typeof(Zone))] - public class Sward : Model, ICrop + public class Sward : Model { #region Links, events and delegates ------------------------------------------------------------------------------- diff --git a/Models/Core/ApsimFile/Converter.cs b/Models/Core/ApsimFile/Converter.cs index 36a3a62a3b..dacb7567f3 100644 --- a/Models/Core/ApsimFile/Converter.cs +++ b/Models/Core/ApsimFile/Converter.cs @@ -23,7 +23,7 @@ namespace Models.Core.ApsimFile public class Converter { /// Gets the lastest .apsimx file format version. - public static int LastestVersion { get { return 27; } } + public static int LastestVersion { get { return 28; } } /// Converts to file to the latest version. /// Name of the file. @@ -821,5 +821,19 @@ private static void UpgradeToVersion27(XmlNode node, string fileName) } } } + + /// + /// Upgrades to version 28. Change ICrop to IPlant + /// + /// The node to upgrade. + /// The name of the .apsimx file + private static void UpgradeToVersion28(XmlNode node, string fileName) + { + foreach (XmlNode manager in XmlUtilities.FindAllRecursivelyByType(node, "manager")) + { + ConverterUtilities.SearchReplaceManagerCode(manager, " ICrop", " IPlant"); + ConverterUtilities.SearchReplaceManagerCode(manager, "(ICrop)", "(IPlant)"); + } + } } } diff --git a/Models/Core/ICrop.cs b/Models/Core/IPlant.cs similarity index 84% rename from Models/Core/ICrop.cs rename to Models/Core/IPlant.cs index f17335fff4..244e244526 100644 --- a/Models/Core/ICrop.cs +++ b/Models/Core/IPlant.cs @@ -10,8 +10,14 @@ namespace Models.Core /// crops must have. In effect this interface describes the interactions /// between a crop and the other models in APSIM. /// - public interface ICrop + public interface IPlant { + /// Gets a value indicating how leguminous a plant is + double Legumosity { get; } + + /// Gets a value indicating whether the biomass is from a c4 plant or not + bool IsC4 { get; } + /// Is the plant alive? bool IsAlive { get; } diff --git a/Models/Manager.cs b/Models/Manager.cs index e978172f44..972363ab11 100644 --- a/Models/Manager.cs +++ b/Models/Manager.cs @@ -305,7 +305,7 @@ private void SetParametersInObject(Model script, XmlElement xmlElement) if (property != null) { object value; - if (property.PropertyType.Name == "ICrop") + if (property.PropertyType.Name == "IPlant") value = Apsim.Find(this, element.InnerText); else value = ReflectionUtilities.StringToObject(property.PropertyType, element.InnerText); @@ -329,7 +329,7 @@ private XmlElement GetParametersInObject(Model script) object value = property.GetValue(script, null); if (value == null) value = ""; - else if (value is ICrop) + else if (value is IPlant) value = (value as IModel).Name; XmlUtilities.SetValue(doc.DocumentElement, property.Name, ReflectionUtilities.ObjectToString(value)); diff --git a/Models/Models.csproj b/Models/Models.csproj index 9d58cb5aee..94bb9cb7f3 100644 --- a/Models/Models.csproj +++ b/Models/Models.csproj @@ -194,6 +194,7 @@ + @@ -483,7 +484,7 @@ - + diff --git a/Models/Plant/Interfaces/IOrgan.cs b/Models/Plant/Interfaces/IOrgan.cs index 73d2940899..d2ec6f57fe 100644 --- a/Models/Plant/Interfaces/IOrgan.cs +++ b/Models/Plant/Interfaces/IOrgan.cs @@ -3,12 +3,10 @@ // Copyright (c) APSIM Initiative // //----------------------------------------------------------------------- -using System.Collections.Generic; - namespace Models.PMF.Interfaces { /// - /// Base organ model + /// Organ interface /// public interface IOrgan { @@ -16,29 +14,7 @@ public interface IOrgan /// The Name of the organ. /// string Name { get; set; } - - /// - /// Biomass removal logic for this organ. - /// - /// Name of event that triggered this biomass remove call. - /// Biomass to remove - void DoRemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType biomassToRemove); - - } - - /// An above ground interface - public interface AboveGround { } - - /// A below ground interface - public interface BelowGround { } - - /// Indicates the organ is a reproductive one. - public interface Reproductive { } - - /// Indicates the organ transpires - public interface Transpiring { } - } diff --git a/Models/Plant/Interfaces/IRemovableBiomass.cs b/Models/Plant/Interfaces/IRemovableBiomass.cs new file mode 100644 index 0000000000..63828a9893 --- /dev/null +++ b/Models/Plant/Interfaces/IRemovableBiomass.cs @@ -0,0 +1,33 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) APSIM Initiative +// +//----------------------------------------------------------------------- +namespace Models.PMF.Interfaces +{ + /// + /// Interface used by code (e.g. STOCK) to remove biomass from an organ. + /// + public interface IRemovableBiomass + { + /// Gets the live biomass + Biomass Live { get; } + + /// Gets the dead biomass + Biomass Dead { get; } + + /// Gets a value indicating whether the biomass is above ground or not + bool IsAboveGround { get; } + + /// + /// Biomass removal logic for this organ. + /// + /// Name of event that triggered this biomass remove call. + /// Biomass to remove + void RemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType biomassToRemove); + } +} + + + + diff --git a/Models/Plant/OilPalm/OilPalm.cs b/Models/Plant/OilPalm/OilPalm.cs index f784792e77..374c433882 100644 --- a/Models/Plant/OilPalm/OilPalm.cs +++ b/Models/Plant/OilPalm/OilPalm.cs @@ -25,7 +25,7 @@ namespace Models.PMF.OilPalm [ViewName("UserInterface.Views.GridView")] [PresenterName("UserInterface.Presenters.PropertyPresenter")] [ValidParent(ParentType = typeof(Zone))] - public class OilPalm : ModelCollectionFromResource, ICrop, ICanopy, IUptake + public class OilPalm : ModelCollectionFromResource, IPlant, ICanopy, IUptake { #region Canopy interface /// Canopy type @@ -99,6 +99,12 @@ public bool IsAlive get { return plant_status == "alive"; } } + /// Gets a value indicating how leguminous a plant is + public double Legumosity { get { return 0; } } + + /// Gets a value indicating whether the biomass is from a c4 plant or not + public bool IsC4 { get { return false; } } + /// Returns true if the crop is ready for harvesting public bool IsReadyForHarvesting { get { return false; } } diff --git a/Models/Plant/Organs/BaseOrgan.cs b/Models/Plant/Organs/BaseOrgan.cs index 37cb4839a4..7589e27082 100644 --- a/Models/Plant/Organs/BaseOrgan.cs +++ b/Models/Plant/Organs/BaseOrgan.cs @@ -143,17 +143,6 @@ public virtual void SetNitrogenAllocation(BiomassAllocationType nitrogen) { } #endregion - #region Biomass removal - /// Removes biomass from organs when harvest, graze or cut events are called. - /// Name of event that triggered this biomass remove call. - /// The fractions of biomass to remove - virtual public void DoRemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType value) - { - throw new NotImplementedException(); - } - - #endregion - #region Management event methods /// Called when [simulation commencing]. diff --git a/Models/Plant/Organs/GenericOrgan.cs b/Models/Plant/Organs/GenericOrgan.cs index c497cf2413..fb6089115e 100644 --- a/Models/Plant/Organs/GenericOrgan.cs +++ b/Models/Plant/Organs/GenericOrgan.cs @@ -15,7 +15,7 @@ namespace Models.PMF.Organs /// [Serializable] [ValidParent(ParentType = typeof(Plant))] - public class GenericOrgan : Model, IOrgan, IArbitration, ICustomDocumentation + public class GenericOrgan : Model, IOrgan, IArbitration, ICustomDocumentation, IRemovableBiomass { /// The parent plant [Link] @@ -145,6 +145,9 @@ public GenericOrgan() Dead = new Biomass(); } + /// Gets a value indicating whether the biomass is above ground or not + public bool IsAboveGround { get { return true; } } + /// The live biomass [XmlIgnore] public Biomass Live { get; private set; } @@ -233,7 +236,7 @@ public double Nconc /// Removes biomass from organs when harvest, graze or cut events are called. /// Name of event that triggered this biomass remove call. /// The fractions of biomass to remove - public virtual void DoRemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType amountToRemove) + public virtual void RemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType amountToRemove) { biomassRemovalModel.RemoveBiomass(biomassRemoveType, amountToRemove, Live, Dead, Removed, Detached); } diff --git a/Models/Plant/Organs/HIReproductiveOrgan.cs b/Models/Plant/Organs/HIReproductiveOrgan.cs index 610418f135..c6091ae9d7 100644 --- a/Models/Plant/Organs/HIReproductiveOrgan.cs +++ b/Models/Plant/Organs/HIReproductiveOrgan.cs @@ -10,7 +10,7 @@ namespace Models.PMF.Organs /// A harvest index reproductive organ /// [Serializable] - public class HIReproductiveOrgan : BaseOrgan, IArbitration + public class HIReproductiveOrgan : BaseOrgan, IArbitration, IRemovableBiomass { /// Gets or sets the above ground. [Link] @@ -39,6 +39,9 @@ public class HIReproductiveOrgan : BaseOrgan, IArbitration /// The dead biomass public Biomass Dead { get; set; } + /// Gets a value indicating whether the biomass is above ground or not + public bool IsAboveGround { get { return true; } } + /// Gets the live f wt. /// The live f wt. [Units("g/m^2")] @@ -162,7 +165,7 @@ public override BiomassPoolType CalculateNitrogenDemand() /// Removes biomass from organs when harvest, graze or cut events are called. /// Name of event that triggered this biomass remove call. /// The fractions of biomass to remove - public override void DoRemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType value) + public void RemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType value) { biomassRemovalModel.RemoveBiomass(biomassRemoveType, value, Live, Dead, Removed, Detached); } diff --git a/Models/Plant/Organs/Leaf.cs b/Models/Plant/Organs/Leaf.cs index 3c15897608..618ac57462 100644 --- a/Models/Plant/Organs/Leaf.cs +++ b/Models/Plant/Organs/Leaf.cs @@ -32,7 +32,7 @@ namespace Models.PMF.Organs [ViewName("UserInterface.Views.GridView")] [PresenterName("UserInterface.Presenters.PropertyPresenter")] [ValidParent(ParentType = typeof(Plant))] - public class Leaf : BaseOrgan, ICanopy, ILeaf, IHasWaterDemand, IArbitration + public class Leaf : BaseOrgan, ICanopy, ILeaf, IHasWaterDemand, IArbitration, IRemovableBiomass { /// The met data @@ -437,6 +437,9 @@ public class LeafCohortParameters : Model //Variables that represent the number of leaf cohorts (integer) in a particular state on an individual main-stem are cohort variables (CohortNo suffix) //Variables that represent the number of primordia or nodes (double) in a particular state on an individual mainstem are called number variables (e.g NodeNo or PrimordiaNo suffix) //Variables that the number of leaves on a plant or a primary bud have Plant or Primary bud prefixes + + /// Gets a value indicating whether the biomass is above ground or not + public bool IsAboveGround { get { return true; } } /// Gets the total (live + dead) N concentration (g/g) [XmlIgnore] @@ -1284,7 +1287,7 @@ public double CoverAboveCohort(double cohortno) /// /// Name of event that triggered this biomass remove call. /// The frations of biomass to remove - public override void DoRemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType value) + public void RemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType value) { bool writeToSummary = true; foreach (LeafCohort leaf in Leaves) diff --git a/Models/Plant/Organs/PerennialLeaf.cs b/Models/Plant/Organs/PerennialLeaf.cs index a235edad90..8325b4b085 100644 --- a/Models/Plant/Organs/PerennialLeaf.cs +++ b/Models/Plant/Organs/PerennialLeaf.cs @@ -20,7 +20,7 @@ namespace Models.PMF.Organs [Serializable] [ViewName("UserInterface.Views.GridView")] [PresenterName("UserInterface.Presenters.PropertyPresenter")] - public class PerennialLeaf : Model, IOrgan, ICanopy, ILeaf, IArbitration, IHasWaterDemand + public class PerennialLeaf : Model, IOrgan, ICanopy, ILeaf, IArbitration, IHasWaterDemand, IRemovableBiomass { /// The met data [Link] @@ -60,6 +60,8 @@ public Biomass Dead } } + /// Gets a value indicating whether the biomass is above ground or not + public bool IsAboveGround { get { return true; } } /// The plant [Link] @@ -833,7 +835,7 @@ protected void DoPlantEnding(object sender, EventArgs e) /// Removes biomass from organs when harvest, graze or cut events are called. /// Name of event that triggered this biomass remove call. /// The fractions of biomass to remove - virtual public void DoRemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType value) + virtual public void RemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType value) { Biomass liveAfterRemoval = Live; Biomass deadAfterRemoval = Dead; diff --git a/Models/Plant/Organs/ReproductiveOrgan.cs b/Models/Plant/Organs/ReproductiveOrgan.cs index 6075434dcd..c08d9b83b2 100644 --- a/Models/Plant/Organs/ReproductiveOrgan.cs +++ b/Models/Plant/Organs/ReproductiveOrgan.cs @@ -13,7 +13,7 @@ namespace Models.PMF.Organs /// This organ uses a generic model for plant reproductive components. Yield is calculated from its components in terms of organ number and size (for example, grain number and grain size). /// [Serializable] - public class ReproductiveOrgan : BaseOrgan, IArbitration + public class ReproductiveOrgan : BaseOrgan, IArbitration, IRemovableBiomass { #region Parameter Input Classes /// The phenology @@ -91,6 +91,9 @@ public class ReproductiveOrgan : BaseOrgan, IArbitration /// The dead biomass public Biomass Dead { get; set; } + + /// Gets a value indicating whether the biomass is above ground or not + public bool IsAboveGround { get { return true; } } /// The number [XmlIgnore] @@ -365,7 +368,7 @@ public double Nconc /// Removes biomass from organs when harvest, graze or cut events are called. /// Name of event that triggered this biomass remove call. /// The fractions of biomass to remove - public override void DoRemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType value) + public void RemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType value) { biomassRemovalModel.RemoveBiomass(biomassRemoveType, value, Live, Dead, Removed, Detached); } diff --git a/Models/Plant/Organs/Root.cs b/Models/Plant/Organs/Root.cs index b2d3f25f30..5278f3814d 100644 --- a/Models/Plant/Organs/Root.cs +++ b/Models/Plant/Organs/Root.cs @@ -62,7 +62,7 @@ namespace Models.PMF.Organs [Description("Root Class")] [ViewName("UserInterface.Views.GridView")] [PresenterName("UserInterface.Presenters.PropertyPresenter")] - public class Root : Model, IWaterNitrogenUptake, IArbitration, IOrgan + public class Root : Model, IWaterNitrogenUptake, IArbitration, IOrgan, IRemovableBiomass { /// The plant [Link] @@ -250,6 +250,9 @@ public Root() ZoneInitialDM = new List(); } + /// Gets a value indicating whether the biomass is above ground or not + public bool IsAboveGround { get { return false; } } + /// A list of other zone names to grow roots in [XmlIgnore] public List ZoneNamesToGrowRootsIn { get; set; } @@ -774,7 +777,7 @@ public double[] CalculateWaterSupply(ZoneWaterAndN zone) /// Removes biomass from root layers when harvest, graze or cut events are called. /// Name of event that triggered this biomass remove call. /// The fractions of biomass to remove - public void DoRemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType removal) + public void RemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType removal) { biomassRemovalModel.RemoveBiomassToSoil(biomassRemoveType, removal, PlantZone.LayerLive, PlantZone.LayerDead, Removed, Detached); } @@ -971,7 +974,7 @@ private double AvailableDMRetranslocation() private void DoPlantEnding(object sender, EventArgs e) { //Send all root biomass to soil FOM - DoRemoveBiomass(null, new OrganBiomassRemovalType() { FractionLiveToResidue = 1.0 }); + RemoveBiomass(null, new OrganBiomassRemovalType() { FractionLiveToResidue = 1.0 }); Clear(); } @@ -1049,7 +1052,7 @@ private void OnDoActualPlantGrowth(object sender, EventArgs e) foreach (ZoneState Z in Zones) Z.GrowRootDepth(); // Do Root Senescence - DoRemoveBiomass(null, new OrganBiomassRemovalType() { FractionLiveToResidue = senescenceRate.Value() }); + RemoveBiomass(null, new OrganBiomassRemovalType() { FractionLiveToResidue = senescenceRate.Value() }); } needToRecalculateLiveDead = false; // Do maintenance respiration diff --git a/Models/Plant/Organs/RootSWIM.cs b/Models/Plant/Organs/RootSWIM.cs index 3fd53158cd..c8b7ee32c1 100644 --- a/Models/Plant/Organs/RootSWIM.cs +++ b/Models/Plant/Organs/RootSWIM.cs @@ -12,7 +12,7 @@ namespace Models.PMF.Organs /// A root model for SWIM /// [Serializable] - public class RootSWIM : BaseOrgan, IArbitration, BelowGround + public class RootSWIM : BaseOrgan, IArbitration { /// The uptake private double[] Uptake = null; @@ -97,7 +97,7 @@ private void OnPlantEnding(object sender, EventArgs e) /// Removes biomass from organs when harvest, graze or cut events are called. /// Name of event that triggered this biomass remove call. /// The fractions of biomass to remove - public override void DoRemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType value) + public void RemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType value) { biomassRemovalModel.RemoveBiomass(biomassRemoveType, value, Live, Dead, Removed, Detached); } diff --git a/Models/Plant/Plant.cs b/Models/Plant/Plant.cs index aabe841318..ec198742c2 100644 --- a/Models/Plant/Plant.cs +++ b/Models/Plant/Plant.cs @@ -60,7 +60,7 @@ namespace Models.PMF [ValidParent(ParentType = typeof(Zone))] [Serializable] [ScopedModel] - public class Plant : ModelCollectionFromResource, ICrop, ICustomDocumentation + public class Plant : ModelCollectionFromResource, IPlant, ICustomDocumentation { #region Class links /// The summary @@ -103,6 +103,14 @@ public class Plant : ModelCollectionFromResource, ICrop, ICustomDocumentation /// Used by several organs to determine the type of crop. public string CropType { get; set; } + /// Gets a value indicating how leguminous a plant is + [XmlIgnore] + public double Legumosity { get; } + + /// Gets a value indicating whether the biomass is from a c4 plant or not + [XmlIgnore] + public bool IsC4 { get; } + /// The sowing data [XmlIgnore] public SowPlant2Type SowingData { get; set; } @@ -149,6 +157,16 @@ private List Cultivars /// The current cultivar definition. private Cultivar cultivarDefinition; + /// + /// Constructor + /// + public Plant() + { + string photosyntheticPathway = (string) Apsim.Get(this, "Leaf.Photosynthesis.FCO2.PhotosyntheticPathway"); + IsC4 = photosyntheticPathway != null && photosyntheticPathway == "C4"; + Legumosity = 0; + } + /// Gets the water supply demand ratio. [Units("0-1")] public double WaterSupplyDemandRatio @@ -409,7 +427,7 @@ public void RemoveBiomass(string biomassRemoveType, RemovalFractions removalData OrganBiomassRemovalType biomassRemoval = null; if (removalData != null) biomassRemoval = removalData.GetFractionsForOrgan(organ.Name); - organ.DoRemoveBiomass(biomassRemoveType, biomassRemoval); + (organ as IRemovableBiomass).RemoveBiomass(biomassRemoveType, biomassRemoval); } // Reset the phenology if SetPhenologyStage specified. diff --git a/Models/Plant/SimpleTree/SimpleTree.cs b/Models/Plant/SimpleTree/SimpleTree.cs index 4f38252644..0d2c444ad7 100644 --- a/Models/Plant/SimpleTree/SimpleTree.cs +++ b/Models/Plant/SimpleTree/SimpleTree.cs @@ -19,7 +19,7 @@ namespace Models.PMF [ViewName("UserInterface.Views.GridView")] [PresenterName("UserInterface.Presenters.PropertyPresenter")] [ValidParent(ParentType = typeof(Zone))] - public class SimpleTree : Model, ICrop, ICanopy, IUptake + public class SimpleTree : Model, IPlant, ICanopy, IUptake { #region Canopy interface @@ -67,6 +67,12 @@ public class SimpleTree : Model, ICrop, ICanopy, IUptake /// public string CropType { get; set; } + /// Gets a value indicating how leguminous a plant is + public double Legumosity { get { return 0; } } + + /// Gets a value indicating whether the biomass is from a c4 plant or not + public bool IsC4 { get { return false; } } + /// Albedo. public double Albedo { get { return 0.15; } } diff --git a/Models/Stock/stock.cs b/Models/Stock/stock.cs index 710b172870..775b25b88f 100644 --- a/Models/Stock/stock.cs +++ b/Models/Stock/stock.cs @@ -3998,7 +3998,7 @@ private void OnStartOfSimulation(object sender, EventArgs e) PaddockInfo thePadd = this.stockModel.Paddocks.byObj(zone); // find all the child crop, pasture components with an TAvailableToAnimal property - foreach (Model crop in Apsim.FindAll(zone, typeof(ICrop))) + foreach (Model crop in Apsim.FindAll(zone, typeof(IPlant))) { this.stockModel.ForagesAll.AddProvider(thePadd, zone.Name, crop.Name, 0, 0, crop, true); } diff --git a/Models/Sugarcane/Sugarcane.cs b/Models/Sugarcane/Sugarcane.cs index c742ad9895..1c9f5f26a6 100644 --- a/Models/Sugarcane/Sugarcane.cs +++ b/Models/Sugarcane/Sugarcane.cs @@ -352,7 +352,7 @@ namespace Models [ViewName("UserInterface.Views.GridView")] [PresenterName("UserInterface.Presenters.PropertyPresenter")] [ValidParent(ParentType=typeof(Zone))] - public class Sugarcane : Model, ICrop, ICanopy, IUptake + public class Sugarcane : Model, IPlant, ICanopy, IUptake { #region Canopy interface @@ -463,7 +463,11 @@ public class Sugarcane : Model, ICrop, ICanopy, IUptake #endregion + /// Gets a value indicating how leguminous a plant is + public double Legumosity { get { return 0; } } + /// Gets a value indicating whether the biomass is from a c4 plant or not + public bool IsC4 { get { return true; } } //CONSTANTS