/// <summary>Creates a list of temperature range factors used to estimate daily temperature from Min and Max temp</summary> /// <returns></returns> public List <double> SubDailyTemperatures() { double d = MetData.CalculateDayLength(-6); double Tmin = MetData.MinT; double Tmax = MetData.MaxT; double TmaxB = MetData.MaxT; double TminA = MetData.MinT; double Hsrise = MetData.CalculateSunRise(); double Hsset = MetData.CalculateSunSet(); List <double> sdts = new List <double>(); for (int Th = 0; Th <= 23; Th++) { double Ta = 1.0; if (Th < Hsrise) { // Hour between midnight and sunrise // PERIOD A MaxTB is max. temperature, before day considered //this is the sunset temperature of based on the previous day double n = 24 - d; Tsset = Tmin + (TmaxB - Tmin) * Math.Sin(Math.PI * (d / (d + 2 * P))); Ta = (Tmin - Tsset * Math.Exp(-n / TC) + (Tsset - Tmin) * Math.Exp(-(Th + 24 - Hsset) / TC)) / (1 - Math.Exp(-n / TC)); } else if (Th >= Hsrise & Th < 12 + P) { // PERIOD B Hour between sunrise and normal time of MaxT Ta = Tmin + (Tmax - Tmin) * Math.Sin(Math.PI * (Th - Hsrise) / (d + 2 * P)); } else if (Th >= 12 + P & Th < Hsset) { // PERIOD C Hour between normal time of MaxT and sunset // MinTA is min. temperature, after day considered Ta = TminA + (Tmax - TminA) * Math.Sin(Math.PI * (Th - Hsrise) / (d + 2 * P)); } else { // PERIOD D Hour between sunset and midnight Tsset = TminA + (Tmax - TminA) * Math.Sin(Math.PI * (d / (d + 2 * P))); double n = 24 - d; Ta = (TminA - Tsset * Math.Exp(-n / TC) + (Tsset - TminA) * Math.Exp(-(Th - Hsset) / TC)) / (1 - Math.Exp(-n / TC)); } sdts.Add(Ta); } return(sdts); }
// Calculates the ground solar incident radiation per hour and scales it to the actual radiation // Developed by Greg McLean and adapted/modified by Behnam (Ben) Ababaei. /// <summary> /// Hourly radiation estimation ported from https://github.com/BrianCollinss/ApsimX/blob/12a89f9981e2636f13251b0faa30200a98b713ce/Models/Functions/SupplyFunctions/MaximumHourlyTrModel.cs#L260 /// by Hamish /// Note, this has not been tested and probably has errors as it is not a dirrect port /// </summary> /// <returns></returns> public List <double> SubDailyValues() { List <double> hourlyRad = new List <double>(); double latR = Math.PI / 180.0 * MetData.Latitude; // convert latitude (degrees) to radians double GlobalRadiation = MetData.Radn * 1e6; // solar radiation double PI = Math.PI; double RAD = PI / 180.0; //Declination of the sun as function of Daynumber (vDay) double Dec = -Math.Asin(Math.Sin(23.45 * RAD) * Math.Cos(2.0 * PI * ((double)clock.Today.DayOfYear + 10.0) / 365.0)); //vSin, vCos and vRsc are intermediate variables double Sin = Math.Sin(latR) * Math.Sin(Dec); double Cos = Math.Cos(latR) * Math.Cos(Dec); double Rsc = Sin / Cos; //Astronomical daylength (hr) double DayL = MetData.CalculateDayLength(-6); double DailySinE = 3600.0 * (DayL * (Sin + 0.4 * (Sin * Sin + Cos * Cos * 0.5)) + 12.0 * Cos * (2.0 + 3.0 * 0.4 * Sin) * Math.Sqrt(1.0 - Rsc * Rsc) / PI); double riseHour = MetData.CalculateSunRise(); double setHour = MetData.CalculateSunSet(); for (int t = 0; t <= 23; t++) { double Hour1 = Math.Min(setHour, Math.Max(riseHour, t)); double SinHeight1 = Math.Max(0.0, Sin + Cos * Math.Cos(2.0 * PI * (Hour1 - 12.0) / 24.0)); double Hour2 = Math.Min(setHour, Math.Max(riseHour, t + 1)); double SinHeight2 = Math.Max(0.0, Sin + Cos * Math.Cos(2.0 * PI * (Hour2 - 12.0) / 24.0)); double SinHeight = 0.5 * (SinHeight1 + SinHeight2); hourlyRad.Add(Math.Max(0, GlobalRadiation * SinHeight * (1.0 + 0.4 * SinHeight) / DailySinE)); hourlyRad[t] *= HourlyWeight(t + 1, riseHour, setHour); } return(hourlyRad); }
/// <summary> /// Calculate time of sunset in hours. /// </summary> public double CalculateSunSet() => weather.CalculateSunSet();