{
  "$type": "Models.Core.Simulations, Models",
  "Version": 220,
  "Name": "Simulations",
  "ResourceName": null,
  "Children": [
    {
      "$type": "Models.Core.Simulation, Models",
      "Name": "Simulation",
      "ResourceName": null,
      "Children": [
        {
          "$type": "Models.Clock, Models",
          "Start": "1998-04-01T00:00:00",
          "End": "1999-04-30T00:00:00",
          "Name": "Clock",
          "ResourceName": null,
          "Children": [],
          "Enabled": true,
          "ReadOnly": false
        },
        {
          "$type": "Models.Summary, Models",
          "Verbosity": 100,
          "Name": "Summary",
          "ResourceName": null,
          "Children": [],
          "Enabled": true,
          "ReadOnly": false
        },
        {
          "$type": "Models.Climate.Weather, Models",
          "ConstantsFile": null,
          "FileName": "%root%/Examples/WeatherFiles/AU_Dalby.met",
          "ExcelWorkSheetName": "",
          "Name": "Weather",
          "ResourceName": null,
          "Children": [],
          "Enabled": true,
          "ReadOnly": false
        },
        {
          "$type": "Models.Soils.Arbitrator.SoilArbitrator, Models",
          "Name": "SoilArbitrator",
          "ResourceName": null,
          "Children": [],
          "Enabled": true,
          "ReadOnly": false
        },
        {
          "$type": "Models.MicroClimate, Models",
          "a_interception": 0.0,
          "b_interception": 1.0,
          "c_interception": 0.0,
          "d_interception": 0.0,
          "SoilHeatFluxFraction": 0.4,
          "MinimumHeightDiffForNewLayer": 0.0,
          "NightInterceptionFraction": 0.5,
          "ReferenceHeight": 2.0,
          "Name": "MicroClimate",
          "ResourceName": "MicroClimate",
          "Children": [],
          "Enabled": true,
          "ReadOnly": false
        },
        {
          "$type": "Models.Core.Zone, Models",
          "Area": 1.0,
          "Slope": 0.0,
          "AspectAngle": 0.0,
          "Altitude": 50.0,
          "CanopyType": null,
          "Name": "Field",
          "ResourceName": null,
          "Children": [
            {
              "$type": "Models.Report, Models",
              "VariableNames": [
                "[Clock].Today"
              ],
              "EventNames": [
                "[Clock].EndOfDay"
              ],
              "GroupByVariableName": null,
              "Name": "Report",
              "ResourceName": null,
              "Children": [
                {
                  "$type": "Models.CLEM.Reporting.ReportPivot, Models",
                  "Value": null,
                  "Row": null,
                  "Column": null,
                  "Time": null,
                  "Aggregator": null,
                  "IncludeValueColumnNameOutputColumns": false,
                  "SelectedTab": null,
                  "Name": "ReportPivot",
                  "ResourceName": null,
                  "Children": [],
                  "Enabled": true,
                  "ReadOnly": false
                }
              ],
              "Enabled": true,
              "ReadOnly": false
            },
            {
              "$type": "Models.Fertiliser, Models",
              "Name": "Fertiliser",
              "ResourceName": "Fertiliser",
              "Children": [],
              "Enabled": true,
              "ReadOnly": false
            },
            {
              "$type": "Models.Soils.Soil, Models",
              "RecordNumber": 104,
              "ASCOrder": "Vertosol",
              "ASCSubOrder": "Black",
              "SoilType": "Clay",
              "LocalName": null,
              "Site": "Norwin",
              "NearestTown": "Norwin",
              "Region": "Darling Downs and Granite Belt",
              "State": "Queensland",
              "Country": "Australia",
              "NaturalVegetation": "Qld. Bluegrass, possible Qld. Blue gum",
              "ApsoilNumber": "900",
              "Latitude": -27.581836,
              "Longitude": 151.320206,
              "LocationAccuracy": " +/- 20m",
              "YearOfSampling": "0",
              "DataSource": "CSIRO Sustainable Ecosystems, Toowoomba; Characteriesd as part of the GRDC funded project\"Doing it better, doing it smarter, managing soil water in Australian agriculture' 2011",
              "Comments": "Clay - OC, CLL for all crops estimated-based on Bongeen Mywybilla Soil No1",
              "Name": "Soil",
              "ResourceName": null,
              "Children": [
                {
                  "$type": "Models.Soils.Physical, Models",
                  "Thickness": [
                    150.0,
                    150.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0
                  ],
                  "ParticleSizeSand": null,
                  "ParticleSizeSilt": null,
                  "ParticleSizeClay": null,
                  "Rocks": null,
                  "Texture": null,
                  "BD": [
                    1.01056473311131,
                    1.07145631083388,
                    1.09393858528057,
                    1.15861335018721,
                    1.17301160318016,
                    1.16287303586874,
                    1.18749547755906
                  ],
                  "AirDry": [
                    0.130250054518252,
                    0.198689390775399,
                    0.28,
                    0.28,
                    0.28,
                    0.28,
                    0.28
                  ],
                  "LL15": [
                    0.260500109036505,
                    0.248361738469248,
                    0.28,
                    0.28,
                    0.28,
                    0.28,
                    0.28
                  ],
                  "DUL": [
                    0.52100021807301,
                    0.496723476938497,
                    0.488437607673005,
                    0.480296969355493,
                    0.471583596524955,
                    0.457070570557793,
                    0.452331759845006
                  ],
                  "SAT": [
                    0.588654817693846,
                    0.565676863836273,
                    0.557192986686577,
                    0.532787415023694,
                    0.527354112007486,
                    0.531179986464627,
                    0.521888499034317
                  ],
                  "KS": [
                    20.0,
                    20.0,
                    20.0,
                    20.0,
                    20.0,
                    20.0,
                    20.0
                  ],
                  "BDMetadata": null,
                  "AirDryMetadata": null,
                  "LL15Metadata": null,
                  "DULMetadata": null,
                  "SATMetadata": null,
                  "KSMetadata": null,
                  "RocksMetadata": null,
                  "TextureMetadata": null,
                  "ParticleSizeSandMetadata": null,
                  "ParticleSizeSiltMetadata": null,
                  "ParticleSizeClayMetadata": null,
                  "Name": "Physical",
                  "ResourceName": null,
                  "Children": [
                    {
                      "$type": "Models.Soils.SoilCrop, Models",
                      "LL": [
                        0.261,
                        0.248,
                        0.28,
                        0.306,
                        0.36,
                        0.392,
                        0.446
                      ],
                      "KL": [
                        0.06,
                        0.06,
                        0.06,
                        0.04,
                        0.04,
                        0.02,
                        0.01
                      ],
                      "XF": [
                        1.0,
                        1.0,
                        1.0,
                        1.0,
                        1.0,
                        1.0,
                        1.0
                      ],
                      "LLMetadata": null,
                      "KLMetadata": null,
                      "XFMetadata": null,
                      "Name": "WheatSoil",
                      "ResourceName": null,
                      "Children": [],
                      "Enabled": true,
                      "ReadOnly": false
                    }
                  ],
                  "Enabled": true,
                  "ReadOnly": false
                },
                {
                  "$type": "Models.WaterModel.WaterBalance, Models",
                  "SummerDate": "1-Nov",
                  "SummerU": 5.0,
                  "SummerCona": 5.0,
                  "WinterDate": "1-Apr",
                  "WinterU": 5.0,
                  "WinterCona": 5.0,
                  "DiffusConst": 40.0,
                  "DiffusSlope": 16.0,
                  "Salb": 0.12,
                  "CN2Bare": 73.0,
                  "CNRed": 20.0,
                  "CNCov": 0.8,
                  "DischargeWidth": "NaN",
                  "CatchmentArea": "NaN",
                  "PSIDul": -100.0,
                  "Thickness": [
                    150.0,
                    150.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0
                  ],
                  "SWCON": [
                    0.3,
                    0.3,
                    0.3,
                    0.3,
                    0.3,
                    0.3,
                    0.3
                  ],
                  "KLAT": null,
                  "Name": "SoilWater",
                  "ResourceName": "WaterBalance",
                  "Children": [],
                  "Enabled": true,
                  "ReadOnly": false
                },
                {
                  "$type": "Models.Soils.Organic, Models",
                  "FOMCNRatio": 40.0,
                  "Thickness": [
                    150.0,
                    150.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0
                  ],
                  "Carbon": [
                    1.2,
                    0.96,
                    0.6,
                    0.3,
                    0.18,
                    0.12,
                    0.12
                  ],
                  "CarbonUnits": 0,
                  "SoilCNRatio": [
                    12.0,
                    12.0,
                    12.0,
                    12.0,
                    12.0,
                    12.0,
                    12.0
                  ],
                  "FBiom": [
                    0.04,
                    0.02,
                    0.02,
                    0.02,
                    0.01,
                    0.01,
                    0.01
                  ],
                  "FInert": [
                    0.4,
                    0.6,
                    0.8,
                    1.0,
                    1.0,
                    1.0,
                    1.0
                  ],
                  "FOM": [
                    347.1290323127564,
                    270.3443621919937,
                    163.97214434990104,
                    99.45413288704063,
                    60.32198083112468,
                    36.58713082867487,
                    22.1912165985086
                  ],
                  "CarbonMetadata": null,
                  "FOMMetadata": null,
                  "Name": "Organic",
                  "ResourceName": null,
                  "Children": [],
                  "Enabled": true,
                  "ReadOnly": false
                },
                {
                  "$type": "Models.Soils.Chemical, Models",
                  "Thickness": [
                    150.0,
                    150.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0
                  ],
                  "PH": [
                    8.0,
                    8.0,
                    8.0,
                    8.0,
                    8.0,
                    8.0,
                    8.0
                  ],
                  "PHUnits": 0,
                  "EC": null,
                  "ESP": null,
                  "CEC": null,
                  "ECMetadata": null,
                  "CLMetadata": null,
                  "CECMetadata": null,
                  "ESPMetadata": null,
                  "PHMetadata": null,
                  "Name": "Chemical",
                  "ResourceName": null,
                  "Children": [],
                  "Enabled": true,
                  "ReadOnly": false
                },
                {
                  "$type": "Models.Soils.Water, Models",
                  "Thickness": [
                    150.0,
                    150.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0
                  ],
                  "InitialValues": [
                    0.52100021807301,
                    0.496723476938497,
                    0.488437607673005,
                    0.480296969355493,
                    0.471583596524955,
                    0.457070570557793,
                    0.452331759845006
                  ],
                  "FilledFromTop": false,
                  "Name": "Water",
                  "ResourceName": null,
                  "Children": [],
                  "Enabled": true,
                  "ReadOnly": false
                },
                {
                  "$type": "Models.Soils.Nutrients.Nutrient, Models",
                  "Name": "Nutrient",
                  "ResourceName": "Nutrient",
                  "Children": [],
                  "Enabled": true,
                  "ReadOnly": false
                },
                {
                  "$type": "Models.Soils.Solute, Models",
                  "Thickness": [
                    150.0,
                    150.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0
                  ],
                  "InitialValues": [
                    1.0,
                    1.0,
                    1.0,
                    1.0,
                    1.0,
                    1.0,
                    1.0
                  ],
                  "InitialValuesUnits": 0,
                  "WaterTableConcentration": 0.0,
                  "D0": 0.0,
                  "Exco": null,
                  "FIP": null,
                  "DepthConstant": 0.0,
                  "MaxDepthSoluteAccessible": 0.0,
                  "RunoffEffectivenessAtMovingSolute": 0.0,
                  "MaxEffectiveRunoff": 0.0,
                  "ConcInSolution": null,
                  "Name": "NO3",
                  "ResourceName": null,
                  "Children": [],
                  "Enabled": true,
                  "ReadOnly": false
                },
                {
                  "$type": "Models.Soils.Solute, Models",
                  "Thickness": [
                    150.0,
                    150.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0
                  ],
                  "InitialValues": [
                    0.1,
                    0.1,
                    0.1,
                    0.1,
                    0.1,
                    0.1,
                    0.1
                  ],
                  "InitialValuesUnits": 0,
                  "WaterTableConcentration": 0.0,
                  "D0": 0.0,
                  "Exco": null,
                  "FIP": null,
                  "DepthConstant": 0.0,
                  "MaxDepthSoluteAccessible": 0.0,
                  "RunoffEffectivenessAtMovingSolute": 0.0,
                  "MaxEffectiveRunoff": 0.0,
                  "ConcInSolution": null,
                  "Name": "NH4",
                  "ResourceName": null,
                  "Children": [],
                  "Enabled": true,
                  "ReadOnly": false
                },
                {
                  "$type": "Models.Soils.Solute, Models",
                  "Thickness": [
                    150.0,
                    150.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0,
                    300.0
                  ],
                  "InitialValues": [
                    0.0,
                    0.0,
                    0.0,
                    0.0,
                    0.0,
                    0.0,
                    0.0
                  ],
                  "InitialValuesUnits": 1,
                  "WaterTableConcentration": 0.0,
                  "D0": 0.0,
                  "Exco": null,
                  "FIP": null,
                  "DepthConstant": 0.0,
                  "MaxDepthSoluteAccessible": 0.0,
                  "RunoffEffectivenessAtMovingSolute": 0.0,
                  "MaxEffectiveRunoff": 0.0,
                  "ConcInSolution": null,
                  "Name": "Urea",
                  "ResourceName": null,
                  "Children": [],
                  "Enabled": true,
                  "ReadOnly": false
                },
                {
                  "$type": "Models.Soils.SoilTemp.SoilTemperature, Models",
                  "Thickness": null,
                  "InitialValues": null,
                  "InteractionsPerDay": 8,
                  "Name": "Temperature",
                  "ResourceName": null,
                  "Children": [],
                  "Enabled": true,
                  "ReadOnly": false
                }
              ],
              "Enabled": true,
              "ReadOnly": false
            },
            {
              "$type": "Models.Surface.SurfaceOrganicMatter, Models",
              "SurfOM": [],
              "Canopies": [],
              "InitialResidueName": "wheat_stubble",
              "InitialResidueType": "wheat",
              "InitialResidueMass": 500.0,
              "InitialStandingFraction": 0.0,
              "InitialCPR": 0.0,
              "InitialCNR": 100.0,
              "Name": "SurfaceOrganicMatter",
              "ResourceName": "SurfaceOrganicMatter",
              "Children": [],
              "Enabled": true,
              "ReadOnly": false
            },
            {
              "$type": "Models.PMF.Plant, Models",
              "Name": "Wheat",
              "ResourceName": "Wheat",
              "Children": [],
              "Enabled": true,
              "ReadOnly": false
            },
            {
              "$type": "Models.Manager, Models",
              "CodeArray": [
                "using APSIM.Numerics;",
                "using Models.Climate;",
                "using System.Linq;",
                "using System;",
                "using Models.Core;",
                "using Models.PMF;",
                "using Models.Soils;",
                "using Models.Utilities;",
                "using APSIM.Shared.Utilities;",
                "using Models.Interfaces;",
                "",
                "namespace Models",
                "{",
                "    [Serializable]",
                "    public class Script : Model",
                "    {",
                "        [Link] private Clock Clock;",
                "        [Link] private Fertiliser Fertiliser;",
                "        [Link] private Summary Summary;",
                "        [Link] private Soil Soil;",
                "        private Accumulator accumulatedRain;",
                "        [Link]",
                "        private ISoilWater waterBalance;",
                "        ",
                "        [Description(\"Crop\")]",
                "        public IPlant Crop { get; set; }",
                "",
                "        [Description(\"Start of sowing window (d-mmm)\")]",
                "        public string StartDate { get; set; }",
                "",
                "        [Description(\"End of sowing window (d-mmm)\")]",
                "        public string EndDate { get; set; }",
                "",
                "        [Description(\"Minimum extractable soil water for sowing (mm)\")]",
                "        public double MinESW { get; set; }",
                "",
                "        [Description(\"Accumulated rainfall required for sowing (mm)\")]",
                "        public double MinRain { get; set; }",
                "",
                "        [Description(\"Duration of rainfall accumulation (d)\")]",
                "        public int RainDays { get; set; }",
                "",
                "        [Display(Type = DisplayType.CultivarName)]",
                "        [Description(\"Cultivar to be sown\")]",
                "        public string CultivarName { get; set; }",
                "",
                "        [Description(\"Sowing depth (mm)\")]",
                "        public double SowingDepth { get; set; }",
                "",
                "        [Description(\"Row spacing (mm)\")]",
                "        public double RowSpacing { get; set; }",
                "",
                "        [Description(\"Plant population (/m2)\")]",
                "        public double Population { get; set; }",
                "        ",
                "        ",
                "        [EventSubscribe(\"StartOfSimulation\")]",
                "        private void OnSimulationCommencing(object sender, EventArgs e)",
                "        {",
                "            accumulatedRain = new Accumulator(this, \"[Weather].Rain\", RainDays);",
                "        }",
                "",
                "        [EventSubscribe(\"DoManagement\")]",
                "        private void OnDoManagement(object sender, EventArgs e)",
                "        {",
                "            accumulatedRain.Update();",
                "            ",
                "            if (DateUtilities.WithinDates(StartDate, Clock.Today, EndDate) &&",
                "                !Crop.IsAlive &&",
                "                MathUtilities.Sum(waterBalance.ESW) > MinESW &&",
                "                accumulatedRain.Sum > MinRain)",
                "            {",
                "                Crop.Sow(population: Population, cultivar: CultivarName, depth: SowingDepth, rowSpacing: RowSpacing);    ",
                "            }",
                "        }",
                "    }",
                "}"
              ],
              "Parameters": [
                {
                  "Key": "Crop",
                  "Value": "[Wheat]"
                },
                {
                  "Key": "StartDate",
                  "Value": "1-may"
                },
                {
                  "Key": "EndDate",
                  "Value": "10-jul"
                },
                {
                  "Key": "MinESW",
                  "Value": "100"
                },
                {
                  "Key": "MinRain",
                  "Value": "25"
                },
                {
                  "Key": "RainDays",
                  "Value": "7"
                },
                {
                  "Key": "CultivarName",
                  "Value": "Hartog"
                },
                {
                  "Key": "SowingDepth",
                  "Value": "30"
                },
                {
                  "Key": "RowSpacing",
                  "Value": "250"
                },
                {
                  "Key": "Population",
                  "Value": "120"
                }
              ],
              "Name": "Sow using a variable rule",
              "ResourceName": null,
              "Children": [],
              "Enabled": true,
              "ReadOnly": false
            },
            {
              "$type": "Models.Manager, Models",
              "CodeArray": [
                "using Models.Soils;",
                "using System;",
                "using System.Linq;",
                "using Models.Core;",
                "using Models.PMF;",
                "namespace Models",
                "{",
                "    [Serializable]",
                "    public class Script : Model",
                "    {",
                "        [Link] Clock Clock;",
                "        [Link] Fertiliser Fertiliser;",
                "        ",
                "        [Description(\"Crop to be fertilised\")]",
                "        public IPlant Crop { get; set; }",
                "",
                "        [Description(\"Type of fertiliser to apply? \")] ",
                "        [Display(Type = DisplayType.FertiliserType)]public string FertiliserType { get; set; }",
                "    ",
                "        [Description(\"Amount of fertiliser to be applied (kg/ha)\")]",
                "        public double Amount { get; set; }",
                "        ",
                "        [EventSubscribe(\"Sowing\")]",
                "        private void OnSowing(object sender, EventArgs e)",
                "        {",
                "            Model crop = sender as Model;",
                "            if (Crop != null && crop.Name.ToLower() == (Crop as IModel).Name.ToLower())",
                "                Fertiliser.Apply(amount: Amount, type: FertiliserType);",
                "        }",
                "    }",
                "}"
              ],
              "Parameters": [
                {
                  "Key": "Crop",
                  "Value": "[Wheat]"
                },
                {
                  "Key": "FertiliserType",
                  "Value": "UreaN"
                },
                {
                  "Key": "Amount",
                  "Value": "120"
                }
              ],
              "Name": "Fertilise at sowing",
              "ResourceName": null,
              "Children": [],
              "Enabled": true,
              "ReadOnly": false
            },
            {
              "$type": "Models.Manager, Models",
              "CodeArray": [
                "using APSIM.Shared.Utilities;",
                "using Models.Utilities;",
                "using Models.Soils;",
                "using Models.PMF;",
                "using Models.Core;",
                "using System;",
                "using System.Linq;",
                "",
                "namespace Models",
                "{",
                "    [Serializable] ",
                "    public class Script : Model",
                "    {",
                "        [Description(\"Crop\")]",
                "        public IPlant Crop { get; set; }",
                "        ",
                "        [EventSubscribe(\"DoManagement\")]",
                "        private void OnDoManagement(object sender, EventArgs e)",
                "        {",
                "            if (Crop.IsReadyForHarvesting)",
                "            {",
                "                Crop.Harvest();",
                "                Crop.EndCrop();",
                "            }",
                "        }",
                "    }",
                "}",
                "       "
              ],
              "Parameters": [
                {
                  "Key": "Crop",
                  "Value": "[Wheat]"
                }
              ],
              "Name": "Harvest",
              "ResourceName": null,
              "Children": [],
              "Enabled": true,
              "ReadOnly": false
            },
            {
              "$type": "Models.Manager, Models",
              "CodeArray": [
                "// ============================================================================",
                "// WheatAmmoniaVolatilisation_v4.cs",
                "//",
                "// Two improvements over the previous version, based on what the last real",
                "// APSIM run revealed:",
                "//",
                "//   1. AMMONIUM POOL, NOT UREA POOL, FOR LOSS REMOVAL.",
                "//      Real ammonia volatilisation occurs from the NH4<->NH3 equilibrium",
                "//      AFTER urea hydrolysis, not from urea itself. Previously, our removal",
                "//      logic was competing directly with APSIM's own built-in urea",
                "//      hydrolysis for the same urea pool, which is why most of the applied",
                "//      N \"disappeared\" (into NH4, via hydrolysis) before our script could",
                "//      remove it as a loss. This version still WATCHES the urea pool to",
                "//      detect when fertiliser has been applied (since that is how N",
                "//      physically enters the system), but REMOVES the predicted",
                "//      volatilisation loss from Nutrient.NH4.kgha[0] instead.",
                "//",
                "//   2. MULTIPLE INDEPENDENT SEASONAL EVENTS.",
                "//      Previously, a single global loss-target ran for the entire",
                "//      simulation, so a second fertiliser application (e.g. from another",
                "//      Manager rule such as \"Fertilise at sowing\", in a later season) just",
                "//      \"topped up\" the original event's leftover target instead of starting",
                "//      its own fresh one. This version detects a NEW season whenever more",
                "//      than SeasonGapDays have passed since urea was last added; a fresh",
                "//      addition within that gap is treated as a new, independent episode",
                "//      with its own full Model-2 season-total target. Additions that occur",
                "//      close together (e.g. split applications within the same season) are",
                "//      treated as topping up the SAME still-open episode.",
                "//",
                "// Output: Desktop\\NH3_Wheat_Output.csv (same file, extra \"Episode\" column).",
                "// ============================================================================",
                "",
                "using System;",
                "using System.IO;",
                "using Models.Core;",
                "using Models.Soils;",
                "using Models.Soils.Nutrients;",
                "",
                "namespace Models",
                "{",
                "    [Serializable]",
                "    public class Script : Model",
                "    {",
                "        [Link] private Clock Clock = null;",
                "        [Link] private INutrient Nutrient = null;",
                "",
                "        [Description(\"Tillage system: 0 = conservation, 1 = conventional\")]",
                "        public int TillageSystem { get; set; } = 0;",
                "",
                "        [Description(\"Basal-nitrogen-timing level, ordinal 1 (80% basal) to 4 (0% basal / fully sensor-guided)\")]",
                "        public int TimingLevel { get; set; } = 1;",
                "",
                "        [Description(\"Nitrogen source/placement index: 1-5 (S1..S5)\")]",
                "        public int SourceIndex { get; set; } = 1;",
                "",
                "        [Description(\"Minimum increase in surface urea pool (kg N/ha) to be treated as a fertiliser application\")]",
                "        public double DetectionThreshold { get; set; } = 0.5;",
                "",
                "        [Description(\"Days of no urea addition after which the NEXT addition is treated as a new season (not a top-up)\")]",
                "        public double SeasonGapDays { get; set; } = 60.0;",
                "",
                "        [Description(\"Daily loss rate constant, k (per day)\")]",
                "        public double K { get; set; } = 0.20;",
                "",
                "        private const double Intercept = 27.25;",
                "        private const double bTillage  = 0.20;",
                "        private const double bTiming   = -5.61;",
                "        private static readonly double[] bSource = { 0.0, 2.59, 3.27, 4.45, 3.52 };",
                "",
                "        private double previousUreaPool = -1;",
                "        private double cumulativeLoss = 0.0;",
                "        private double seasonTotal = 0.0;",
                "        private DateTime episodeStartDate;",
                "        private DateTime? lastAdditionDate = null;",
                "        private int episodeNumber = 0;",
                "        private bool tracking = false;",
                "        private string outputPath;",
                "",
                "        [EventSubscribe(\"StartOfSimulation\")]",
                "        private void OnStartOfSimulation(object sender, EventArgs e)",
                "        {",
                "            outputPath = Path.Combine(",
                "                Environment.GetFolderPath(Environment.SpecialFolder.Desktop),",
                "                \"NH3_Wheat_Output.csv\");",
                "",
                "            File.WriteAllText(outputPath,",
                "                \"Date,UreaPool_kgha,NH4Pool_kgha,LossThisEvent_kgha,CumulativeLoss_kgha,SeasonTotalPrediction_kgha,Episode,NewUreaDetected\" + Environment.NewLine);",
                "",
                "            previousUreaPool = -1;",
                "            cumulativeLoss = 0.0;",
                "            seasonTotal = 0.0;",
                "            lastAdditionDate = null;",
                "            episodeNumber = 0;",
                "            tracking = false;",
                "        }",
                "",
                "        [EventSubscribe(\"DoManagement\")]",
                "        private void OnDoManagement(object sender, EventArgs e)",
                "        {",
                "            double currentUrea = Nutrient.Urea.kgha[0];",
                "            bool newUreaDetected = false;",
                "",
                "            if (previousUreaPool < 0)",
                "            {",
                "                previousUreaPool = currentUrea;",
                "            }",
                "            else",
                "            {",
                "                double increase = currentUrea - previousUreaPool;",
                "",
                "                if (increase > DetectionThreshold)",
                "                {",
                "                    newUreaDetected = true;",
                "",
                "                    bool isNewSeason = (lastAdditionDate == null) ||",
                "                        (Clock.Today - lastAdditionDate.Value).TotalDays > SeasonGapDays;",
                "",
                "                    if (isNewSeason)",
                "                    {",
                "                        // Start a brand-new episode with its own fresh target.",
                "                        episodeNumber++;",
                "                        int sIdx = Math.Max(1, Math.Min(SourceIndex, 5)) - 1;",
                "                        seasonTotal = Intercept + bTillage * TillageSystem + bTiming * TimingLevel + bSource[sIdx];",
                "                        episodeStartDate = Clock.Today;",
                "                        cumulativeLoss = 0.0;",
                "                        tracking = true;",
                "                    }",
                "                    // else: this is a top-up within the same still-open episode;",
                "                    // seasonTotal, episodeStartDate and cumulativeLoss are left as-is.",
                "",
                "                    lastAdditionDate = Clock.Today;",
                "                }",
                "",
                "                previousUreaPool = currentUrea;",
                "            }",
                "",
                "            // Remove today's predicted increment of loss from the AMMONIUM pool.",
                "            double lossThisEvent = 0.0;",
                "            if (tracking)",
                "            {",
                "                double daysSince = (Clock.Today - episodeStartDate).TotalDays;",
                "                if (daysSince >= 0)",
                "                {",
                "                    double cumulativeTarget = seasonTotal * (1 - Math.Exp(-K * daysSince));",
                "                    double increment = Math.Max(0.0, cumulativeTarget - cumulativeLoss);",
                "                    double availableNH4 = Nutrient.NH4.kgha[0];",
                "                    double removed = Math.Min(increment, availableNH4);",
                "",
                "                    Nutrient.NH4.kgha[0] -= removed;",
                "                    cumulativeLoss += removed;",
                "                    lossThisEvent = removed;",
                "                }",
                "            }",
                "",
                "            string line = string.Join(\",\",",
                "                Clock.Today.ToString(\"yyyy-MM-dd\"),",
                "                Nutrient.Urea.kgha[0].ToString(\"F3\"),",
                "                Nutrient.NH4.kgha[0].ToString(\"F3\"),",
                "                lossThisEvent.ToString(\"F3\"),",
                "                cumulativeLoss.ToString(\"F3\"),",
                "                seasonTotal.ToString(\"F3\"),",
                "                episodeNumber.ToString(),",
                "                newUreaDetected ? \"YES\" : \"\");",
                "",
                "            File.AppendAllText(outputPath, line + Environment.NewLine);",
                "        }",
                "    }",
                "}",
                ""
              ],
              "Parameters": [
                {
                  "Key": "TillageSystem",
                  "Value": "0"
                },
                {
                  "Key": "TimingLevel",
                  "Value": "1"
                },
                {
                  "Key": "SourceIndex",
                  "Value": "1"
                },
                {
                  "Key": "DetectionThreshold",
                  "Value": "0.5"
                },
                {
                  "Key": "SeasonGapDays",
                  "Value": "60"
                },
                {
                  "Key": "K",
                  "Value": "0.2"
                }
              ],
              "Name": "Manager",
              "ResourceName": null,
              "Children": [],
              "Enabled": true,
              "ReadOnly": false
            },
            {
              "$type": "Models.Manager, Models",
              "CodeArray": [
                "// ============================================================================",
                "// RiceAmmoniaVolatilisation_v4.cs",
                "// APSIM Next Generation Manager script",
                "//",
                "// Implements Model 1 from the manuscript (Section 3.1):",
                "//   NH3-N loss (kg/ha, season total) = 7.625 + 0.0483*N_rate + 0.603*T_level",
                "//   (R2 = 0.943, RMSE = 0.69 kg/ha, n = 16)",
                "//",
                "// This version incorporates every fix discovered while debugging the wheat",
                "// (Model 2) coupling, applied from the start rather than iteratively:",
                "//",
                "//   1. Detects fertiliser application by watching the UREA pool for an",
                "//      upward jump - NOT by subscribing to a \"FertiliserApplied\" event",
                "//      (that event's argument-type name varies across APSIM versions and",
                "//      caused repeated compile errors during the wheat testing).",
                "//   2. Removes the predicted volatilisation loss from the AMMONIUM pool",
                "//      ([Nutrient].NH4.kgha[0]), not the urea pool - because our loss",
                "//      logic would otherwise compete with APSIM's own built-in urea",
                "//      hydrolysis for the same finite urea pool and under-count the loss",
                "//      (this is exactly what happened on the first wheat test).",
                "//   3. Supports MULTIPLE independent fertiliser episodes within one run",
                "//      (e.g. repeated applications across seasons), using a time-gap rule:",
                "//      a new urea addition starts a fresh loss-target episode only if more",
                "//      than SeasonGapDays have passed since urea was last added; additions",
                "//      closer together than that are treated as topping up the same",
                "//      still-open episode.",
                "//   4. Writes output directly to a CSV file on the Desktop using",
                "//      System.IO, bypassing APSIM's Report component entirely - this",
                "//      avoided an unresolved \"unknown model or property\" limitation that",
                "//      affected custom Manager-script properties in Report on the tested",
                "//      APSIM build.",
                "//",
                "// IMPORTANT CAVEAT (carried over from the manuscript, Section 6.2): the",
                "// TemperatureLevel input below is the ORDINAL 1-4 temperature-gradient-",
                "// tunnel category from the source thesis, not a continuous, real-world",
                "// temperature. Ideally, replace this with a re-fitted, continuous-",
                "// temperature version of Model 1 once you have simulated",
                "// [ISoilTemperature] (or canopy/air temperature) output from a real run,",
                "// by regressing the original 16 observed values against that continuous",
                "// variable instead of the ordinal category.",
                "//",
                "// HOW TO USE:",
                "//   1. Add a Manager node under your rice Zone/Field (right-click Zone ->",
                "//      Add Model -> Manager).",
                "//   2. Paste this entire file (from \"using System;\" onward) into its",
                "//      Script tab, replacing the default template.",
                "//   3. Set NRate and TemperatureLevel in the Properties panel to match the",
                "//      scenario you want to simulate.",
                "//   4. No Report node changes are needed - this script does not rely on",
                "//      Report at all. You can safely ignore or delete any Report node",
                "//      variable list that references this Manager's properties.",
                "//   5. Run. Check Desktop\\NH3_Rice_Output.csv afterward.",
                "// ============================================================================",
                "",
                "using System;",
                "using System.IO;",
                "using Models.Core;",
                "using Models.Soils;",
                "using Models.Soils.Nutrients;",
                "",
                "namespace Models",
                "{",
                "    [Serializable]",
                "    public class Script : Model",
                "    {",
                "        [Link] private Clock Clock = null;",
                "        [Link] private INutrient Nutrient = null;",
                "",
                "        // ---------------- User-set scenario inputs ----------------",
                "        [Description(\"Nitrogen rate applied (kg N/ha)\")]",
                "        public double NRate { get; set; } = 120.0;",
                "",
                "        [Description(\"Ordinal temperature level, 1 (ambient) to 4 (most elevated) - see header caveat\")]",
                "        public int TemperatureLevel { get; set; } = 1;",
                "",
                "        [Description(\"Minimum increase in surface urea pool (kg N/ha) to be treated as a new fertiliser application\")]",
                "        public double DetectionThreshold { get; set; } = 0.5;",
                "",
                "        [Description(\"Days of no urea addition after which the NEXT addition starts a new episode rather than topping up the current one\")]",
                "        public double SeasonGapDays { get; set; } = 60.0;",
                "",
                "        // ---------------- Internal state ----------------",
                "        private double previousUreaPool = -1;",
                "        private double cumulativeLoss = 0.0;",
                "        private double seasonTotal = 0.0;",
                "        private DateTime episodeStartDate;",
                "        private DateTime? lastAdditionDate = null;",
                "        private int episodeNumber = 0;",
                "        private bool tracking = false;",
                "        private string outputPath;",
                "",
                "        [EventSubscribe(\"StartOfSimulation\")]",
                "        private void OnStartOfSimulation(object sender, EventArgs e)",
                "        {",
                "            outputPath = Path.Combine(",
                "                Environment.GetFolderPath(Environment.SpecialFolder.Desktop),",
                "                \"NH3_Rice_Output.csv\");",
                "",
                "            File.WriteAllText(outputPath,",
                "                \"Date,UreaPool_kgha,NH4Pool_kgha,LossThisEvent_kgha,CumulativeLoss_kgha,SeasonTotalPrediction_kgha,Episode,NewUreaDetected\" + Environment.NewLine);",
                "",
                "            previousUreaPool = -1;",
                "            cumulativeLoss = 0.0;",
                "            seasonTotal = 0.0;",
                "            lastAdditionDate = null;",
                "            episodeNumber = 0;",
                "            tracking = false;",
                "        }",
                "",
                "        [EventSubscribe(\"DoManagement\")]",
                "        private void OnDoManagement(object sender, EventArgs e)",
                "        {",
                "            double currentUrea = Nutrient.Urea.kgha[0];",
                "            bool newUreaDetected = false;",
                "",
                "            if (previousUreaPool < 0)",
                "            {",
                "                previousUreaPool = currentUrea;",
                "            }",
                "            else",
                "            {",
                "                double increase = currentUrea - previousUreaPool;",
                "",
                "                if (increase > DetectionThreshold)",
                "                {",
                "                    newUreaDetected = true;",
                "",
                "                    bool isNewSeason = (lastAdditionDate == null) ||",
                "                        (Clock.Today - lastAdditionDate.Value).TotalDays > SeasonGapDays;",
                "",
                "                    if (isNewSeason)",
                "                    {",
                "                        episodeNumber++;",
                "                        // Model 1: Lmax = 7.625 + 0.0483*N + 0.603*T   (Section 3.1)",
                "                        seasonTotal = 7.625 + 0.0483 * NRate + 0.603 * TemperatureLevel;",
                "                        episodeStartDate = Clock.Today;",
                "                        cumulativeLoss = 0.0;",
                "                        tracking = true;",
                "                    }",
                "                    // else: top-up within the same still-open episode; seasonTotal,",
                "                    // episodeStartDate and cumulativeLoss are left unchanged.",
                "",
                "                    lastAdditionDate = Clock.Today;",
                "                }",
                "",
                "                previousUreaPool = currentUrea;",
                "            }",
                "",
                "            // Remove today's predicted increment of loss from the ammonium pool.",
                "            double lossThisEvent = 0.0;",
                "            if (tracking)",
                "            {",
                "                double daysSince = (Clock.Today - episodeStartDate).TotalDays;",
                "                if (daysSince >= 0)",
                "                {",
                "                    // Same exponential-rise-to-maximum shape as the wheat script,",
                "                    // with the rate constant scaled by temperature level exactly as",
                "                    // in the manuscript's Section 7 (rice) calibration:",
                "                    //   k0 = 0.230/day at T1, k = k0*(1+alpha*(T-1)), alpha = 0.143",
                "                    double k0 = 0.230;",
                "                    double alpha = 0.143;",
                "                    double k = k0 * (1 + alpha * (TemperatureLevel - 1));",
                "",
                "                    double cumulativeTarget = seasonTotal * (1 - Math.Exp(-k * daysSince));",
                "                    double increment = Math.Max(0.0, cumulativeTarget - cumulativeLoss);",
                "                    double availableNH4 = Nutrient.NH4.kgha[0];",
                "                    double removed = Math.Min(increment, availableNH4);",
                "",
                "                    Nutrient.NH4.kgha[0] -= removed;",
                "                    cumulativeLoss += removed;",
                "                    lossThisEvent = removed;",
                "                }",
                "            }",
                "",
                "            string line = string.Join(\",\",",
                "                Clock.Today.ToString(\"yyyy-MM-dd\"),",
                "                Nutrient.Urea.kgha[0].ToString(\"F3\"),",
                "                Nutrient.NH4.kgha[0].ToString(\"F3\"),",
                "                lossThisEvent.ToString(\"F3\"),",
                "                cumulativeLoss.ToString(\"F3\"),",
                "                seasonTotal.ToString(\"F3\"),",
                "                episodeNumber.ToString(),",
                "                newUreaDetected ? \"YES\" : \"\");",
                "",
                "            File.AppendAllText(outputPath, line + Environment.NewLine);",
                "        }",
                "    }",
                "}"
              ],
              "Parameters": [
                {
                  "Key": "NRate",
                  "Value": "120"
                },
                {
                  "Key": "TemperatureLevel",
                  "Value": "1"
                },
                {
                  "Key": "DetectionThreshold",
                  "Value": "0.5"
                },
                {
                  "Key": "SeasonGapDays",
                  "Value": "60"
                }
              ],
              "Name": "Manager1",
              "ResourceName": null,
              "Children": [],
              "Enabled": true,
              "ReadOnly": false
            }
          ],
          "Enabled": true,
          "ReadOnly": false
        },
        {
          "$type": "Models.Graph, Models",
          "Caption": null,
          "Axis": [
            {
              "$type": "APSIM.Shared.Graphing.Axis, APSIM.Shared",
              "Title": "Date",
              "Position": 3,
              "Inverted": false,
              "CrossesAtZero": false,
              "LabelOnOneLine": false,
              "Minimum": null,
              "Maximum": null,
              "Interval": null
            },
            {
              "$type": "APSIM.Shared.Graphing.Axis, APSIM.Shared",
              "Title": null,
              "Position": 0,
              "Inverted": false,
              "CrossesAtZero": false,
              "LabelOnOneLine": false,
              "Minimum": null,
              "Maximum": null,
              "Interval": null
            }
          ],
          "LegendPosition": 0,
          "LegendOrientation": 0,
          "AnnotationLocation": 0,
          "DisabledSeries": [],
          "LegendOutsideGraph": false,
          "Name": "Graph",
          "ResourceName": null,
          "Children": [
            {
              "$type": "Models.Series, Models",
              "Type": 1,
              "XAxis": 3,
              "YAxis": 0,
              "ColourArgb": -16777216,
              "FactorToVaryColours": null,
              "FactorToVaryMarkers": null,
              "FactorToVaryLines": null,
              "Marker": 0,
              "MarkerSize": 0,
              "Line": 0,
              "LineThickness": 0,
              "TableName": "Report",
              "XFieldName": "Clock.Today",
              "YFieldName": "Wheat.Grain.Total.Wt",
              "X2FieldName": null,
              "Y2FieldName": null,
              "ShowInLegend": false,
              "IncludeSeriesNameInLegend": false,
              "Cumulative": false,
              "CumulativeX": false,
              "Filter": null,
              "Name": "Series",
              "ResourceName": null,
              "Children": [],
              "Enabled": true,
              "ReadOnly": false
            }
          ],
          "Enabled": true,
          "ReadOnly": false
        }
      ],
      "Enabled": true,
      "ReadOnly": false
    },
    {
      "$type": "Models.Storage.DataStore, Models",
      "CustomFileName": null,
      "Name": "DataStore",
      "ResourceName": null,
      "Children": [],
      "Enabled": true,
      "ReadOnly": false
    }
  ],
  "Enabled": true,
  "ReadOnly": false
}