/// <summary>Does the re allocation.</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="BAT">The bat.</param>
        /// <param name="arbitrator">The arbitrator.</param>
        virtual public void DoReAllocation(IArbitration[] Organs, BiomassArbitrationType BAT, IArbitrationMethod arbitrator)
        {
            double BiomassReallocated = 0;

            if (BAT.TotalReallocationSupply > 0.00000000001)
            {
                arbitrator.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 = MathUtilities.Sum(BAT.Reallocation);
            }
        }
Beispiel #2
0
        /// <summary>Relatives the allocation.</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="N">The N bat.</param>
        /// <param name="dm">The DM BAT.</param>
        public void DoRetranslocation(IArbitration[] Organs, BiomassArbitrationType N, BiomassArbitrationType dm)
        {
            double NotAllocated = N.TotalRetranslocationSupply;
            //var rootIndex = 1;
            var leafIndex   = 2;
            var rachisIndex = 3;
            var stemIndex   = 4;
            var grainIndex  = 0;

            var stemDemand   = N.StructuralDemand[stemIndex];
            var rachisDemand = N.StructuralDemand[rachisIndex];
            var leafDemand   = N.StructuralDemand[leafIndex];

            var forStem         = AllocateStructuralFromLeaf(Organs[leafIndex] as SorghumLeaf, leafIndex, stemIndex, N);
            var forRachis       = AllocateStructuralFromLeaf(Organs[leafIndex] as SorghumLeaf, leafIndex, rachisIndex, N);
            var forLeaffromStem = AllocateStructuralFromStem(stemIndex, leafIndex, N, dm, Organs[stemIndex] as GenericOrgan);
            var forLeaf         = AllocateStructuralFromLeaf(Organs[leafIndex] as SorghumLeaf, leafIndex, leafIndex, N);

            double fromRachis = AllocateStructuralFromRachis(rachisIndex, grainIndex, N, dm, Organs[rachisIndex] as GenericOrgan);
            double fromStem   = AllocateStructuralFromStem(stemIndex, grainIndex, N, dm, Organs[stemIndex] as GenericOrgan);
            double fromLeaf   = AllocateStructuralFromLeaf(Organs[leafIndex] as SorghumLeaf, leafIndex, grainIndex, N);
        }
        /// <summary>Relatives the allocation.</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="BAT">The bat.</param>
        public void DoRetranslocation(IArbitration[] Organs, BiomassArbitrationType BAT)
        {
            double NotAllocated = BAT.TotalRetranslocationSupply;
            //var rootIndex = 1;
            var leafIndex   = 2;
            var rachisIndex = 3;
            var stemIndex   = 4;
            var grainIndex  = 0;

            var stemDemand   = BAT.StructuralDemand[stemIndex];
            var rachisDemand = BAT.StructuralDemand[rachisIndex];
            var leafDemand   = BAT.StructuralDemand[leafIndex];

            var forStem         = AllocateStructuralFromLeaf(Organs[leafIndex] as SorghumLeaf, leafIndex, stemIndex, BAT);
            var forRachis       = AllocateStructuralFromLeaf(Organs[leafIndex] as SorghumLeaf, leafIndex, rachisIndex, BAT);
            var forLeaffromStem = AllocateStructuralFromOrgan(stemIndex, leafIndex, BAT);
            var forLeaf         = AllocateStructuralFromLeaf(Organs[leafIndex] as SorghumLeaf, leafIndex, leafIndex, BAT);

            AllocateStructuralFromOrgan(rachisIndex, grainIndex, BAT);
            AllocateStructuralFromOrgan(stemIndex, grainIndex, BAT);
            AllocateStructuralFromLeaf(Organs[leafIndex] as SorghumLeaf, leafIndex, grainIndex, BAT);
        }
        private void AllocateMetabolic(int i, double allocation, BiomassArbitrationType BAT)
        {
            double MetabolicRequirement = Math.Max(0.0, BAT.MetabolicDemand[i] - BAT.MetabolicAllocation[i]);

            if (MathUtilities.IsPositive(allocation))
            {
                //double MetabolicAllocation = Math.Max(0.0, NotAllocated * MathUtilities.Divide(BAT.MetabolicDemand[i], nTotalDemand, 0));
                //double Allocation = Math.Max(0.0, allocatation * MathUtilities.Divide(organDemand, nTotalDemand, 0));
                double MetabolicAllocation = Math.Min(MetabolicRequirement, allocation);

                //to stop it from givig it too much metabolic - push the flowover from metabolic into storage
                BAT.MetabolicAllocation[i] += MetabolicAllocation;

                //do storage if there is any leftover
                double storageAllocation = allocation - MetabolicAllocation;
                BAT.StorageAllocation[i] += storageAllocation;

                if (storageAllocation > BAT.StorageDemand[i])
                {
                    BAT.StorageDemand[i] += storageAllocation;
                }
            }
        }
Beispiel #5
0
        virtual protected void OnPlantSowing(object sender, SowPlant2Type data)
        {
            List <IArbitration>    organsToArbitrate = new List <IArbitration>();
            List <IHasWaterDemand> Waterdemands      = new List <IHasWaterDemand>();

            foreach (Model Can in Apsim.FindAll(Plant, typeof(IHasWaterDemand)))
            {
                Waterdemands.Add(Can as IHasWaterDemand);
            }

            foreach (IOrgan organ in Plant.Organs)
            {
                if (organ is IArbitration)
                {
                    organsToArbitrate.Add(organ as IArbitration);
                }
            }


            Organs       = organsToArbitrate;
            WaterDemands = Waterdemands;
            DM           = new BiomassArbitrationType("DM", Organs);
            N            = new BiomassArbitrationType("N", Organs);
        }
        private void AllocateStorage(int i, ref double TotalAllocated, ref double NotAllocated, BiomassArbitrationType BAT)
        {
            double StorageRequirement = Math.Max(0.0, BAT.StorageDemand[i] - BAT.StorageAllocation[i]); //N needed to take organ up to maximum N concentration, Structural, Metabolic and Luxury N demands

            if (StorageRequirement > 0.0)
            {
                double StorageAllocation = Math.Min(NotAllocated * MathUtilities.Divide(BAT.StorageDemand[i], BAT.TotalStorageDemand, 0), StorageRequirement);
                BAT.StorageAllocation[i] += Math.Max(0, StorageAllocation);
                NotAllocated             -= StorageAllocation;
                TotalAllocated           += StorageAllocation;
            }
        }
        private void AllocateStructural(int i, ref double TotalAllocated, ref double NotAllocated, BiomassArbitrationType BAT)
        {
            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

            if ((StructuralRequirement) > 0.0)
            {
                double StructuralAllocation = Math.Min(StructuralRequirement, NotAllocated);
                BAT.StructuralAllocation[i] += StructuralAllocation;
                NotAllocated   -= (StructuralAllocation);
                TotalAllocated += (StructuralAllocation);
            }
        }
 /// <summary>Clears this instance.</summary>
 public void Clear()
 {
     DM = new BiomassArbitrationType();
     N  = new BiomassArbitrationType();
 }
 /// <summary>Functions called at DoAllocations.</summary>
 public void DoAllocations(IArbitration[] Organs, BiomassArbitrationType DM)
 {
     allocationMethods.ForEach(pm => pm.Allocate(Organs, DM));
 }
Beispiel #10
0
        /// <summary>Does the fixation.</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="BAT">The bat.</param>
        /// <param name="arbitrator">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>
        override public void AllocateFixation(IArbitration[] Organs, BiomassArbitrationType BAT, IArbitrationMethod arbitrator)
        {
            double BiomassFixed = 0;

            if (BAT.TotalFixationSupply > 0.00000000001)
            {
                arbitrator.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;

                // 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");
                        }
                    }
                }
            }
        }
        /// <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>
        public void DoAllocation(IArbitration[] Organs, double TotalSupply, ref double TotalAllocated, BiomassArbitrationType BAT)
        {
            double NotAllocated = TotalSupply; // / 0.1; //g/m^2
            //allocate structural first - will be a different order to biomass so need to hard code the order until an interface is created
            //roots
            //stem
            //rachis
            //leaf

            //then allocate metabolic relative to demand
            var grainIndex  = 0;
            var rootIndex   = 1;
            var leafIndex   = 2;
            var rachisIndex = 3;
            var stemIndex   = 4;

            var grainDemand          = BAT.StructuralDemand[grainIndex] + BAT.MetabolicDemand[grainIndex];
            var rootDemand           = BAT.StructuralDemand[rootIndex] + BAT.MetabolicDemand[rootIndex];
            var stemDemand           = BAT.StructuralDemand[stemIndex] + BAT.MetabolicDemand[stemIndex];
            var rachisDemand         = BAT.StructuralDemand[rachisIndex] + BAT.MetabolicDemand[rachisIndex];
            var leafMetabolicDemand  = BAT.MetabolicDemand[leafIndex];
            var leafStructuralDemand = BAT.StructuralDemand[leafIndex];

            //calc leaf demand separately - old sorghum doesn't quite fit
            var leaf           = Organs[leafIndex] as SorghumLeaf;
            var leafAdjustment = leaf.calculateClassicDemandDelta();

            var totalPlantNDemand = BAT.TotalPlantDemand + leafAdjustment - grainDemand; // to replicate calcNDemand in old sorghum

            if (totalPlantNDemand > 0.0)
            {
                BAT.SupplyDemandRatioN = Math.Min((BAT.TotalUptakeSupply) / totalPlantNDemand, 1.0);
            }

            double rootAllocation = BAT.SupplyDemandRatioN * BAT.StructuralDemand[rootIndex];

            BAT.StructuralAllocation[rootIndex] += rootAllocation;
            NotAllocated   -= (rootAllocation);
            TotalAllocated += (rootAllocation);

            AllocateStructural(stemIndex, ref TotalAllocated, ref NotAllocated, BAT);
            AllocateStructural(rachisIndex, ref TotalAllocated, ref NotAllocated, BAT);
            AllocateStructural(leafIndex, ref TotalAllocated, ref NotAllocated, BAT);

            var nDemand = totalPlantNDemand - rootDemand;

            var leafAlloc = CalcPoportionalAllocation(NotAllocated, BAT.MetabolicDemand[leafIndex], nDemand);

            AllocateMetabolic(leafIndex, leafAlloc, BAT);

            var rachisAlloc = NotAllocated * MathUtilities.Divide(BAT.StructuralDemand[rachisIndex] + BAT.MetabolicDemand[rachisIndex], nDemand, 0.0);

            AllocateMetabolic(rachisIndex, rachisAlloc, BAT);

            var stemAlloc = NotAllocated * MathUtilities.Divide(BAT.StructuralDemand[stemIndex] + BAT.MetabolicDemand[stemIndex], nDemand, 0.0);

            AllocateMetabolic(stemIndex, stemAlloc, BAT);

            if (!MathUtilities.FloatsAreEqual(leafAlloc + rachisAlloc + stemAlloc, NotAllocated))
            {
                //this is to check that nDemand is equal to old sorghum N demand calc
                throw new Exception("Proportional allocation of Metabolic N doesn't balance");
            }
            TotalAllocated += NotAllocated;
        }
        /// <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>
        public void DoAllocation(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 StorageRequirement    = Math.Max(0, BAT.StorageDemand[i] - BAT.StorageAllocation[i]);
                if ((StructuralRequirement + MetabolicRequirement + StorageRequirement) > 0.0)
                {
                    double StructuralAllocation = Math.Min(StructuralRequirement, TotalSupply * MathUtilities.Divide(BAT.StructuralDemand[i], BAT.TotalPlantDemand, 0));
                    double MetabolicAllocation  = Math.Min(MetabolicRequirement, TotalSupply * MathUtilities.Divide(BAT.MetabolicDemand[i], BAT.TotalPlantDemand, 0));
                    double StorageAllocation    = Math.Min(StorageRequirement, TotalSupply * MathUtilities.Divide(BAT.StorageDemand[i], BAT.TotalPlantDemand, 0));

                    BAT.StructuralAllocation[i] += StructuralAllocation;
                    BAT.MetabolicAllocation[i]  += MetabolicAllocation;
                    BAT.StorageAllocation[i]    += StorageAllocation;
                    NotAllocated   -= (StructuralAllocation + MetabolicAllocation + StorageAllocation);
                    TotalAllocated += (StructuralAllocation + MetabolicAllocation + StorageAllocation);
                }
            }
        }
        /// <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>
        public void DoAllocation(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 StorageRequirement = Math.Max(0.0, BAT.StorageDemand[i] - BAT.StorageAllocation[i]); //N needed to take organ up to maximum N concentration, Structural, Metabolic and Luxury N demands
                if (StorageRequirement > 0.0)
                {
                    double StorageAllocation = Math.Min(FirstPassNotallocated * MathUtilities.Divide(BAT.StorageDemand[i], BAT.TotalStorageDemand, 0), StorageRequirement);
                    BAT.StorageAllocation[i] += Math.Max(0, StorageAllocation);
                    NotAllocated             -= StorageAllocation;
                    TotalAllocated           += StorageAllocation;
                }
            }
        }
        /// <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>
        public void DoAllocation(IArbitration[] Organs, double TotalSupply, ref double TotalAllocated, BiomassArbitrationType BAT)
        {
            double NotAllocated = TotalSupply;

            // Save Totals for use inside the for loops below
            double totalStructuralDemand = BAT.TotalStructuralDemand;
            double totalMetabolicDemand  = BAT.TotalMetabolicDemand;
            double totalStorageDemand    = BAT.TotalStorageDemand;


            ////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   = totalStructuralDemand / (totalStructuralDemand + totalMetabolicDemand);
                    double StructuralAllocation = Math.Min(StructuralRequirement, TotalSupply * StructuralFraction * MathUtilities.Divide(BAT.StructuralDemand[i], totalStructuralDemand, 0));
                    double MetabolicAllocation  = Math.Min(MetabolicRequirement, TotalSupply * (1 - StructuralFraction) * MathUtilities.Divide(BAT.MetabolicDemand[i], totalMetabolicDemand, 0));
                    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 StorageRequirement = Math.Max(0.0, BAT.StorageDemand[i] - BAT.StorageAllocation[i]); //N needed to take organ up to maximum N concentration, Structural, Metabolic and Luxury N demands
                if (StorageRequirement > 0.0)
                {
                    double StorageAllocation = Math.Min(FirstPassNotAllocated * MathUtilities.Divide(BAT.StorageDemand[i], totalStorageDemand, 0), StorageRequirement);
                    BAT.StorageAllocation[i] += Math.Max(0, StorageAllocation);
                    NotAllocated             -= StorageAllocation;
                    TotalAllocated           += StorageAllocation;
                }
            }
            //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;
        }
Beispiel #15
0
 /// <summary>Clears this instance.</summary>
 private void Clear()
 {
     string[] organNames = new string[0];
     DM = new BiomassArbitrationType("DM", Organs);
     N  = new BiomassArbitrationType("N", Organs);
 }
        /// <summary>Relatives the allocation.</summary>
        /// <param name="leaf">The organs.</param>
        /// <param name="iSupply">The organs.</param>
        /// <param name="iSink">The organs.</param>
        /// <param name="BAT">The organs.</param>
        public double AllocateStructuralFromLeaf(SorghumLeaf leaf, int iSupply, int iSink, BiomassArbitrationType BAT)
        {
            //leaf called
            double StructuralRequirement = Math.Max(0.0, BAT.StructuralDemand[iSink] - BAT.StructuralAllocation[iSink]);

            if ((StructuralRequirement) > 0.0)
            {
                double currentRetranslocatedN = leaf.DltRetranslocatedN; //-ve number

                double providedN = leaf.provideNRetranslocation(BAT, StructuralRequirement);
                BAT.StructuralAllocation[iSink] += providedN;

                double afterRetranslocatedN = leaf.DltRetranslocatedN;
                //Leaf keeps track of retranslocation - the return value can include DltLAI which is not techncally retraslocated
                //Let leaf handle the updating

                BAT.Retranslocation[iSupply] += Math.Abs(afterRetranslocatedN - currentRetranslocatedN);
                return(providedN);
            }
            return(0.0);
        }
Beispiel #17
0
        /// <summary>Relatives the allocation.</summary>
        /// <param name="iSupply">The organs.</param>
        /// <param name="iSink">The organs.</param>
        /// <param name="n">The organs.</param>
        /// <param name="dm">The dm BAT.</param>
        /// <param name="source">The organ which N will be taken from.</param>
        public double AllocateStructuralFromRachis(int iSupply, int iSink, BiomassArbitrationType n, BiomassArbitrationType dm, GenericOrgan source)
        {
            double StructuralRequirement = Math.Max(0.0, n.StructuralDemand[iSink] - n.StructuralAllocation[iSink]);

            if (MathUtilities.IsPositive(StructuralRequirement))
            {
                //only allocate as much structural as demanded - cyclical process so allow for any amounts already allocated to Retranslocation
                double StructuralAllocation = Math.Min(StructuralRequirement, n.RetranslocationSupply[iSupply] - n.Retranslocation[iSupply]);

                double dmGreen    = source.Live.Wt;
                double dltDmGreen = dm.StructuralAllocation[iSupply] + dm.MetabolicAllocation[iSupply];
                double dltNGreen  = n.StructuralAllocation[iSupply] + n.MetabolicAllocation[iSupply];
                double nConc      = MathUtilities.Divide(source.Live.N, dmGreen + dltDmGreen, 0);
                // dh - no point multiplying both numbers by 100 as we do in old apsim.
                if (nConc < source.MinNconc)
                {
                    return(0);
                }

                n.StructuralAllocation[iSink] += StructuralAllocation;
                n.Retranslocation[iSupply]    += StructuralAllocation;
                return(StructuralAllocation);
            }
            return(0.0);
        }
Beispiel #18
0
 /// <summary>Clears this instance.</summary>
 virtual protected void Clear()
 {
     DM = new BiomassArbitrationType("DM", Organs);
     N  = new BiomassArbitrationType("N", Organs);
 }
Beispiel #19
0
        /// <summary>Relatives the allocation.</summary>
        /// <param name="iSupply">The organs.</param>
        /// <param name="iSink">The organs.</param>
        /// <param name="n">The organs.</param>
        /// <param name="dm">The dm BAT.</param>
        /// <param name="source">The organ which N will be taken from.</param>
        public double AllocateStructuralFromStem(int iSupply, int iSink, BiomassArbitrationType n, BiomassArbitrationType dm, GenericOrgan source)
        {
            double StructuralRequirement = Math.Max(0.0, n.StructuralDemand[iSink] - n.StructuralAllocation[iSink]);

            if (MathUtilities.IsPositive(StructuralRequirement))
            {
                //only allocate as much structural as demanded - cyclical process so allow for any amounts already allocated to Retranslocation
                double nAvailable = Math.Min(StructuralRequirement, n.RetranslocationSupply[iSupply] - n.Retranslocation[iSupply]);
                double nProvided  = 0;
                double dmGreen    = source.Live.Wt;
                double dltDmGreen = dm.StructuralAllocation[iSupply] + dm.MetabolicAllocation[iSupply];
                double dltNGreen  = n.StructuralAllocation[iSupply] + n.MetabolicAllocation[iSupply] + n.StorageAllocation[iSupply];

                if (dltNGreen > StructuralRequirement)
                {
                    n.StructuralAllocation[iSink] += StructuralRequirement;
                    n.Retranslocation[iSupply]    += StructuralRequirement;
                    return(StructuralRequirement);
                }
                else
                {
                    StructuralRequirement -= dltNGreen;
                    nProvided              = dltNGreen;
                }

                // dh - no point multiplying both numbers by 100 as we do in old apsim.
                double nConc = MathUtilities.Divide(source.Live.N, dmGreen + dltDmGreen, 0);
                if (nConc < source.CritNconc)
                {
                    return(0);
                }

                double availableN = n.RetranslocationSupply[iSupply] - n.Retranslocation[iSupply];

                // cannot take below structural N
                double structN = (dmGreen + dltDmGreen) * source.CritNconc;
                nAvailable = Math.Min(nAvailable, source.Live.N - structN);
                nAvailable = Math.Max(nAvailable, 0);
                nProvided += Math.Min(StructuralRequirement, nAvailable);

                n.StructuralAllocation[iSink] += nProvided;
                n.Retranslocation[iSupply]    += nProvided;
                return(nProvided);
            }
            return(0.0);
        }
 /// <summary>Functions called at DoActualPartitioning.</summary>
 public void DoActualPartitioning(IArbitration[] Organs, BiomassArbitrationType DM)
 {
     actualPartitioningMethods.ForEach(pm => pm.Calculate(Organs, DM, ArbitrationMethod));
 }
Beispiel #21
0
        /// <summary>Relatives the allocation.</summary>
        /// <param name="leaf">The organs.</param>
        /// <param name="iSupply">The organs.</param>
        /// <param name="iSink">The organs.</param>
        /// <param name="BAT">The organs.</param>
        public double AllocateStructuralFromLeaf(SorghumLeaf leaf, int iSupply, int iSink, BiomassArbitrationType BAT)
        {
            double StructuralRequirement = Math.Max(0.0, BAT.StructuralDemand[iSink] - BAT.StructuralAllocation[iSink]);

            if (MathUtilities.IsPositive(StructuralRequirement))
            {
                bool   forLeaf   = iSupply == iSink;
                double providedN = leaf.provideNRetranslocation(BAT, StructuralRequirement, forLeaf);
                BAT.StructuralAllocation[iSink] += providedN;

                // Leaf's dltRetranslocatedN is negative (as in old apsim).
                BAT.Retranslocation[iSupply] = Math.Abs(leaf.DltRetranslocatedN);

                return(providedN);
            }
            return(0.0);
        }
 /// <summary>Functions called at DoUptakes.</summary>
 public void DoUptakes(IArbitration[] Organs, BiomassArbitrationType DM)
 {
     AllocateUptakesMethod.Calculate(Organs, DM, ArbitrationMethod);
 }
Beispiel #23
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>
        public void DoAllocation(IArbitration[] Organs, double TotalSupply, ref double TotalAllocated, BiomassArbitrationType BAT)
        {
            double NotAllocated = TotalSupply; // / 0.1; //g/m^2

            NSupply = TotalSupply;             // reporting variable
            //allocate structural first - will be a different order to biomass so need to hard code the order until an interface is created
            //roots
            //stem
            //rachis
            //leaf

            //then allocate metabolic relative to demand
            var grainIndex  = 0;
            var rootIndex   = 1;
            var leafIndex   = 2;
            var rachisIndex = 3;
            var stemIndex   = 4;

            var grainDemand = BAT.StructuralDemand[grainIndex] + BAT.MetabolicDemand[grainIndex];
            var rootDemand  = BAT.StructuralDemand[rootIndex] + BAT.MetabolicDemand[rootIndex];
            //var stemDemand = BAT.StructuralDemand[stemIndex] + BAT.MetabolicDemand[stemIndex];
            //var rachisDemand = BAT.StructuralDemand[rachisIndex] + BAT.MetabolicDemand[rachisIndex];
            //var leafMetabolicDemand = BAT.MetabolicDemand[leafIndex];
            //var leafStructuralDemand = BAT.StructuralDemand[leafIndex];

            //calc leaf demand separately - old sorghum doesn't quite fit
            var leaf           = Organs[leafIndex] as SorghumLeaf;
            var leafAdjustment = leaf.calculateClassicDemandDelta();

            //var totalPlantNDemand = BAT.TotalPlantDemand + leafAdjustment - grainDemand; // to replicate calcNDemand in old sorghum

            // dh - Old apsim calls organ->calcNDemand() to get demands. This is equivalent to metabolic NDemand in new apsim.
            //      Root and grain had no separation of structural/metabolic N in old apsim. New apsim is similar, except it's all in
            //      structural demand, so we need to remember to take that into account as well.
            double totalDemand  = BAT.TotalMetabolicDemand + BAT.StructuralDemand[rootIndex] + BAT.StructuralDemand[grainIndex];
            double plantNDemand = Math.Max(0, totalDemand - grainDemand); // to replicate calcNDemand in old sorghum

            if (MathUtilities.IsPositive(plantNDemand))
            {
                BAT.SupplyDemandRatioN = MathUtilities.Divide(BAT.TotalUptakeSupply, plantNDemand, 0);
                BAT.SupplyDemandRatioN = Math.Min(BAT.SupplyDemandRatioN, 1);
                // BAT.SupplyDemandRatioN = Math.Max(BAT.SupplyDemandRatioN, 0); // ?
            }

            // todo - what if root demand exceeds supply?
            double rootAllocation = BAT.SupplyDemandRatioN * BAT.StructuralDemand[rootIndex];

            rootAllocation = Math.Min(rootAllocation, NotAllocated);
            BAT.StructuralAllocation[rootIndex] += rootAllocation;
            NotAllocated   -= (rootAllocation);
            TotalAllocated += (rootAllocation);

            AllocateStructural(stemIndex, ref TotalAllocated, ref NotAllocated, BAT);
            AllocateStructural(rachisIndex, ref TotalAllocated, ref NotAllocated, BAT);
            AllocateStructural(leafIndex, ref TotalAllocated, ref NotAllocated, BAT);

            // Structural allocation is subtracted from metabolic demand in old apsim.
            BAT.MetabolicDemand[leafIndex]   = Math.Max(0, BAT.MetabolicDemand[leafIndex] - BAT.StructuralAllocation[leafIndex]);
            BAT.MetabolicDemand[rachisIndex] = Math.Max(0, BAT.MetabolicDemand[rachisIndex] - BAT.StructuralAllocation[rachisIndex]);
            BAT.MetabolicDemand[stemIndex]   = Math.Max(0, BAT.MetabolicDemand[stemIndex] - BAT.StructuralAllocation[stemIndex]);

            double leafDemand   = BAT.MetabolicDemand[leafIndex];
            double rachisDemand = BAT.MetabolicDemand[rachisIndex];
            double stemDemand   = BAT.MetabolicDemand[stemIndex];

            double totalMetabolicDemand = leafDemand + rachisDemand + stemDemand;

            double leafProportion   = MathUtilities.Bound(MathUtilities.Divide(leafDemand, totalMetabolicDemand, 0), 0, 1);
            double rachisProportion = MathUtilities.Bound(MathUtilities.Divide(rachisDemand, totalMetabolicDemand, 0), 0, 1);
            double stemProportion   = MathUtilities.Bound(MathUtilities.Divide(stemDemand, totalMetabolicDemand, 0), 0, 1);

            double leafAlloc = NotAllocated * leafProportion;

            leafAlloc = Math.Min(leafAlloc, leafDemand);

            double rachisAlloc = NotAllocated * rachisProportion;

            rachisAlloc = Math.Min(rachisAlloc, rachisDemand);

            double stemAlloc = NotAllocated - leafAlloc - rachisAlloc;

            AllocateMetabolic(leafIndex, leafAlloc, BAT);
            AllocateMetabolic(rachisIndex, rachisAlloc, BAT);
            AllocateMetabolic(stemIndex, stemAlloc, BAT);

            if (!MathUtilities.FloatsAreEqual(leafAlloc + rachisAlloc + stemAlloc, NotAllocated, 0.0001))
            {
                //this is to check that nDemand is equal to old sorghum N demand calc
                throw new Exception("Proportional allocation of Metabolic N doesn't balance");
            }
            TotalAllocated += NotAllocated;
        }
Beispiel #24
0
 /// <summary>Clears this instance.</summary>
 virtual protected void Clear()
 {
     string[] organNames = new string[0];
     DM = new BiomassArbitrationType("DM", Organs);
     N  = new BiomassArbitrationType("N", Organs);
 }
Beispiel #25
0
        /// <summary>Relatives the allocation.</summary>
        /// <param name="Organs">The organs.</param>
        /// <param name="TypeSupply">The biomass supply for the current supply type.</param>
        /// <param name="TotalAllocated">The total allocated.</param>
        /// <param name="BAT">The bat.</param>
        public void DoAllocation(IArbitration[] Organs, double TypeSupply, ref double TotalAllocated, BiomassArbitrationType BAT)
        {
            BiomassPoolType[] PriorityScalledDemands          = new BiomassPoolType[Organs.Length];
            double            TotalPlantPriorityScalledDemand = 0;

            for (int i = 0; i < Organs.Length; i++)
            {
                PriorityScalledDemands[i]            = new BiomassPoolType();
                PriorityScalledDemands[i].Structural = BAT.StructuralDemand[i] * BAT.QStructural[i];
                PriorityScalledDemands[i].Metabolic  = BAT.MetabolicDemand[i] * BAT.QMetabolic[i];
                PriorityScalledDemands[i].Storage    = BAT.StorageDemand[i] * BAT.QStorage[i];
                TotalPlantPriorityScalledDemand     += PriorityScalledDemands[i].Total;
            }

            double NotAllocated = TypeSupply;

            ////First time round allocate with priority factors applied so higher priority sinks get more allocation
            for (int i = 0; i < Organs.Length; i++)
            {
                double StructuralRequirement = Math.Max(0, BAT.StructuralDemand[i] - BAT.StructuralAllocation[i]);
                double MetabolicRequirement  = Math.Max(0, BAT.MetabolicDemand[i] - BAT.MetabolicAllocation[i]);
                double StorageRequirement    = Math.Max(0, BAT.StorageDemand[i] - BAT.StorageAllocation[i]);
                if ((StructuralRequirement + MetabolicRequirement + StorageRequirement) > 0.0)
                {
                    double StructuralAllocation = Math.Min(StructuralRequirement, TypeSupply * MathUtilities.Divide(PriorityScalledDemands[i].Structural, TotalPlantPriorityScalledDemand, 0));
                    double MetabolicAllocation  = Math.Min(MetabolicRequirement, TypeSupply * MathUtilities.Divide(PriorityScalledDemands[i].Metabolic, TotalPlantPriorityScalledDemand, 0));
                    double StorageAllocation    = Math.Min(StorageRequirement, TypeSupply * MathUtilities.Divide(PriorityScalledDemands[i].Storage, TotalPlantPriorityScalledDemand, 0));

                    BAT.StructuralAllocation[i] += StructuralAllocation;
                    BAT.MetabolicAllocation[i]  += MetabolicAllocation;
                    BAT.StorageAllocation[i]    += StorageAllocation;
                    NotAllocated   -= (StructuralAllocation + MetabolicAllocation + StorageAllocation);
                    TotalAllocated += (StructuralAllocation + MetabolicAllocation + StorageAllocation);
                }
            }
            double FirstPassNotallocated = NotAllocated;
            double RemainingDemand       = BAT.TotalPlantDemand - BAT.TotalPlantAllocation;

            // Second time round if there is still biomass to allocate do it based on relative demands so lower priority organs have the change to be allocated full demand
            for (int i = 0; i < Organs.Length; i++)
            {
                double StructuralRequirement = Math.Max(0, BAT.StructuralDemand[i] - BAT.StructuralAllocation[i]);
                double MetabolicRequirement  = Math.Max(0, BAT.MetabolicDemand[i] - BAT.MetabolicAllocation[i]);
                double StorageRequirement    = Math.Max(0, BAT.StorageDemand[i] - BAT.StorageAllocation[i]);
                if ((StructuralRequirement + MetabolicRequirement + StorageRequirement) > 0.0)
                {
                    double StructuralAllocation = Math.Min(StructuralRequirement, FirstPassNotallocated * MathUtilities.Divide(StructuralRequirement, RemainingDemand, 0));
                    double MetabolicAllocation  = Math.Min(MetabolicRequirement, FirstPassNotallocated * MathUtilities.Divide(MetabolicRequirement, RemainingDemand, 0));
                    double StorageAllocation    = Math.Min(StorageRequirement, FirstPassNotallocated * MathUtilities.Divide(StorageRequirement, RemainingDemand, 0));

                    BAT.StructuralAllocation[i] += StructuralAllocation;
                    BAT.MetabolicAllocation[i]  += MetabolicAllocation;
                    BAT.StorageAllocation[i]    += StorageAllocation;
                    NotAllocated   -= (StructuralAllocation + MetabolicAllocation + StorageAllocation);
                    TotalAllocated += (StructuralAllocation + MetabolicAllocation + StorageAllocation);
                }
            }
        }