private void OnSimulationCommencing(object sender, EventArgs e)
        {
            bool   ParentOrganIdentified = false;
            IModel ParentClass           = this.Parent;

            while (!ParentOrganIdentified)
            {
                if (ParentClass is IArbitration)
                {
                    parentOrgan           = ParentClass as IArbitration;
                    ParentOrganIdentified = true;
                    if (ParentClass is IPlant)
                    {
                        throw new Exception(Name + "cannot find parent organ to get Structural and Storage N status");
                    }
                }
                ParentClass = ParentClass.Parent;
            }
        }
Example #2
0
        /// <summary>Does the retranslocation.</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="BAT">The bat.</param>
        /// <param name="Option">The option.</param>
        public virtual void DoRetranslocation(IArbitration[] Organs, BiomassArbitrationType BAT, ArbitrationType Option)
        {
            double BiomassRetranslocated = 0;
            if (BAT.TotalRetranslocationSupply > 0.00000000001)
            {
                // Calculate how much retranslocation N (and associated biomass) each demanding organ is allocated based on relative demands
                if (Option == ArbitrationType.RelativeAllocation)
                    RelativeAllocation(Organs, BAT.TotalRetranslocationSupply, ref BiomassRetranslocated, BAT);
                if (Option == ArbitrationType.PriorityAllocation)
                    PriorityAllocation(Organs, BAT.TotalRetranslocationSupply, ref BiomassRetranslocated, BAT);
                if (Option == ArbitrationType.PriorityThenRelativeAllocation)
                    PrioritythenRelativeAllocation(Organs, BAT.TotalRetranslocationSupply, ref BiomassRetranslocated, BAT);
                if (Option == ArbitrationType.RelativeAllocationSinglePass)
                    RelativeAllocationSinglePass(Organs, BAT.TotalRetranslocationSupply, ref BiomassRetranslocated, BAT);

                // Then calculate how much N (and associated biomass) is retranslocated from each supplying organ based on relative retranslocation supply
                for (int i = 0; i < Organs.Length; i++)
                {
                    if (BAT.RetranslocationSupply[i] > 0.00000000001)
                    {
                        double RelativeSupply = BAT.RetranslocationSupply[i] / BAT.TotalRetranslocationSupply;
                        BAT.Retranslocation[i] += BiomassRetranslocated * RelativeSupply;
                    }
                }
            }
        }
Example #3
0
        /// <summary>Does the nutrient set up.</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="N">The bat.</param>
        public virtual void DoNutrientSetUp(IArbitration[] Organs, ref BiomassArbitrationType N)
        {
            //Creat Biomass variable class
            N = new BiomassArbitrationType(Organs.Length);
            N.BiomassType = "N";

            // GET ALL INITIAL STATE VARIABLES FOR MASS BALANCE CHECKS
            N.Start = 0;

            // GET ALL SUPPLIES AND DEMANDS AND CALCULATE TOTALS
            for (int i = 0; i < Organs.Length; i++)
            {
                BiomassSupplyType Supply = Organs[i].NSupply;
                N.ReallocationSupply[i] = Supply.Reallocation;
                //N.UptakeSupply[i] = Supply.Uptake;             This is done on DoNutrientUptakeCalculations
                N.FixationSupply[i] = Supply.Fixation;
                N.RetranslocationSupply[i] = Supply.Retranslocation;
                N.Start += Organs[i].N;
            }

            N.TotalReallocationSupply = MathUtilities.Sum(N.ReallocationSupply);
            //N.TotalUptakeSupply = MathUtilities.Sum(N.UptakeSupply);       This is done on DoNutrientUptakeCalculations
            N.TotalFixationSupply = MathUtilities.Sum(N.FixationSupply);
            N.TotalRetranslocationSupply = MathUtilities.Sum(N.RetranslocationSupply);
            N.TotalPlantSupply = N.TotalReallocationSupply + N.TotalUptakeSupply + N.TotalFixationSupply + N.TotalRetranslocationSupply;

            for (int i = 0; i < Organs.Length; i++)
            {
                BiomassPoolType Demand = Organs[i].NDemand;
                if (MathUtilities.IsLessThan(Demand.Structural, 0))
                    throw new Exception(Organs[i].Name + " is returning a negative Structural N demand.  Check your parameterisation");
                if (MathUtilities.IsLessThan(Demand.NonStructural, 0))
                    throw new Exception(Organs[i].Name + " is returning a negative NonStructural N demand.  Check your parameterisation");
                if (MathUtilities.IsLessThan(Demand.Metabolic, 0))
                    throw new Exception(Organs[i].Name + " is returning a negative Metabolic N demand.  Check your parameterisation");
                N.StructuralDemand[i] = Organs[i].NDemand.Structural;
                N.MetabolicDemand[i] = Organs[i].NDemand.Metabolic;
                N.NonStructuralDemand[i] = Organs[i].NDemand.NonStructural;
                N.TotalDemand[i] = N.StructuralDemand[i] + N.MetabolicDemand[i] + N.NonStructuralDemand[i];

                N.Reallocation[i] = 0;
                N.Uptake[i] = 0;
                N.Fixation[i] = 0;
                N.Retranslocation[i] = 0;
                N.StructuralAllocation[i] = 0;
                N.MetabolicAllocation[i] = 0;
                N.NonStructuralAllocation[i] = 0;
            }

            N.TotalStructuralDemand = MathUtilities.Sum(N.StructuralDemand);
            N.TotalMetabolicDemand = MathUtilities.Sum(N.MetabolicDemand);
            N.TotalNonStructuralDemand = MathUtilities.Sum(N.NonStructuralDemand);
            N.TotalPlantDemand = N.TotalStructuralDemand + N.TotalMetabolicDemand + N.TotalNonStructuralDemand;

            N.TotalStructuralAllocation = 0;
            N.TotalMetabolicAllocation = 0;
            N.TotalNonStructuralAllocation = 0;

            //Set relative N demands of each organ
            for (int i = 0; i < Organs.Length; i++)
            {
                if (N.TotalStructuralDemand > 0)
                    N.RelativeStructuralDemand[i] = N.StructuralDemand[i] / N.TotalStructuralDemand;
                if (N.TotalMetabolicDemand > 0)
                    N.RelativeMetabolicDemand[i] = N.MetabolicDemand[i] / N.TotalMetabolicDemand;
                if (N.TotalNonStructuralDemand > 0)
                    N.RelativeNonStructuralDemand[i] = N.NonStructuralDemand[i] / N.TotalNonStructuralDemand;
            }
        }
Example #4
0
        /// <summary>Determines Nutrient limitations to DM allocations</summary>
        /// <param name="Organs">The organs.</param>
        public virtual void DoNutrientConstrainedDMAllocation(IArbitration[] Organs)
        {
            double PreNStressDMAllocation = DM.Allocated;
            for (int i = 0; i < Organs.Length; i++)
                N.TotalAllocation[i] = N.StructuralAllocation[i] + N.MetabolicAllocation[i] + N.NonStructuralAllocation[i];

            N.Allocated = MathUtilities.Sum(N.TotalAllocation);

            //To introduce functionality for other nutrients we need to repeat this for loop for each new nutrient type
            // Calculate posible growth based on Minimum N requirement of organs
            for (int i = 0; i < Organs.Length; i++)
            {
                if (N.TotalAllocation[i] >= N.TotalDemand[i])
                    N.ConstrainedGrowth[i] = 100000000; //given high value so where there is no N deficit in organ and N limitation to growth
                else
                    if (N.TotalAllocation[i] == 0)
                        N.ConstrainedGrowth[i] = 0;
                    else
                        N.ConstrainedGrowth[i] = N.TotalAllocation[i] / Organs[i].MinNconc;
            }

            // Reduce DM allocation below potential if insufficient N to reach Min n Conc or if DM was allocated to fixation
            for (int i = 0; i < Organs.Length; i++)
            {
                if ((DM.MetabolicAllocation[i] + DM.StructuralAllocation[i]) != 0)
                {
                    double MetabolicProportion = DM.MetabolicAllocation[i] / (DM.MetabolicAllocation[i] + DM.StructuralAllocation[i] + DM.NonStructuralAllocation[i]);
                    double StructuralProportion = DM.StructuralAllocation[i] / (DM.MetabolicAllocation[i] + DM.StructuralAllocation[i] + DM.NonStructuralAllocation[i]);
                    double NonStructuralProportion = DM.NonStructuralAllocation[i] / (DM.MetabolicAllocation[i] + DM.StructuralAllocation[i] + DM.NonStructuralAllocation[i]);
                    DM.MetabolicAllocation[i] = Math.Min(DM.MetabolicAllocation[i], N.ConstrainedGrowth[i] * MetabolicProportion);
                    DM.StructuralAllocation[i] = Math.Min(DM.StructuralAllocation[i], N.ConstrainedGrowth[i] * StructuralProportion);  //To introduce effects of other nutrients Need to include Plimited and Klimited growth in this min function
                    DM.NonStructuralAllocation[i] = Math.Min(DM.NonStructuralAllocation[i], N.ConstrainedGrowth[i] * NonStructuralProportion);  //To introduce effects of other nutrients Need to include Plimited and Klimited growth in this min function

                    //Question.  Why do I not restrain non-structural DM allocations.  I think this may be wrong and require further thought HEB 15-1-2015
                }
            }
            //Recalculated DM Allocation totals
            DM.TotalStructuralAllocation = MathUtilities.Sum(DM.StructuralAllocation);
            DM.TotalMetabolicAllocation = MathUtilities.Sum(DM.MetabolicAllocation);
            DM.TotalNonStructuralAllocation = MathUtilities.Sum(DM.NonStructuralAllocation);
            DM.Allocated = DM.TotalStructuralAllocation + DM.TotalMetabolicAllocation + DM.TotalNonStructuralAllocation;
            DM.NutrientLimitation = (PreNStressDMAllocation - DM.Allocated);
        }
Example #5
0
        /// <summary>Does the fixation.</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="BAT">The bat.</param>
        /// <param name="Option">The option.</param>
        /// <exception cref="System.Exception">Crop is trying to Fix excessive amounts of BAT.  Check partitioning coefficients are giving realistic nodule size and that FixationRatePotential is realistic</exception>
        public virtual void DoFixation(IArbitration[] Organs, BiomassArbitrationType BAT, ArbitrationType Option)
        {
            double BiomassFixed = 0;
            if (BAT.TotalFixationSupply > 0.00000000001)
            {
                // Calculate how much fixed resource each demanding organ is allocated based on relative demands
                if (Option == ArbitrationType.RelativeAllocation)
                    RelativeAllocation(Organs, BAT.TotalFixationSupply, ref BiomassFixed, BAT);
                if (Option == ArbitrationType.PriorityAllocation)
                    PriorityAllocation(Organs, BAT.TotalFixationSupply, ref BiomassFixed, BAT);
                if (Option == ArbitrationType.PriorityThenRelativeAllocation)
                    PrioritythenRelativeAllocation(Organs, BAT.TotalFixationSupply, ref BiomassFixed, BAT);
                if (Option == ArbitrationType.RelativeAllocationSinglePass)
                    RelativeAllocationSinglePass(Organs, BAT.TotalFixationSupply, ref BiomassFixed, BAT);

                //Set the sink limitation variable.  BAT.NotAllocated changes after each allocation step so it must be caught here and assigned as sink limitation
                BAT.SinkLimitation = BAT.NotAllocated;

                // Then calculate how much resource is fixed from each supplying organ based on relative fixation supply
                if (BiomassFixed > 0)
                {
                    for (int i = 0; i < Organs.Length; i++)
                    {
                        if (BAT.FixationSupply[i] > 0.00000000001)
                        {
                            double RelativeSupply = BAT.FixationSupply[i] / BAT.TotalFixationSupply;
                            BAT.Fixation[i] = BiomassFixed * RelativeSupply;
                            double Respiration = BiomassFixed * RelativeSupply * Organs[i].NFixationCost;  //Calculalte how much respirtion is associated with fixation
                            DM.Respiration[i] = Respiration; // allocate it to the organ
                        }
                        DM.TotalRespiration = MathUtilities.Sum(DM.Respiration);
                    }
                }

                // Work out the amount of biomass (if any) lost due to the cost of N fixation
                if (DM.TotalRespiration <= DM.SinkLimitation)
                { } //Cost of N fixation can be met by DM supply that was not allocated
                else
                {//claw back todays NonStructuralDM allocation to cover the cost
                    double UnallocatedRespirationCost = DM.TotalRespiration - DM.SinkLimitation;
                    if (DM.TotalNonStructuralAllocation > 0)
                    {
                        for (int i = 0; i < Organs.Length; i++)
                        {
                            double proportion = DM.NonStructuralAllocation[i] / DM.TotalNonStructuralAllocation;
                            double Clawback = Math.Min(UnallocatedRespirationCost * proportion, DM.NonStructuralAllocation[i]);
                            DM.NonStructuralAllocation[i] -= Clawback;
                            UnallocatedRespirationCost -= Clawback;
                        }
                    }
                    if (UnallocatedRespirationCost == 0)
                    { }//All cost accounted for
                    else
                    {//Remobilise more Non-structural DM to cover the cost
                        if (DM.TotalRetranslocationSupply > 0)
                        {
                            for (int i = 0; i < Organs.Length; i++)
                            {
                                double proportion = DM.RetranslocationSupply[i] / DM.TotalRetranslocationSupply;
                                double DMRetranslocated = Math.Min(UnallocatedRespirationCost * proportion, DM.RetranslocationSupply[i]);
                                DM.Retranslocation[i] += DMRetranslocated;
                                UnallocatedRespirationCost -= DMRetranslocated;
                            }
                        }
                        if (UnallocatedRespirationCost == 0)
                        { }//All cost accounted for
                        else
                        {//Start cutting into Structural and Metabolic Allocations
                            if ((DM.TotalStructuralAllocation + DM.TotalMetabolicAllocation) > 0)
                            {
                                double Costmet = 0;
                                for (int i = 0; i < Organs.Length; i++)
                                {
                                    if ((DM.StructuralAllocation[i] + DM.MetabolicAllocation[i]) > 0)
                                    {
                                        double proportion = (DM.StructuralAllocation[i] + DM.MetabolicAllocation[i]) / (DM.TotalStructuralAllocation + DM.TotalMetabolicAllocation);
                                        double StructualFraction = DM.StructuralAllocation[i] / (DM.StructuralAllocation[i] + DM.MetabolicAllocation[i]);
                                        double StructuralClawback = Math.Min(UnallocatedRespirationCost * proportion * StructualFraction, DM.StructuralAllocation[i]);
                                        double MetabolicClawback = Math.Min(UnallocatedRespirationCost * proportion * (1 - StructualFraction), DM.MetabolicAllocation[i]);
                                        DM.StructuralAllocation[i] -= StructuralClawback;
                                        DM.MetabolicAllocation[i] -= MetabolicClawback;
                                        Costmet += (StructuralClawback + MetabolicClawback);
                                    }
                                }
                                UnallocatedRespirationCost -= Costmet;
                            }
                        }
                        if (UnallocatedRespirationCost > 0.0000000001)
                            throw new Exception("Crop is trying to Fix excessive amounts of " + BAT.BiomassType +" Check partitioning coefficients are giving realistic nodule size and that FixationRatePotential is realistic");
                    }
                }
            }
        }
Example #6
0
        /// <summary>Does the dm setup.</summary>
        /// <param name="Organs">The organs.</param>
        public virtual void DoDMSetup(IArbitration[] Organs)
        {
            //Creat Drymatter variable class
            DM = new BiomassArbitrationType(Organs.Length);
            DM.BiomassType = "DM";

            // GET INITIAL STATE VARIABLES FOR MASS BALANCE CHECKS
            DM.Start = 0;
            // GET SUPPLIES AND CALCULATE TOTAL
            for (int i = 0; i < Organs.Length; i++)
            {
                BiomassSupplyType Supply = Organs[i].DMSupply;
                if (MathUtilities.IsLessThan(Supply.Fixation + Supply.Reallocation+Supply.Retranslocation+Supply.Uptake, 0))
                    throw new Exception(Organs[i].Name + " is returning a negative DM supply.  Check your parameterisation");
                DM.ReallocationSupply[i] = Supply.Reallocation;
                DM.UptakeSupply[i] = Supply.Uptake;
                DM.FixationSupply[i] = Supply.Fixation;
                DM.RetranslocationSupply[i] = Supply.Retranslocation;
                DM.Start += Organs[i].Wt;
            }

            DM.TotalReallocationSupply = MathUtilities.Sum(DM.ReallocationSupply);
            DM.TotalUptakeSupply = MathUtilities.Sum(DM.UptakeSupply);
            DM.TotalFixationSupply = MathUtilities.Sum(DM.FixationSupply);
            DM.TotalRetranslocationSupply = MathUtilities.Sum(DM.RetranslocationSupply);
            DM.TotalPlantSupply = DM.TotalReallocationSupply + DM.TotalUptakeSupply + DM.TotalFixationSupply + DM.TotalRetranslocationSupply;

            // SET OTHER ORGAN VARIABLES AND CALCULATE TOTALS
            for (int i = 0; i < Organs.Length; i++)
            {
                BiomassPoolType Demand = Organs[i].DMDemand;
                if (MathUtilities.IsLessThan(Demand.Structural, 0))
                    throw new Exception(Organs[i].Name + " is returning a negative Structural DM demand.  Check your parameterisation");
                if (MathUtilities.IsLessThan(Demand.NonStructural, 0))
                    throw new Exception(Organs[i].Name + " is returning a negative NonStructural DM demand.  Check your parameterisation");
                if (MathUtilities.IsLessThan(Demand.Metabolic, 0))
                    throw new Exception(Organs[i].Name + " is returning a negative Metabolic DM demand.  Check your parameterisation");
                DM.StructuralDemand[i] = Demand.Structural;
                DM.MetabolicDemand[i] = Demand.Metabolic;
                DM.NonStructuralDemand[i] = Demand.NonStructural;
                DM.TotalDemand[i] = DM.StructuralDemand[i] + DM.MetabolicDemand[i] + DM.NonStructuralDemand[i];

                DM.Reallocation[i] = 0;
                DM.Uptake[i] = 0;
                DM.Fixation[i] = 0;
                DM.Retranslocation[i] = 0;
                DM.StructuralAllocation[i] = 0;
                DM.MetabolicAllocation[i] = 0;
                DM.NonStructuralAllocation[i] = 0;
            }

            DM.TotalStructuralDemand = MathUtilities.Sum(DM.StructuralDemand);
            DM.TotalMetabolicDemand = MathUtilities.Sum(DM.MetabolicDemand);
            DM.TotalNonStructuralDemand = MathUtilities.Sum(DM.NonStructuralDemand);
            DM.TotalPlantDemand = DM.TotalStructuralDemand + DM.TotalMetabolicDemand + DM.TotalNonStructuralDemand;

            DM.TotalStructuralAllocation = 0;
            DM.TotalMetabolicAllocation = 0;
            DM.TotalNonStructuralAllocation = 0;
            DM.Allocated = 0;
            DM.SinkLimitation = 0;
            DM.NutrientLimitation = 0;

            //Set relative DM demands of each organ
            for (int i = 0; i < Organs.Length; i++)
            {
                if (DM.TotalStructuralDemand > 0)
                    DM.RelativeStructuralDemand[i] = DM.StructuralDemand[i] / DM.TotalStructuralDemand;
                if (DM.TotalMetabolicDemand > 0)
                    DM.RelativeMetabolicDemand[i] = DM.MetabolicDemand[i] / DM.TotalMetabolicDemand;
                if (DM.TotalNonStructuralDemand > 0)
                    DM.RelativeNonStructuralDemand[i] = DM.NonStructuralDemand[i] / DM.TotalNonStructuralDemand;
            }
        }
Example #7
0
        /// <summary>Partitions biomass between organs based on their relative demand in a single pass so non-structural always gets some if there is a non-structural demand</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="TotalSupply">The total supply.</param>
        /// <param name="TotalAllocated">The total allocated.</param>
        /// <param name="BAT">The bat.</param>
        private void RelativeAllocationSinglePass(IArbitration[] Organs, double TotalSupply, ref double TotalAllocated, BiomassArbitrationType BAT)
        {
            double NotAllocated = TotalSupply;
            ////allocate to all pools based on their relative demands
            for (int i = 0; i < Organs.Length; i++)
            {
                double StructuralRequirement = Math.Max(0, BAT.StructuralDemand[i] - BAT.StructuralAllocation[i]); //N needed to get to Minimum N conc and satisfy structural and metabolic N demands
                double MetabolicRequirement = Math.Max(0, BAT.MetabolicDemand[i] - BAT.MetabolicAllocation[i]);
                double NonStructuralRequirement = Math.Max(0, BAT.NonStructuralDemand[i] - BAT.NonStructuralAllocation[i]);
                if ((StructuralRequirement + MetabolicRequirement + NonStructuralRequirement) > 0.0)
                {
                    double StructuralFraction = BAT.TotalStructuralDemand / (BAT.TotalStructuralDemand + BAT.TotalMetabolicDemand + BAT.TotalNonStructuralDemand);
                    double MetabolicFraction = BAT.TotalMetabolicDemand / (BAT.TotalStructuralDemand + BAT.TotalMetabolicDemand + BAT.TotalNonStructuralDemand);
                    double NonStructuralFraction = BAT.TotalNonStructuralDemand / (BAT.TotalStructuralDemand + BAT.TotalMetabolicDemand + BAT.TotalNonStructuralDemand);

                    double StructuralAllocation = Math.Min(StructuralRequirement, TotalSupply * StructuralFraction * BAT.RelativeStructuralDemand[i]);
                    double MetabolicAllocation = Math.Min(MetabolicRequirement, TotalSupply * MetabolicFraction * BAT.RelativeMetabolicDemand[i]);
                    double NonStructuralAllocation = Math.Min(NonStructuralRequirement, TotalSupply * NonStructuralFraction * BAT.RelativeNonStructuralDemand[i]);

                    BAT.StructuralAllocation[i] += StructuralAllocation;
                    BAT.MetabolicAllocation[i] += MetabolicAllocation;
                    BAT.NonStructuralAllocation[i] += Math.Max(0, NonStructuralAllocation);
                    NotAllocated -= (StructuralAllocation + MetabolicAllocation + NonStructuralAllocation);
                    TotalAllocated += (StructuralAllocation + MetabolicAllocation + NonStructuralAllocation);
                }
            }
        }
Example #8
0
        /// <summary>Does the re allocation.</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="BAT">The bat.</param>
        /// <param name="Option">The option.</param>
        public virtual void DoReAllocation(IArbitration[] Organs, BiomassArbitrationType BAT, string Option)
        {
            double BiomassReallocated = 0;
            if (BAT.TotalReallocationSupply > 0.00000000001)
            {
                //Calculate how much reallocated N (and associated biomass) each demanding organ is allocated based on relative demands
                if (string.Compare(Option, "RelativeAllocation", true) == 0)
                    RelativeAllocation(Organs, BAT.TotalReallocationSupply, ref BiomassReallocated, BAT);
                if (string.Compare(Option, "PriorityAllocation", true) == 0)
                    PriorityAllocation(Organs, BAT.TotalReallocationSupply, ref BiomassReallocated, BAT);
                if (string.Compare(Option, "PrioritythenRelativeAllocation", true) == 0)
                    PrioritythenRelativeAllocation(Organs, BAT.TotalReallocationSupply, ref BiomassReallocated, BAT);

                //Then calculate how much biomass is realloced from each supplying organ based on relative reallocation supply
                for (int i = 0; i < Organs.Length; i++)
                {
                    if (BAT.ReallocationSupply[i] > 0)
                    {
                        double RelativeSupply = BAT.ReallocationSupply[i] / BAT.TotalReallocationSupply;
                        BAT.Reallocation[i] += BiomassReallocated * RelativeSupply;
                    }
                }
                BAT.TotalReallocation = MathUtilities.Sum(BAT.Reallocation);
            }
        }
Example #9
0
 /// <summary>Prioritythens the relative allocation.</summary>
 /// <param name="Organs">The organs.</param>
 /// <param name="TotalSupply">The total supply.</param>
 /// <param name="TotalAllocated">The total allocated.</param>
 /// <param name="BAT">The bat.</param>
 private void PrioritythenRelativeAllocation(IArbitration[] Organs, double TotalSupply, ref double TotalAllocated, BiomassArbitrationType BAT)
 {
     double NotAllocated = TotalSupply;
     ////First time round allocate to met priority demands of each organ
     for (int i = 0; i < Organs.Length; i++)
     {
         double StructuralRequirement = Math.Max(0.0, BAT.StructuralDemand[i] - BAT.StructuralAllocation[i]); //N needed to get to Minimum N conc and satisfy structural and metabolic N demands
         double MetabolicRequirement = Math.Max(0.0, BAT.MetabolicDemand[i] - BAT.MetabolicAllocation[i]);
         if ((StructuralRequirement + MetabolicRequirement) > 0.0)
         {
             double StructuralFraction = BAT.StructuralDemand[i] / (BAT.StructuralDemand[i] + BAT.MetabolicDemand[i]);
             double StructuralAllocation = Math.Min(StructuralRequirement, NotAllocated * StructuralFraction);
             double MetabolicAllocation = Math.Min(MetabolicRequirement, NotAllocated * (1 - StructuralFraction));
             BAT.StructuralAllocation[i] += StructuralAllocation;
             BAT.MetabolicAllocation[i] += MetabolicAllocation;
             NotAllocated -= (StructuralAllocation + MetabolicAllocation);
             TotalAllocated += (StructuralAllocation + MetabolicAllocation);
         }
     }
     // Second time round if there is still N to allocate let organs take N up to their Maximum
     double FirstPassNotallocated = NotAllocated;
     for (int i = 0; i < Organs.Length; i++)
     {
         double NonStructuralRequirement = Math.Max(0.0, BAT.NonStructuralDemand[i] - BAT.NonStructuralAllocation[i]); //N needed to take organ up to maximum N concentration, Structural, Metabolic and Luxury N demands
         if (NonStructuralRequirement > 0.0)
         {
             double NonStructuralAllocation = Math.Min(FirstPassNotallocated * BAT.RelativeNonStructuralDemand[i], NonStructuralRequirement);
             BAT.NonStructuralAllocation[i] += Math.Max(0, NonStructuralAllocation);
             NotAllocated -= NonStructuralAllocation;
             TotalAllocated += NonStructuralAllocation;
         }
     }
 }
Example #10
0
        /// <summary>Sends the potential dm allocations.</summary>
        /// <param name="Organs">The organs.</param>
        /// <exception cref="System.Exception">Mass Balance Error in Photosynthesis DM Allocation</exception>
        public virtual void SendPotentialDMAllocations(IArbitration[] Organs)
        {
            //  Allocate to meet Organs demands
            DM.TotalStructuralAllocation = MathUtilities.Sum(DM.StructuralAllocation);
            DM.TotalMetabolicAllocation = MathUtilities.Sum(DM.MetabolicAllocation);
            DM.TotalNonStructuralAllocation = MathUtilities.Sum(DM.NonStructuralAllocation);
            DM.Allocated = DM.TotalStructuralAllocation + DM.TotalMetabolicAllocation + DM.TotalNonStructuralAllocation;

            // Then check it all adds up
            if (Math.Round(DM.Allocated,8) > Math.Round(DM.TotalPlantSupply,8))
                throw new Exception("Potential DM allocation by " + this.Name + " exceeds DM supply.   Thats not really possible so something has gone a miss");
            if (Math.Round(DM.Allocated,8) > Math.Round(DM.TotalPlantDemand,8))
                throw new Exception("Potential DM allocation by " + this.Name + " exceeds DM Demand.   Thats not really possible so something has gone a miss");

            // Send potential DM allocation to organs to set this variable for calculating N demand
            for (int i = 0; i < Organs.Length; i++)
            {
                Organs[i].DMPotentialAllocation = new BiomassPoolType
                {
                    Structural = DM.StructuralAllocation[i],  //Need to seperate metabolic and structural allocations
                    Metabolic = DM.MetabolicAllocation[i],  //This wont do anything currently
                    NonStructural = DM.NonStructuralAllocation[i], //Nor will this do anything
                };
            }
        }
Example #11
0
        /// <summary>Sends the nutrient allocations.</summary>
        /// <param name="Organs">The organs.</param>
        /// <exception cref="System.Exception">
        /// -ve N Allocation
        /// or
        /// N Mass balance violated!!!!.  Daily Plant N increment is greater than N supply
        /// or
        /// N Mass balance violated!!!!  Daily Plant N increment is greater than N demand
        /// or
        /// DM Mass Balance violated!!!!  Daily Plant Wt increment is greater than Photosynthetic DM supply
        /// or
        /// DM Mass Balance violated!!!!  Daily Plant Wt increment is greater than the sum of structural DM demand, metabolic DM demand and NonStructural DM capacity
        /// </exception>
        public virtual void SendNutrientAllocations(IArbitration[] Organs)
        {
            // Send N allocations to all Plant Organs
            for (int i = 0; i < Organs.Length; i++)
            {
                if ((N.StructuralAllocation[i] < -0.00000001) || (N.MetabolicAllocation[i] < -0.00000001) || (N.NonStructuralAllocation[i] < -0.00000001))
                    throw new Exception("-ve N Allocation");
                if (N.StructuralAllocation[i] < 0.0)
                    N.StructuralAllocation[i] = 0.0;
                if (N.MetabolicAllocation[i] < 0.0)
                    N.MetabolicAllocation[i] = 0.0;
                if (N.NonStructuralAllocation[i] < 0.0)
                    N.NonStructuralAllocation[i] = 0.0;
                Organs[i].NAllocation = new BiomassAllocationType
                {
                    Structural = N.StructuralAllocation[i], //This needs to be seperated into components
                    Metabolic = N.MetabolicAllocation[i],
                    NonStructural = N.NonStructuralAllocation[i],
                    Fixation = N.Fixation[i],
                    Reallocation = N.Reallocation[i],
                    Retranslocation = N.Retranslocation[i],
                    Uptake = N.Uptake[i]
                };
            }

            //Finally Check Mass balance adds up
            N.End = 0;
            for (int i = 0; i < Organs.Length; i++)
                N.End += Organs[i].N;
            N.BalanceError = (N.End - (N.Start + N.TotalUptakeSupply + N.TotalFixationSupply));
            if (N.BalanceError > 0.000000001)
                throw new Exception("N Mass balance violated!!!!.  Daily Plant N increment is greater than N supply");
            N.BalanceError = (N.End - (N.Start + N.TotalPlantDemand));
            if (N.BalanceError > 0.000000001)
                throw new Exception("N Mass balance violated!!!!  Daily Plant N increment is greater than N demand");
            DM.End = 0;
            for (int i = 0; i < Organs.Length; i++)
                DM.End += Organs[i].Wt;
            DM.BalanceError = (DM.End - (DM.Start + DM.TotalFixationSupply));
            if (DM.BalanceError > 0.0001)
                throw new Exception("DM Mass Balance violated!!!!  Daily Plant Wt increment is greater than Photosynthetic DM supply");
            DM.BalanceError = (DM.End - (DM.Start + DM.TotalStructuralDemand + DM.TotalMetabolicDemand + DM.TotalNonStructuralDemand));
            if (DM.BalanceError > 0.0001)
                throw new Exception("DM Mass Balance violated!!!!  Daily Plant Wt increment is greater than the sum of structural DM demand, metabolic DM demand and NonStructural DM capacity");
        }
Example #12
0
 /// <summary>Sends the dm allocations.</summary>
 /// <param name="Organs">The organs.</param>
 public virtual void SendDMAllocations(IArbitration[] Organs)
 {
     // Send DM allocations to all Plant Organs
     for (int i = 0; i < Organs.Length; i++)
     {
         Organs[i].DMAllocation = new BiomassAllocationType
         {
             Respired = DM.Respiration[i],
             Reallocation = DM.Reallocation[i],
             Retranslocation = DM.Retranslocation[i],
             Structural = DM.StructuralAllocation[i],
             NonStructural = DM.NonStructuralAllocation[i],
             Metabolic = DM.MetabolicAllocation[i],
         };
     }
 }
Example #13
0
        /// <summary>Does the uptake.</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="BAT">The bat.</param>
        /// <param name="soilstate">The soilstate.</param>
        public virtual void DoPotentialNutrientUptake(IArbitration[] Organs, ref BiomassArbitrationType BAT, SoilState soilstate)
        {
            // Model can only handle one root zone at present
            ZoneWaterAndN MyZone = new ZoneWaterAndN();
            Zone ParentZone = Apsim.Parent(this, typeof(Zone)) as Zone;
            foreach (ZoneWaterAndN Z in soilstate.Zones)
                if (Z.Name == ParentZone.Name)
                    MyZone = Z;

            PotentialNO3NUptake = new double[MyZone.NO3N.Length];
            PotentialNH4NUptake = new double[MyZone.NH4N.Length];

            //Get Nuptake supply from each organ and set the PotentialUptake parameters that are passed to the soil arbitrator
            for (int i = 0; i < Organs.Length; i++)
            {
                double[] organNO3Supply = Organs[i].NO3NSupply(soilstate.Zones);
                if (organNO3Supply != null)
                {
                    PotentialNO3NUptake = MathUtilities.Add(PotentialNO3NUptake, organNO3Supply); //Add uptake supply from each organ to the plants total to tell the Soil arbitrator
                    BAT.UptakeSupply[i] = MathUtilities.Sum(organNO3Supply) * kgha2gsm;    //Populate uptakeSupply for each organ for internal allocation routines
                }

                double[] organNH4Supply = Organs[i].NH4NSupply(soilstate.Zones);
                if (organNH4Supply != null)
                {
                    PotentialNH4NUptake = MathUtilities.Add(PotentialNH4NUptake, organNH4Supply);
                    BAT.UptakeSupply[i] += MathUtilities.Sum(organNH4Supply) * kgha2gsm;
                }
            }

            //Calculate plant level supply totals.
            BAT.TotalUptakeSupply = MathUtilities.Sum(BAT.UptakeSupply);
            BAT.TotalPlantSupply = BAT.TotalReallocationSupply + BAT.TotalUptakeSupply + BAT.TotalFixationSupply + BAT.TotalRetranslocationSupply;

            //If NUsupply is greater than uptake (total demand - reallocatio nsupply) reduce the PotentialUptakes that we pass to the soil arbitrator
            if (BAT.TotalUptakeSupply > (BAT.TotalPlantDemand - BAT.TotalReallocation))
            {
                double ratio = Math.Min(1.0, (BAT.TotalPlantDemand - BAT.TotalReallocation) / BAT.TotalUptakeSupply);
                PotentialNO3NUptake = MathUtilities.Multiply_Value(PotentialNO3NUptake, ratio);
                PotentialNH4NUptake = MathUtilities.Multiply_Value(PotentialNH4NUptake, ratio);
            }
        }
Example #14
0
        /// <summary>Sends the potential dm allocations.</summary>
        /// <param name="Organs">The organs.</param>
        /// <exception cref="System.Exception">Mass Balance Error in Photosynthesis DM Allocation</exception>
        public virtual void SendPotentialDMAllocations(IArbitration[] Organs)
        {
            //  Allocate to meet Organs demands
            DM.TotalStructuralAllocation = MathUtilities.Sum(DM.StructuralAllocation);
            DM.TotalMetabolicAllocation = MathUtilities.Sum(DM.MetabolicAllocation);
            DM.TotalNonStructuralAllocation = MathUtilities.Sum(DM.NonStructuralAllocation);
            DM.Allocated = DM.TotalStructuralAllocation + DM.TotalMetabolicAllocation + DM.TotalNonStructuralAllocation;
            DM.SinkLimitation = Math.Max(0.0, DM.TotalFixationSupply + DM.TotalRetranslocationSupply + DM.TotalReallocationSupply - DM.Allocated);

            // Then check it all adds up
            DM.BalanceError = Math.Abs((DM.Allocated + DM.SinkLimitation) - (DM.TotalFixationSupply + DM.TotalRetranslocationSupply + DM.TotalReallocationSupply));
            if (DM.BalanceError > 0.0000001 & DM.TotalStructuralDemand > 0)
                throw new Exception("Mass Balance Error in Photosynthesis DM Allocation");

            // Send potential DM allocation to organs to set this variable for calculating N demand
            for (int i = 0; i < Organs.Length; i++)
            {
                Organs[i].DMPotentialAllocation = new BiomassPoolType
                {
                    Structural = DM.StructuralAllocation[i],  //Need to seperate metabolic and structural allocations
                    Metabolic = DM.MetabolicAllocation[i],  //This wont do anything currently
                    NonStructural = DM.NonStructuralAllocation[i], //Nor will this do anything
                };
            }
        }
Example #15
0
        /// <summary>Does the uptake.</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="BAT">The bat.</param>
        /// <param name="Option">The option.</param>
        public virtual void DoUptake(IArbitration[] Organs, BiomassArbitrationType BAT,  ArbitrationType Option)
        {
            double BiomassTakenUp = 0;
            if (BAT.TotalUptakeSupply > 0.00000000001)
            {
                // Calculate how much uptake N each demanding organ is allocated based on relative demands
                if (Option == ArbitrationType.RelativeAllocation)
                    RelativeAllocation(Organs, BAT.TotalUptakeSupply, ref BiomassTakenUp, BAT);
                if (Option == ArbitrationType.PriorityAllocation)
                    PriorityAllocation(Organs, BAT.TotalUptakeSupply, ref BiomassTakenUp, BAT);
                if (Option == ArbitrationType.PriorityThenRelativeAllocation)
                    PrioritythenRelativeAllocation(Organs, BAT.TotalUptakeSupply, ref BiomassTakenUp, BAT);
                if (Option == ArbitrationType.RelativeAllocationSinglePass)
                    RelativeAllocationSinglePass(Organs, BAT.TotalUptakeSupply, ref BiomassTakenUp, BAT);

                // Then calculate how much N is taken up by each supplying organ based on relative uptake supply
                for (int i = 0; i < Organs.Length; i++)
                {
                    if (BAT.UptakeSupply[i] > 0.00000000001)
                    {
                        double RelativeSupply = BAT.UptakeSupply[i] / BAT.TotalUptakeSupply;
                        BAT.Uptake[i] += BiomassTakenUp * RelativeSupply;
                    }
                }
            }
        }
Example #16
0
 /// <summary>Relatives the allocation.</summary>
 /// <param name="Organs">The organs.</param>
 /// <param name="TotalSupply">The total supply.</param>
 /// <param name="TotalAllocated">The total allocated.</param>
 /// <param name="BAT">The bat.</param>
 private void RelativeAllocation(IArbitration[] Organs, double TotalSupply, ref double TotalAllocated, BiomassArbitrationType BAT)
 {
     double NotAllocated = TotalSupply;
     ////allocate to structural and metabolic Biomass first
     for (int i = 0; i < Organs.Length; i++)
     {
         double StructuralRequirement = Math.Max(0, BAT.StructuralDemand[i] - BAT.StructuralAllocation[i]); //N needed to get to Minimum N conc and satisfy structural and metabolic N demands
         double MetabolicRequirement = Math.Max(0, BAT.MetabolicDemand[i] - BAT.MetabolicAllocation[i]);
         if ((StructuralRequirement + MetabolicRequirement) > 0.0)
         {
             double StructuralFraction = BAT.TotalStructuralDemand / (BAT.TotalStructuralDemand + BAT.TotalMetabolicDemand);
             double StructuralAllocation = Math.Min(StructuralRequirement, TotalSupply * StructuralFraction * BAT.RelativeStructuralDemand[i]);
             double MetabolicAllocation = Math.Min(MetabolicRequirement, TotalSupply * (1 - StructuralFraction) * BAT.RelativeMetabolicDemand[i]);
             BAT.StructuralAllocation[i] += StructuralAllocation;
             BAT.MetabolicAllocation[i] += MetabolicAllocation;
             NotAllocated -= (StructuralAllocation + MetabolicAllocation);
             TotalAllocated += (StructuralAllocation + MetabolicAllocation);
         }
     }
     // Second time round if there is still Biomass to allocate let organs take N up to their Maximum
     double FirstPassNotAllocated = NotAllocated;
     for (int i = 0; i < Organs.Length; i++)
     {
         double NonStructuralRequirement = Math.Max(0.0, BAT.NonStructuralDemand[i] - BAT.NonStructuralAllocation[i]); //N needed to take organ up to maximum N concentration, Structural, Metabolic and Luxury N demands
         if (NonStructuralRequirement > 0.0)
         {
             double NonStructuralAllocation = Math.Min(FirstPassNotAllocated * BAT.RelativeNonStructuralDemand[i], NonStructuralRequirement);
             BAT.NonStructuralAllocation[i] += Math.Max(0,NonStructuralAllocation);
             NotAllocated -= NonStructuralAllocation;
             TotalAllocated += NonStructuralAllocation;
         }
     }
     //Set the amount of biomass not allocated.  Note, that this value is overwritten following by each arbitration step so if it is to be used correctly
     //it must be caught in that step.  Currently only using to catch DM not allocated so we can report as sink limitaiton
     BAT.NotAllocated = NotAllocated;
 }
Example #17
0
        /// <summary>Does the nutrient set up.</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="BAT">The bat.</param>
        public virtual void DoNutrientSetUp(IArbitration[] Organs, ref BiomassArbitrationType BAT)
        {
            //Creat Biomass variable class
            BAT = new BiomassArbitrationType(Organs.Length);

            // GET ALL INITIAL STATE VARIABLES FOR MASS BALANCE CHECKS
            BAT.Start = 0;

            // GET ALL SUPPLIES AND DEMANDS AND CALCULATE TOTALS
            for (int i = 0; i < Organs.Length; i++)
            {
                BiomassSupplyType Supply = Organs[i].NSupply;
                BAT.ReallocationSupply[i] = Supply.Reallocation;
                //BAT.UptakeSupply[i] = Supply.Uptake;             This is done on DoNutrientUptakeCalculations
                BAT.FixationSupply[i] = Supply.Fixation;
                BAT.RetranslocationSupply[i] = Supply.Retranslocation;
                BAT.Start += Organs[i].TotalN;
            }

            BAT.TotalReallocationSupply = MathUtilities.Sum(BAT.ReallocationSupply);
            //BAT.TotalUptakeSupply = MathUtilities.Sum(BAT.UptakeSupply);       This is done on DoNutrientUptakeCalculations
            BAT.TotalFixationSupply = MathUtilities.Sum(BAT.FixationSupply);
            BAT.TotalRetranslocationSupply = MathUtilities.Sum(BAT.RetranslocationSupply);
            BAT.TotalPlantSupply = BAT.TotalReallocationSupply + BAT.TotalUptakeSupply + BAT.TotalFixationSupply + BAT.TotalRetranslocationSupply;

            for (int i = 0; i < Organs.Length; i++)
            {
                BiomassPoolType Demand = Organs[i].NDemand;
                BAT.StructuralDemand[i] = Organs[i].NDemand.Structural;
                BAT.MetabolicDemand[i] = Organs[i].NDemand.Metabolic;
                BAT.NonStructuralDemand[i] = Organs[i].NDemand.NonStructural;
                BAT.TotalDemand[i] = BAT.StructuralDemand[i] + BAT.MetabolicDemand[i] + BAT.NonStructuralDemand[i];

                BAT.Reallocation[i] = 0;
                BAT.Uptake[i] = 0;
                BAT.Fixation[i] = 0;
                BAT.Retranslocation[i] = 0;
                BAT.StructuralAllocation[i] = 0;
                BAT.MetabolicAllocation[i] = 0;
                BAT.NonStructuralAllocation[i] = 0;
            }

            BAT.TotalStructuralDemand = MathUtilities.Sum(BAT.StructuralDemand);
            BAT.TotalMetabolicDemand = MathUtilities.Sum(BAT.MetabolicDemand);
            BAT.TotalNonStructuralDemand = MathUtilities.Sum(BAT.NonStructuralDemand);
            BAT.TotalPlantDemand = BAT.TotalStructuralDemand + BAT.TotalMetabolicDemand + BAT.TotalNonStructuralDemand;

            BAT.TotalStructuralAllocation = 0;
            BAT.TotalMetabolicAllocation = 0;
            BAT.TotalNonStructuralAllocation = 0;

            //Set relative N demands of each organ
            for (int i = 0; i < Organs.Length; i++)
            {
                if (BAT.TotalStructuralDemand > 0)
                    BAT.RelativeStructuralDemand[i] = BAT.StructuralDemand[i] / BAT.TotalStructuralDemand;
                if (BAT.TotalMetabolicDemand > 0)
                    BAT.RelativeMetabolicDemand[i] = BAT.MetabolicDemand[i] / BAT.TotalMetabolicDemand;
                if (BAT.TotalNonStructuralDemand > 0)
                    BAT.RelativeNonStructuralDemand[i] = BAT.NonStructuralDemand[i] / BAT.TotalNonStructuralDemand;
            }
        }