private void OnDoSoilWaterMovement(object sender, EventArgs e) { // Calculate lateral flow. LateralFlow = lateralFlowModel.Values; MathUtilities.Subtract(Water, LateralFlow); // Calculate runoff. Runoff = runoffModel.Value(); // Calculate infiltration. Infiltration = PotentialInfiltration - Runoff; Water[0] = Water[0] + Infiltration; // Allow irrigation to infiltrate. if (!irrigation.WillRunoff) { int irrigationLayer = APSIM.Shared.APSoil.SoilUtilities.FindLayerIndex(properties, Convert.ToInt32(irrigation.Depth, CultureInfo.InvariantCulture)); Water[irrigationLayer] = irrigation.IrrigationApplied; Infiltration += irrigation.IrrigationApplied; // DeanH - haven't implemented solutes in irrigation water yet. // NO3[irrigationLayer] = irrigation.NO3; // NH4[irrigationLayer] = irrigation.NH4; // CL[irrigationLayer] = irrigation.Cl; } // Saturated flow. Flux = saturatedFlow.Values; // Add backed up water to runoff. Water[0] = Water[0] - saturatedFlow.backedUpSurface; // Now reduce the infiltration amount by what backed up. Infiltration = Infiltration - saturatedFlow.backedUpSurface; // Turn the proportion of the infiltration that backed up into runoff. Runoff = Runoff + saturatedFlow.backedUpSurface; // Should go to pond if one exists. // pond = Math.Min(Runoff, max_pond); MoveDown(Water, Flux); double[] NO3Values = soilNitrogen.CalculateNO3(); double[] NH4Values = soilNitrogen.CalculateNH4(); // Calcualte solute movement down with water. double[] NO3Down = CalculateSoluteMovementDown(NO3Values, Water, Flux, SoluteFluxEfficiency); double[] NH4Down = CalculateSoluteMovementDown(NH4Values, Water, Flux, SoluteFluxEfficiency); MoveDown(NO3Values, NO3Down); MoveDown(NH4Values, NH4Down); double es = evaporationModel.Calculate(); Water[0] = Water[0] - es; Flow = unsaturatedFlow.Values; MoveUp(Water, Flow); CheckForErrors(); double waterTableDepth = waterTableModel.Value(); double[] NO3Up = CalculateSoluteMovementUpDown(soilNitrogen.CalculateNO3(), Water, Flow, SoluteFlowEfficiency); double[] NH4Up = CalculateSoluteMovementUpDown(soilNitrogen.CalculateNH4(), Water, Flow, SoluteFlowEfficiency); MoveUp(NO3Values, NO3Up); MoveUp(NH4Values, NH4Up); // Set deltas NO3.SetKgHa(SoluteSetterType.Soil, MathUtilities.Subtract(soilNitrogen.CalculateNO3(), NO3Values)); NH4.SetKgHa(SoluteSetterType.Soil, MathUtilities.Subtract(soilNitrogen.CalculateNH4(), NH4Values)); }
private void OnDoSoilWaterMovement(object sender, EventArgs e) { // Calculate lateral flow. lateralFlowModel.Calculate(); if (LateralFlow.Length > 0) { Water = MathUtilities.Subtract(Water, LateralFlow); } // Calculate runoff. Runoff = runoffModel.Value(); // Calculate infiltration. Infiltration = PotentialInfiltration - Runoff; Water[0] = Water[0] + Infiltration + Runon; // Allow irrigation to infiltrate. foreach (var irrigation in irrigations) { if (irrigation.Amount > 0) { int irrigationLayer = soil.LayerIndexOfDepth(Convert.ToInt32(irrigation.Depth, CultureInfo.InvariantCulture)); Water[irrigationLayer] += irrigation.Amount; if (irrigationLayer == 0) { Infiltration += irrigation.Amount; } if (no3 != null) { no3.kgha[irrigationLayer] += irrigation.NO3; } if (nh4 != null) { nh4.kgha[irrigationLayer] += irrigation.NH4; } if (cl != null) { cl.kgha[irrigationLayer] += irrigation.CL; } } } // Saturated flow. Flux = saturatedFlow.Values; // Add backed up water to runoff. Water[0] = Water[0] - saturatedFlow.backedUpSurface; // Now reduce the infiltration amount by what backed up. Infiltration = Infiltration - saturatedFlow.backedUpSurface; // Turn the proportion of the infiltration that backed up into runoff. Runoff = Runoff + saturatedFlow.backedUpSurface; // Should go to pond if one exists. // pond = Math.Min(Runoff, max_pond); MoveDown(Water, Flux); double[] no3Values = no3.kgha; double[] ureaValues = urea.kgha; // Calcualte solute movement down with water. double[] no3Down = CalculateSoluteMovementDown(no3Values, Water, Flux, SoluteFluxEfficiency); MoveDown(no3Values, no3Down); double[] ureaDown = CalculateSoluteMovementDown(ureaValues, Water, Flux, SoluteFluxEfficiency); MoveDown(ureaValues, ureaDown); // Calculate evaporation and remove from top layer. double es = evaporationModel.Calculate(); Water[0] = Water[0] - es; // Calculate unsaturated flow of water and apply. Flow = unsaturatedFlow.Values; MoveUp(Water, Flow); // Check for errors in water variables. //CheckForErrors(); // Calculate water table depth. waterTableModel.Calculate(); // Calculate and apply net solute movement. double[] no3Up = CalculateNetSoluteMovement(no3Values, Water, Flow, SoluteFlowEfficiency); MoveUp(no3Values, no3Up); double[] ureaUp = CalculateNetSoluteMovement(ureaValues, Water, Flow, SoluteFlowEfficiency); MoveUp(ureaValues, ureaUp); // Update flow output variables. FlowNO3 = MathUtilities.Subtract(no3Down, no3Up); FlowUrea = MathUtilities.Subtract(ureaDown, ureaUp); // Set solute state variables. no3.SetKgHa(SoluteSetterType.Soil, no3Values); urea.SetKgHa(SoluteSetterType.Soil, ureaValues); // Now that we've finished moving water, calculate volumetric water waterVolumetric = MathUtilities.Divide(Water, soil.Thickness); }
public void TestEvaporation() { MockSoil soil = new MockSoil(); APSIM.Shared.Soils.Soil soilProperties = Setup(); APSIMReadySoil.Create(soilProperties); MockClock clock = new MockClock(); clock.Today = new DateTime(2015, 6, 1); MockWeather weather = new MockWeather(); weather.MaxT = 30; weather.MinT = 10; weather.Rain = 100; weather.Radn = 25; MockSurfaceOrganicMatter surfaceOrganicMatter = new MockSurfaceOrganicMatter(); surfaceOrganicMatter.Cover = 0.8; List<ICanopy> canopies = new List<ICanopy>(); EvaporationModel evaporation = new EvaporationModel(); SetLink(soil, "properties", soilProperties); SetLink(evaporation, "soil", soil); SetLink(evaporation, "clock", clock); SetLink(evaporation, "weather", weather); SetLink(evaporation, "canopies", canopies); SetLink(evaporation, "surfaceOrganicMatter", surfaceOrganicMatter); // Empty profile. soil.Water = MathUtilities.Multiply(soilProperties.Water.LL15, soilProperties.Water.Thickness); evaporation.Calculate(); Assert.IsTrue(MathUtilities.FloatsAreEqual(evaporation.Es, 3.00359)); soil.Infiltration = 0; evaporation.Calculate(); Assert.IsTrue(MathUtilities.FloatsAreEqual(evaporation.Es, 2.20072)); soil.Infiltration = 0; evaporation.Calculate(); Assert.IsTrue(MathUtilities.FloatsAreEqual(evaporation.Es, 1.57064)); soil.Infiltration = 0; evaporation.Calculate(); Assert.IsTrue(MathUtilities.FloatsAreEqual(evaporation.Es, 0.96006)); soil.Infiltration = 0; evaporation.Calculate(); Assert.IsTrue(MathUtilities.FloatsAreEqual(evaporation.Es, 0.75946)); soil.Infiltration = 0; evaporation.Calculate(); Assert.IsTrue(MathUtilities.FloatsAreEqual(evaporation.Es, 0.64851)); soil.Infiltration = 100; evaporation.Calculate(); Assert.IsTrue(MathUtilities.FloatsAreEqual(evaporation.Es, 3.00359)); soil.Infiltration = 0; evaporation.Calculate(); Assert.IsTrue(MathUtilities.FloatsAreEqual(evaporation.Es, 2.20072)); }