Пример #1
0
        /// <summary>Reallocate the Biomass Type.</summary>
        public void Calculate(IArbitration[] Organs, BiomassArbitrationType BAT, IArbitrationMethod arbitrationMethod)
        {
            double BiomassReallocated = 0;

            if (BAT.TotalReallocationSupply > 0.00000000001)
            {
                arbitrationMethod.DoAllocation(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 = BAT.Reallocation.Sum();
            }
        }
Пример #2
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;
            }
        }
Пример #3
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");
                    }
                }
            }
        }
Пример #4
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;
            }
        }
Пример #5
0
 /// <summary>Clears this instance.</summary>
 public void Clear()
 {
     DM = null;
     N = null;
 }
Пример #6
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);
                }
            }
        }
Пример #7
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;
            }
        }
Пример #8
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;
                    }
                }
            }
        }
Пример #9
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);
            }
        }
Пример #10
0
 /// <summary>Allocate the nutrient allocations.</summary>
 /// <param name="Organs">The organs.</param>
 /// <param name="N">The biomass arbitration type.</param>
 /// <param name="method">The arbitration method.</param>
 public void Calculate(IArbitration[] Organs, BiomassArbitrationType N, IArbitrationMethod method)
 {
     Leaf.UpdateArea();
 }
Пример #11
0
    private void PrioritythenRelativeAllocation(List <Organ> 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.Count; 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
        for (int i = 0; i < Organs.Count; 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(NotAllocated * BAT.RelativeNonStructuralDemand[i], NonStructuralRequirement);
                BAT.NonStructuralAllocation[i] += NonStructuralAllocation;
                NotAllocated   -= NonStructuralAllocation;
                TotalAllocated += NonStructuralAllocation;
            }
        }
    }
Пример #12
0
    virtual public void DoFixation(List <Organ> Organs, BiomassArbitrationType BAT, string Option)
    {
        double BiomassFixed = 0;

        if (BAT.TotalFixationSupply > 0.00000000001)
        {
            // Calculate how much fixation each demanding organ is allocated based on relative demands
            if (string.Compare(Option, "RelativeAllocation", true) == 0)
            {
                RelativeAllocation(Organs, BAT.TotalFixationSupply, ref BiomassFixed, BAT);
            }
            if (string.Compare(Option, "PriorityAllocation", true) == 0)
            {
                PriorityAllocation(Organs, BAT.TotalFixationSupply, ref BiomassFixed, BAT);
            }
            if (string.Compare(Option, "PrioritythenRelativeAllocation", true) == 0)
            {
                PrioritythenRelativeAllocation(Organs, BAT.TotalFixationSupply, ref BiomassFixed, BAT);
            }

            // Then calculate how much is fixed from each supplying organ based on relative fixation supply
            if (BiomassFixed > 0)
            {
                for (int i = 0; i < Organs.Count; 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 = MathUtility.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.Count; 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.Count; 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.Count; 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.  Check partitioning coefficients are giving realistic nodule size and that FixationRatePotential is realistic");
                    }
                }
            }
        }
    }
Пример #13
0
    virtual public void DoSetup(List <Organ> Organs, ref BiomassArbitrationType BAT)
    {
        //Creat Biomass variable class
        BAT = new BiomassArbitrationType(Organs.Count);

        // 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.Count; i++)
        {
            BiomassSupplyType Supply = Organs[i].NSupply;
            BAT.ReallocationSupply[i]    = Supply.Reallocation;
            BAT.UptakeSupply[i]          = Supply.Uptake;
            BAT.FixationSupply[i]        = Supply.Fixation;
            BAT.RetranslocationSupply[i] = Supply.Retranslocation;
            BAT.Start += Organs[i].Live.N + Organs[i].Dead.N;
        }

        BAT.TotalReallocationSupply    = MathUtility.Sum(BAT.ReallocationSupply);
        BAT.TotalUptakeSupply          = MathUtility.Sum(BAT.UptakeSupply);
        BAT.TotalFixationSupply        = MathUtility.Sum(BAT.FixationSupply);
        BAT.TotalRetranslocationSupply = MathUtility.Sum(BAT.RetranslocationSupply);

        for (int i = 0; i < Organs.Count; 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    = MathUtility.Sum(BAT.StructuralDemand);
        BAT.TotalMetabolicDemand     = MathUtility.Sum(BAT.MetabolicDemand);
        BAT.TotalNonStructuralDemand = MathUtility.Sum(BAT.NonStructuralDemand);
        BAT.TotalPlantDemand         = BAT.TotalStructuralDemand + BAT.TotalMetabolicDemand + BAT.TotalNonStructuralDemand;

        DM.TotalStructuralAllocation    = 0;
        DM.TotalMetabolicAllocation     = 0;
        DM.TotalNonStructuralAllocation = 0;

        //Set relative N demands of each organ
        for (int i = 0; i < Organs.Count; 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;
            }
        }
    }
Пример #14
0
    virtual public void DoDMSetup(List <Organ> Organs)
    {
        //Creat Drymatter variable class
        DM = new BiomassArbitrationType(Organs.Count);

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

        // GET SUPPLIES AND CALCULATE TOTAL
        for (int i = 0; i < Organs.Count; i++)
        {
            BiomassSupplyType Supply = Organs[i].DMSupply;
            //BiomassSupplyType Supply = null;
            //Activator.CreateInstance(BiomassSupplyType, ("Organs[i].DMSupply", ,);
            DM.ReallocationSupply[i]    = Supply.Reallocation;
            DM.UptakeSupply[i]          = Supply.Uptake;
            DM.FixationSupply[i]        = Supply.Fixation;
            DM.RetranslocationSupply[i] = Supply.Retranslocation;
            //double _dead;
            //Organs[i].My.Get("Dead.Wt", out _dead);
            DM.Start += Organs[i].Live.Wt + Organs[i].Dead.Wt;
        }

        DM.TotalReallocationSupply    = MathUtility.Sum(DM.ReallocationSupply);
        DM.TotalUptakeSupply          = MathUtility.Sum(DM.UptakeSupply);
        DM.TotalFixationSupply        = MathUtility.Sum(DM.FixationSupply);
        DM.TotalRetranslocationSupply = MathUtility.Sum(DM.RetranslocationSupply);

        // SET OTHER ORGAN VARIABLES AND CALCULATE TOTALS
        for (int i = 0; i < Organs.Count; i++)
        {
            BiomassPoolType Demand = Organs[i].DMDemand;
            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    = MathUtility.Sum(DM.StructuralDemand);
        DM.TotalMetabolicDemand     = MathUtility.Sum(DM.MetabolicDemand);
        DM.TotalNonStructuralDemand = MathUtility.Sum(DM.NonStructuralDemand);
        DM.TotalPlantDemand         = DM.TotalStructuralDemand + DM.TotalMetabolicDemand + DM.TotalNonStructuralDemand;

        DM.TotalStructuralAllocation    = 0;
        DM.TotalMetabolicAllocation     = 0;
        DM.TotalNonStructuralAllocation = 0;

        //Set relative N demands of each organ
        for (int i = 0; i < Organs.Count; 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;
            }
        }
    }
Пример #15
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);
            }
        }
Пример #16
0
        /// <summary>Does the uptake from the specified zone.</summary>
        /// <param name="BAT">The bat.</param>
        /// <param name="MyZone">The zone.</param>
        public virtual void DoPotentialNutrientUptake(ref BiomassArbitrationType BAT, ZoneWaterAndN MyZone)
        {
            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;
                double[] organNH4Supply;

                Organs[i].CalcNSupply(MyZone, out organNO3Supply, out organNH4Supply);

                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
                }

                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);
            }
        }
Пример #17
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;
                    }
                }
            }
        }
Пример #18
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;
         }
     }
 }
        /// <summary>Does the fixation.</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="BAT">The bat.</param>
        /// <param name="arbitrationMethod">The option.</param>
        public void Calculate(IArbitration[] Organs, BiomassArbitrationType BAT, IArbitrationMethod arbitrationMethod)
        {
            double BiomassFixed = 0;

            if (BAT.TotalFixationSupply > 0.00000000001)
            {
                arbitrationMethod.DoAllocation(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;
                var DM = Arbitrator.DM;
                // 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 StorageDM allocation to cover the cost
                    double UnallocatedRespirationCost = DM.TotalRespiration - DM.SinkLimitation;
                    if (MathUtilities.IsGreaterThan(DM.TotalStorageAllocation, 0))
                    {
                        double Costmet = 0;
                        for (int i = 0; i < Organs.Length; i++)
                        {
                            double proportion = DM.StorageAllocation[i] / DM.TotalStorageAllocation;
                            double Clawback   = Math.Min(UnallocatedRespirationCost * proportion, DM.StorageAllocation[i]);
                            DM.StorageAllocation[i] -= Clawback;
                            Costmet += Clawback;
                        }
                        UnallocatedRespirationCost -= Costmet;
                    }
                    if (UnallocatedRespirationCost == 0)
                    {
                    }  //All cost accounted for
                    else
                    {//Remobilise more Non-structural DM to cover the cost
                        if (DM.TotalRetranslocationSupply > 0)
                        {
                            double Costmet = 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;
                                Costmet += DMRetranslocated;
                            }
                            UnallocatedRespirationCost -= Costmet;
                        }
                        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");
                        }
                    }
                }
            }
        }
Пример #20
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;
 }