private void OnSimulationCommencing(object sender, EventArgs e) { foreach (string destinationName in destinationNames) { NutrientPool destination = Apsim.Find(this, destinationName) as NutrientPool; if (destination == null) { throw new Exception("Cannot find destination pool with name: " + destinationName); } destinations.Add(destination); } }
private void OnSimulationCommencing(object sender, EventArgs e) { foreach (string destinationName in destinationNames) { NutrientPool destination = Apsim.Find(this, destinationName) as NutrientPool; if (destination == null) { throw new Exception("Cannot find destination pool with name: " + destinationName); } destinations.Add(destination); } MineralisedN = new double[(Parent as NutrientPool).C.Length]; Catm = new double[(Parent as NutrientPool).C.Length]; }
private void OnSimulationCommencing(object sender, EventArgs e) { destinations = new NutrientPool[destinationNames.Length]; for (int i = 0; i < destinationNames.Length; i++) { NutrientPool destination = FindInScope <NutrientPool>(destinationNames[i]); if (destination == null) { throw new Exception("Cannot find destination pool with name: " + destinationNames[i]); } destinations[i] = destination; } MineralisedN = new double[(Parent as NutrientPool).C.Length]; Catm = new double[(Parent as NutrientPool).C.Length]; carbonFlowToDestination = new double[destinations.Length]; nitrogenFlowToDestination = new double[destinations.Length]; }
private void OnDoSoilOrganicMatter(object sender, EventArgs e) { NutrientPool source = Parent as NutrientPool; double[] no3 = NO3.kgha; double[] nh4 = NH4.kgha; double[] labileP = LabileP.kgha; int numLayers = source.C.Length; int numDestinations = destinations.Length; for (int i = 0; i < numLayers; i++) { double carbonFlowFromSource = Rate.Value(i) * source.C[i]; double nitrogenFlowFromSource = MathUtilities.Divide(carbonFlowFromSource * source.N[i], source.C[i], 0); double phosphorusFlowFromSource = MathUtilities.Divide(carbonFlowFromSource * source.P[i], source.C[i], 0); double totalNitrogenFlowToDestinations = 0; double totalPhosphorusFlowToDestinations = 0; double co2Efficiency = CO2Efficiency.Value(i); for (int j = 0; j < numDestinations; j++) { var destination = destinations[j]; carbonFlowToDestination[j] = carbonFlowFromSource * co2Efficiency * destinationFraction[j]; nitrogenFlowToDestination[j] = MathUtilities.Divide(carbonFlowToDestination[j] * destination.N[i], destination.C[i], 0.0); totalNitrogenFlowToDestinations += nitrogenFlowToDestination[j]; phosphorusFlowToDestination[j] = MathUtilities.Divide(carbonFlowToDestination[j] * destination.P[i], destination.C[i], 0.0); totalPhosphorusFlowToDestinations += phosphorusFlowToDestination[j]; } // some pools do not fully occupy a layer (e.g. residue decomposition) and so need to incorporate fraction of layer double mineralNSupply = (no3[i] + nh4[i]) * source.LayerFraction[i]; double nSupply = nitrogenFlowFromSource + mineralNSupply; double mineralPSupply = labileP[i] * source.LayerFraction[i]; double pSupply = phosphorusFlowFromSource + mineralPSupply; double SupplyFactor = 1; if (totalNitrogenFlowToDestinations > nSupply) { SupplyFactor = MathUtilities.Bound(MathUtilities.Divide(mineralNSupply, totalNitrogenFlowToDestinations - nitrogenFlowFromSource, 1.0), 0.0, 1.0); } if (totalPhosphorusFlowToDestinations > pSupply) { double pSupplyFactor = MathUtilities.Bound(MathUtilities.Divide(mineralPSupply, totalPhosphorusFlowToDestinations - phosphorusFlowFromSource, 1.0), 0.0, 1.0); // ALERT pSupplyFactor = 1; // remove P constraint until P model fully operational SupplyFactor = Math.Min(SupplyFactor, pSupplyFactor); } if (SupplyFactor < 1) { for (int j = 0; j < numDestinations; j++) { carbonFlowToDestination[j] *= SupplyFactor; nitrogenFlowToDestination[j] *= SupplyFactor; phosphorusFlowToDestination[j] *= SupplyFactor; } totalNitrogenFlowToDestinations *= SupplyFactor; totalPhosphorusFlowToDestinations *= SupplyFactor; carbonFlowFromSource *= SupplyFactor; nitrogenFlowFromSource *= SupplyFactor; phosphorusFlowFromSource *= SupplyFactor; } source.C[i] -= carbonFlowFromSource; source.N[i] -= nitrogenFlowFromSource; source.P[i] -= phosphorusFlowFromSource; Catm[i] = carbonFlowFromSource - carbonFlowToDestination.Sum(); for (int j = 0; j < numDestinations; j++) { destinations[j].C[i] += carbonFlowToDestination[j]; destinations[j].N[i] += nitrogenFlowToDestination[j]; destinations[j].P[i] += phosphorusFlowToDestination[j]; } if (totalNitrogenFlowToDestinations <= nitrogenFlowFromSource) { MineralisedN[i] = nitrogenFlowFromSource - totalNitrogenFlowToDestinations; nh4[i] += MineralisedN[i]; } else { double NDeficit = totalNitrogenFlowToDestinations - nitrogenFlowFromSource; double NH4Immobilisation = Math.Min(nh4[i], NDeficit); nh4[i] -= NH4Immobilisation; NDeficit -= NH4Immobilisation; double NO3Immobilisation = Math.Min(no3[i], NDeficit); no3[i] -= NO3Immobilisation; NDeficit -= NO3Immobilisation; MineralisedN[i] = -NH4Immobilisation - NO3Immobilisation; if (MathUtilities.IsGreaterThan(NDeficit, 0.0)) { throw new Exception("Insufficient mineral N for immobilisation demand for C flow " + Name); } } if (totalPhosphorusFlowToDestinations <= phosphorusFlowFromSource) { MineralisedP[i] = phosphorusFlowFromSource - totalPhosphorusFlowToDestinations; labileP[i] += MineralisedP[i]; } else { double PDeficit = totalPhosphorusFlowToDestinations - phosphorusFlowFromSource; double PImmobilisation = Math.Min(labileP[i], PDeficit); labileP[i] -= PImmobilisation; PDeficit -= PImmobilisation; MineralisedP[i] = -PImmobilisation; // ALERT //if (MathUtilities.IsGreaterThan(PDeficit, 0.0)) // throw new Exception("Insufficient mineral P for immobilisation demand for C flow " + Name); } } }
private void OnDoSoilOrganicMatter(object sender, EventArgs e) { NutrientPool source = Parent as NutrientPool; double[] NH4 = solutes.GetSolute("NH4"); double[] NO3 = solutes.GetSolute("NO3"); for (int i = 0; i < source.C.Length; i++) { double carbonFlowFromSource = Rate.Value(i) * source.C[i]; double nitrogenFlowFromSource = MathUtilities.Divide(carbonFlowFromSource, source.CNRatio[i], 0); double[] carbonFlowToDestination = new double[destinations.Count]; double[] nitrogenFlowToDestination = new double[destinations.Count]; for (int j = 0; j < destinations.Count; j++) { carbonFlowToDestination[j] = carbonFlowFromSource * CO2Efficiency.Value(i) * destinationFraction[j]; nitrogenFlowToDestination[j] = MathUtilities.Divide(carbonFlowToDestination[j], destinations[j].CNRatio[i], 0.0); } double TotalNitrogenFlowToDestinations = MathUtilities.Sum(nitrogenFlowToDestination); double NSupply = nitrogenFlowFromSource + NO3[i] + NH4[i]; if (MathUtilities.Sum(nitrogenFlowToDestination) > NSupply) { double NSupplyFactor = MathUtilities.Bound(MathUtilities.Divide(NO3[i] + NH4[i], TotalNitrogenFlowToDestinations - nitrogenFlowFromSource, 1.0), 0.0, 1.0); for (int j = 0; j < destinations.Count; j++) { carbonFlowToDestination[j] *= NSupplyFactor; nitrogenFlowToDestination[j] *= NSupplyFactor; if (nitrogenFlowToDestination[j] > 0.5) { } } TotalNitrogenFlowToDestinations *= NSupplyFactor; carbonFlowFromSource *= NSupplyFactor; nitrogenFlowFromSource *= NSupplyFactor; } source.C[i] -= carbonFlowFromSource; source.N[i] -= nitrogenFlowFromSource; for (int j = 0; j < destinations.Count; j++) { destinations[j].C[i] += carbonFlowToDestination[j]; destinations[j].N[i] += nitrogenFlowToDestination[j]; } if (TotalNitrogenFlowToDestinations <= nitrogenFlowFromSource) { NH4[i] += nitrogenFlowFromSource - TotalNitrogenFlowToDestinations; } else { double NDeficit = TotalNitrogenFlowToDestinations - nitrogenFlowFromSource; double NH4Immobilisation = Math.Min(NH4[i], NDeficit); NH4[i] -= NH4Immobilisation; NDeficit -= NH4Immobilisation; double NO3Immobilisation = Math.Min(NO3[i], NDeficit); NO3[i] -= NO3Immobilisation; NDeficit -= NO3Immobilisation; if (MathUtilities.IsGreaterThan(NDeficit, 0.0)) { throw new Exception("Insufficient mineral N for immobilisation demand for C flow " + Name); } } } solutes.SetSolute("NH4", SoluteManager.SoluteSetterType.Soil, NH4); solutes.SetSolute("NO3", SoluteManager.SoluteSetterType.Soil, NO3); }
private void OnDoSoilOrganicMatter(object sender, EventArgs e) { NutrientPool source = Parent as NutrientPool; for (int i = 0; i < source.C.Length; i++) { double carbonFlowFromSource = Rate.Value(i) * source.C[i]; double nitrogenFlowFromSource = MathUtilities.Divide(carbonFlowFromSource, source.CNRatio[i], 0); double[] carbonFlowToDestination = new double[destinations.Count]; double[] nitrogenFlowToDestination = new double[destinations.Count]; for (int j = 0; j < destinations.Count; j++) { carbonFlowToDestination[j] = carbonFlowFromSource * CO2Efficiency.Value(i) * destinationFraction[j]; nitrogenFlowToDestination[j] = MathUtilities.Divide(carbonFlowToDestination[j], destinations[j].CNRatio[i], 0.0); } double TotalNitrogenFlowToDestinations = MathUtilities.Sum(nitrogenFlowToDestination); // some pools do not fully occupy a layer (e.g. residue decomposition) and so need to incorporate fraction of layer double MineralNSupply = (NO3.kgha[i] + NH4.kgha[i]) * source.LayerFraction[i]; double NSupply = nitrogenFlowFromSource + MineralNSupply; if (TotalNitrogenFlowToDestinations > NSupply) { double NSupplyFactor = MathUtilities.Bound(MathUtilities.Divide(MineralNSupply, TotalNitrogenFlowToDestinations - nitrogenFlowFromSource, 1.0), 0.0, 1.0); for (int j = 0; j < destinations.Count; j++) { carbonFlowToDestination[j] *= NSupplyFactor; nitrogenFlowToDestination[j] *= NSupplyFactor; } TotalNitrogenFlowToDestinations *= NSupplyFactor; carbonFlowFromSource *= NSupplyFactor; nitrogenFlowFromSource *= NSupplyFactor; } source.C[i] -= carbonFlowFromSource; source.N[i] -= nitrogenFlowFromSource; Catm[i] = carbonFlowFromSource - MathUtilities.Sum(carbonFlowToDestination); for (int j = 0; j < destinations.Count; j++) { destinations[j].C[i] += carbonFlowToDestination[j]; destinations[j].N[i] += nitrogenFlowToDestination[j]; } if (TotalNitrogenFlowToDestinations <= nitrogenFlowFromSource) { MineralisedN[i] = nitrogenFlowFromSource - TotalNitrogenFlowToDestinations; NH4.kgha[i] += MineralisedN[i]; } else { double NDeficit = TotalNitrogenFlowToDestinations - nitrogenFlowFromSource; double NH4Immobilisation = Math.Min(NH4.kgha[i], NDeficit); NH4.kgha[i] -= NH4Immobilisation; NDeficit -= NH4Immobilisation; double NO3Immobilisation = Math.Min(NO3.kgha[i], NDeficit); NO3.kgha[i] -= NO3Immobilisation; NDeficit -= NO3Immobilisation; MineralisedN[i] = -NH4Immobilisation - NO3Immobilisation; if (MathUtilities.IsGreaterThan(NDeficit, 0.0)) { throw new Exception("Insufficient mineral N for immobilisation demand for C flow " + Name); } } } }