private float CalculateWaterLimitation(int leafOnStart, int leafOnEnd) { // return 1 if effect is disabled if (mRUspecies.Species.EstablishmentParameters.PsiMin >= 0.0F) { return(1.0F); } float minimumPsiMPa = mRUspecies.Species.EstablishmentParameters.PsiMin; WaterCycle water = mRUspecies.RU.WaterCycle; // two week (14 days) running average of actual psi-values on the resource unit const int daysToAverage = 14; float[] soilWaterPotentialsInAverage = new float[daysToAverage]; float currentPsiSum = 0.0F; float miniumumMovingAverage = Single.MaxValue; int daysInYear = mRUspecies.RU.Climate.GetDaysInYear(); for (int dayOfYear = 0, averageIndex = 0; dayOfYear < daysInYear; ++dayOfYear) { // running average: remove oldest item, add new item in a ringbuffer currentPsiSum -= soilWaterPotentialsInAverage[averageIndex]; soilWaterPotentialsInAverage[averageIndex] = water.SoilWaterPsi[dayOfYear]; currentPsiSum += soilWaterPotentialsInAverage[averageIndex]; if (dayOfYear >= leafOnStart && dayOfYear <= leafOnEnd) { float currentPsiAverage = dayOfYear > 0 ? currentPsiSum / MathF.Min(dayOfYear, daysToAverage) : currentPsiSum; miniumumMovingAverage = MathF.Min(miniumumMovingAverage, currentPsiAverage); } // move to next value in the buffer averageIndex = ++averageIndex % daysToAverage; } if (miniumumMovingAverage > 1000.0) { return(1.0F); // invalid vegetation period? } // calculate the response of the species to this value of psi (see also Species.GetSoilWaterModifier()) float meanPsiMPa = 0.001F * miniumumMovingAverage; // convert to MPa float result = Maths.Limit((meanPsiMPa - minimumPsiMPa) / (-0.015F - minimumPsiMPa), 0.0F, 1.0F); return(result); }
protected override void LogYear(Model model, SqliteCommand insertRow) { // global condition if ((this.mYearFilter.IsEmpty == false) && (mYearFilter.Evaluate(model.CurrentYear) == 0.0)) { return; } int resourceUnitCount = 0; int snowDays = 0; float evapotranspiration = 0.0F, runoff = 0.0F, rad = 0.0F, snowRad = 0.0F, precip = 0.0F; float stockable = 0.0F, stocked = 0.0F; foreach (ResourceUnit ru in model.Landscape.ResourceUnits) { if (ru.EnvironmentID == -1) { continue; // do not include if out of project area } bool logResourceUnits = true; // switch off details if this is indicated in the conditionRU option if (this.mResourceUnitFilter.IsEmpty == false) { Debug.Assert(this.mResourceUnitFilter.Wrapper != null); ((ResourceUnitWrapper)this.mResourceUnitFilter.Wrapper).ResourceUnit = ru; logResourceUnits = this.mResourceUnitFilter.Evaluate(model.CurrentYear) != 0.0; } WaterCycle wc = ru.WaterCycle; if (logResourceUnits) { insertRow.Parameters[0].Value = model.CurrentYear; insertRow.Parameters[1].Value = ru.ResourceUnitGridIndex; insertRow.Parameters[2].Value = ru.EnvironmentID; insertRow.Parameters[3].Value = ru.AreaWithTrees / Constant.RUArea; insertRow.Parameters[4].Value = ru.AreaInLandscape / Constant.RUArea; insertRow.Parameters[5].Value = ru.Climate.GetTotalPrecipitationInCurrentYear(); insertRow.Parameters[6].Value = wc.TotalEvapotranspiration; insertRow.Parameters[7].Value = wc.TotalRunoff; insertRow.Parameters[8].Value = wc.SnowDays; insertRow.Parameters[9].Value = ru.Climate.TotalAnnualRadiation; insertRow.Parameters[10].Value = wc.SnowDayRadiation; insertRow.ExecuteNonQuery(); } ++resourceUnitCount; stockable += ru.AreaInLandscape; stocked += ru.AreaWithTrees; precip += ru.Climate.GetTotalPrecipitationInCurrentYear(); evapotranspiration += wc.TotalEvapotranspiration; runoff += wc.TotalRunoff; snowDays += (int)wc.SnowDays; rad += ru.Climate.TotalAnnualRadiation; snowRad += wc.SnowDayRadiation; } // write landscape sums if (resourceUnitCount == 0) { return; } insertRow.Parameters[0].Value = model.CurrentYear; // codes -1/-1 for landscape level insertRow.Parameters[1].Value = -1; insertRow.Parameters[2].Value = -1; insertRow.Parameters[3].Value = stocked / resourceUnitCount / Constant.RUArea; insertRow.Parameters[4].Value = stockable / resourceUnitCount / Constant.RUArea; insertRow.Parameters[5].Value = precip / resourceUnitCount; // mean precip insertRow.Parameters[6].Value = evapotranspiration / resourceUnitCount; insertRow.Parameters[7].Value = runoff / resourceUnitCount; insertRow.Parameters[8].Value = snowDays / resourceUnitCount; insertRow.Parameters[9].Value = rad / resourceUnitCount; insertRow.Parameters[10].Value = snowRad / resourceUnitCount; insertRow.ExecuteNonQuery(); }