/// <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> virtual 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; } } } } }
/// <summary>Does the retranslocation.</summary> /// <param name="Organs">The organs.</param> /// <param name="BAT">The bat.</param> /// <param name="arbitrator">The option.</param> override public void Retranslocation(IArbitration[] Organs, BiomassArbitrationType BAT, IArbitrationMethod arbitrator) { if (MathUtilities.IsPositive(BAT.TotalRetranslocationSupply)) { var nArbitrator = arbitrator as SorghumArbitratorN; if (nArbitrator != null) { nArbitrator.DoRetranslocation(Organs, BAT); } else { double BiomassRetranslocated = 0; if (MathUtilities.IsPositive(BAT.TotalRetranslocationSupply)) { arbitrator.DoAllocation(Organs, BAT.TotalRetranslocationSupply, ref BiomassRetranslocated, BAT); // Then calculate how much DM (and associated biomass) is retranslocated from each supplying organ based on relative retranslocation supply for (int i = 0; i < Organs.Length; i++) { if (MathUtilities.IsPositive(BAT.RetranslocationSupply[i])) { double RelativeSupply = BAT.RetranslocationSupply[i] / BAT.TotalRetranslocationSupply; BAT.Retranslocation[i] += BiomassRetranslocated * RelativeSupply; } } } } } }
/// <summary>Does the retranslocation.</summary> /// <param name="Organs">The organs.</param> /// <param name="BAT">The bat.</param> /// <param name="arbitrator">The option.</param> override public void Retranslocation(IArbitration[] Organs, BiomassArbitrationType BAT, IArbitrationMethod arbitrator) { if (MathUtilities.IsPositive(BAT.TotalRetranslocationSupply)) { var nArbitrator = arbitrator as SorghumArbitratorN; if (nArbitrator != null) { nArbitrator.DoRetranslocation(Organs, BAT, DM); } else { double BiomassRetranslocated = 0; if (MathUtilities.IsPositive(BAT.TotalRetranslocationSupply)) { arbitrator.DoAllocation(Organs, BAT.TotalRetranslocationSupply, ref BiomassRetranslocated, BAT); int leafIndex = 2; int stemIndex = 4; double grainDifferential = BiomassRetranslocated; // Retranslocate from stem. double stemWtAvail = BAT.RetranslocationSupply[stemIndex]; double stemRetrans = Math.Min(grainDifferential, stemWtAvail); BAT.Retranslocation[stemIndex] += stemRetrans; grainDifferential -= stemRetrans; double leafWtAvail = BAT.RetranslocationSupply[leafIndex]; double leafRetrans = Math.Min(grainDifferential, leafWtAvail); BAT.Retranslocation[leafIndex] += Math.Min(grainDifferential, leafWtAvail); grainDifferential -= leafRetrans; } } } }
/// <summary>Does the uptake.</summary> /// <param name="Organs">The organs.</param> /// <param name="BAT">The bat.</param> /// <param name="arbitrator">The option.</param> virtual public void AllocateUptake(IArbitration[] Organs, BiomassArbitrationType BAT, IArbitrationMethod arbitrator) { double BiomassTakenUp = 0; if (BAT.TotalUptakeSupply > 0.00000000001) { arbitrator.DoAllocation(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++) { BAT.Uptake[i] += BiomassTakenUp * MathUtilities.Divide(BAT.UptakeSupply[i], BAT.TotalUptakeSupply, 0); } } }
/// <summary>Does the retranslocation.</summary> /// <param name="Organs">The organs.</param> /// <param name="BAT">The bat.</param> /// <param name="arbitrator">The option.</param> virtual public void Retranslocation(IArbitration[] Organs, BiomassArbitrationType BAT, IArbitrationMethod arbitrator) { double BiomassRetranslocated = 0; if (BAT.TotalRetranslocationSupply > 0.00000000001) { arbitrator.DoAllocation(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; } } } }
/// <summary>Does the retranslocation.</summary> /// <param name="Organs">The organs.</param> /// <param name="BAT">The bat.</param> /// <param name="arbitrator">The option.</param> override public void Retranslocation(IArbitration[] Organs, BiomassArbitrationType BAT, IArbitrationMethod arbitrator) { if (MathUtilities.IsPositive(BAT.TotalRetranslocationSupply)) { var nArbitrator = arbitrator as SorghumArbitratorN; if (nArbitrator != null) { nArbitrator.DoRetranslocation(Organs, BAT, DM); } else { double BiomassRetranslocated = 0; if (MathUtilities.IsPositive(BAT.TotalRetranslocationSupply)) { var phenology = Apsim.Find(this, typeof(Phen.Phenology)) as Phen.Phenology; if (phenology.Beyond("EndGrainFill")) { return; } arbitrator.DoAllocation(Organs, BAT.TotalRetranslocationSupply, ref BiomassRetranslocated, BAT); int leafIndex = 2; int stemIndex = 4; double grainDifferential = BiomassRetranslocated; if (grainDifferential > 0) { // Retranslocate from stem. double stemWtAvail = BAT.RetranslocationSupply[stemIndex]; double stemRetrans = Math.Min(grainDifferential, stemWtAvail); BAT.Retranslocation[stemIndex] += stemRetrans; grainDifferential -= stemRetrans; double leafWtAvail = BAT.RetranslocationSupply[leafIndex]; double leafRetrans = Math.Min(grainDifferential, leafWtAvail); BAT.Retranslocation[leafIndex] += Math.Min(grainDifferential, leafWtAvail); grainDifferential -= leafRetrans; } } } } }
/// <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 = MathUtilities.Sum(BAT.Reallocation); } }
/// <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"); } } } } }