public static int ValidateInputs(ref SPAData spa) { if ((spa.Year < -2000) || (spa.Year > 6000)) return 1; if ((spa.Month < 1) || (spa.Month > 12)) return 2; if ((spa.Day < 1) || (spa.Day > 31)) return 3; if ((spa.Hour < 0) || (spa.Hour > 24)) return 4; if ((spa.Minute < 0) || (spa.Minute > 59)) return 5; if ((spa.Second < 0) || (spa.Second >= 60)) return 6; if ((spa.Pressure < 0) || (spa.Pressure > 5000)) return 12; if ((spa.Temperature <= -273) || (spa.Temperature > 6000)) return 13; if ((spa.DeltaUt1 <= -1) || (spa.DeltaUt1 >= 1)) return 17; if ((spa.Hour == 24) && (spa.Minute > 0)) return 5; if ((spa.Hour == 24) && (spa.Second > 0)) return 6; if (Math.Abs(spa.DeltaT) > 8000) return 7; if (Math.Abs(spa.Timezone) > 18) return 8; if (Math.Abs(spa.Longitude) > 180) return 9; if (Math.Abs(spa.Latitude) > 90) return 10; if (Math.Abs(spa.AtmosRefract) > 5) return 16; if (spa.Elevation < -6500000) return 11; if ((spa.Function == CalculationMode.SPA_ZA_INC) || (spa.Function == CalculationMode.SPA_ALL)) { if (Math.Abs(spa.Slope) > 360) return 14; if (Math.Abs(spa.AzmRotation) > 360) return 15; } return 0; }
static void Main(string[] args) { var timer = new Stopwatch(); timer.Start(); var dic = new Dictionary <DateTime, Data>(); SPAData data = new SPAData { Year = 2020, Month = 1, Day = 1, Hour = 1, Minute = 0, Second = 0, DeltaUt1 = 0, DeltaT = 0, Timezone = 2, Latitude = 54.5421, Longitude = 23.57262, Elevation = 76, Pressure = 993, Temperature = 20, Slope = 0, AzmRotation = 0, AtmosRefract = 0.5667, }; var endTime = new DateTime(2021, 1, 1, 1, 1, 1); for (var time = new DateTime(2020, 1, 1, 1, 1, 1); time < endTime; time = time.AddMinutes(1.0)) { data.Month = time.Month; data.Day = time.Day; data.Hour = time.Hour; data.Minute = time.Minute; SPACalculate(ref data); dic.Add(time, new Data { Azimuth = data.Azimuth, Zenith = data.Zenith }); } timer.Stop(); }
public static int SPACalculate(ref SPAData spa) { var result = ValidateInputs(ref spa); if (result == 0) { spa.Jd = JulianDay(spa.Year, spa.Month, spa.Day, spa.Hour, spa.Minute, spa.Second, spa.DeltaUt1, spa.Timezone); CalculateGeocentricSunRightAscensionAndDeclination(ref spa); spa.H = ObserverHourAngle(spa.Nu, spa.Longitude, spa.Alpha); spa.Xi = SunEquatorialHorizontalParallax(spa.R); RightAscensionParallaxAndTopocentricDec(spa.Latitude, spa.Elevation, spa.Xi, spa.H, spa.Delta, ref spa.DelAlpha, ref spa.DeltaPrime); spa.AlphaPrime = TopocentricRightAscension(spa.Alpha, spa.DelAlpha); spa.HPrime = TopocentricLocalHourAngle(spa.H, spa.DelAlpha); spa.E0 = TopocentricElevationAngle(spa.Latitude, spa.DeltaPrime, spa.HPrime); spa.DelE = AtmosphericRefractionCorrection(spa.Pressure, spa.Temperature, spa.AtmosRefract, spa.E0); spa.E = TopocentricElevationAngleCorrected(spa.E0, spa.DelE); spa.Zenith = TopocentricZenithAngle(spa.E); spa.AzimuthAstro = TopocentricAzimuthAngleAstro(spa.HPrime, spa.Latitude, spa.DeltaPrime); spa.Azimuth = TopocentricAzimuthAngle(spa.AzimuthAstro); if ((spa.Function == CalculationMode.SPA_ZA_INC) || (spa.Function == CalculationMode.SPA_ALL)) spa.Incidence = SurfaceIncidenceAngle(spa.Zenith, spa.AzimuthAstro, spa.AzmRotation, spa.Slope); if ((spa.Function == CalculationMode.SPA_ZA_RTS) || (spa.Function == CalculationMode.SPA_ALL)) CalculateEOTAndSunRiseTransitSet(ref spa); } return result; }
static void CalculateGeocentricSunRightAscensionAndDeclination(ref SPAData spa) { double[] x = new double[(int)TERM2.TERM_X_COUNT]; spa.Jc = JulianCentury(spa.Jd); spa.Jde = JulianEphemerisDay(spa.Jd, spa.DeltaT); spa.Jce = JulianEphemerisCentury(spa.Jde); spa.Jme = JulianEphemerisMillennium(spa.Jce); spa.L = EarthHeliocentricLongitude(spa.Jme); spa.B = EarthHeliocentricLatitude(spa.Jme); spa.R = EarthRadiusVector(spa.Jme); spa.Theta = GeocentricLongitude(spa.L); spa.Beta = GeocentricLatitude(spa.B); x[(int)TERM2.TERM_X0] = spa.X0 = MeanElongationMoonSun(spa.Jce); x[(int)TERM2.TERM_X1] = spa.X1 = MeanAnomalySun(spa.Jce); x[(int)TERM2.TERM_X2] = spa.X2 = MeanAnomalyMoon(spa.Jce); x[(int)TERM2.TERM_X3] = spa.X3 = ArgumentLatitudeMoon(spa.Jce); x[(int)TERM2.TERM_X4] = spa.X4 = AscendingLongitudeMoon(spa.Jce); NutationLongitudeAndObliquity(spa.Jce, x, ref spa.DelPsi, ref spa.DelEpsilon); spa.Epsilon0 = EclipticMeanObliquity(spa.Jme); spa.Epsilon = EclipticTrueObliquity(spa.DelEpsilon, spa.Epsilon0); spa.DelTau = AberrationCorrection(spa.R); spa.Lamda = ApparentSunLongitude(spa.Theta, spa.DelPsi, spa.DelTau); spa.Nu0 = GreenwichMeanSiderealTime(spa.Jd, spa.Jc); spa.Nu = GreenwichSiderealTime(spa.Nu0, spa.DelPsi, spa.Epsilon); spa.Alpha = GeocentricRightAscension(spa.Lamda, spa.Epsilon, spa.Beta); spa.Delta = GeocentricDeclination(spa.Beta, spa.Epsilon, spa.Lamda); }
static void CalculateEOTAndSunRiseTransitSet(ref SPAData spa) { double[] alpha = new double[(int)TERM4.JD_COUNT], delta = new double[(int)TERM4.JD_COUNT]; double[] mRts = new double[(int)TERM5.SUN_COUNT], nuRts = new double[(int)TERM5.SUN_COUNT], hRts = new double[(int)TERM5.SUN_COUNT]; double[] alphaPrime = new double[(int)TERM5.SUN_COUNT], deltaPrime = new double[(int)TERM5.SUN_COUNT], hPrime = new double[(int)TERM5.SUN_COUNT]; double h0Prime = -1 * (SunRadius + spa.AtmosRefract); int i; SPAData sunRts = spa; var m = SunMeanLongitude(spa.Jme); spa.Eot = EquationOfTime(m, spa.Alpha, spa.DelPsi, spa.Epsilon); sunRts.Hour = sunRts.Minute = 0; sunRts.Second = 0; sunRts.DeltaUt1 = sunRts.Timezone = 0.0; sunRts.Jd = JulianDay(sunRts.Year, sunRts.Month, sunRts.Day, sunRts.Hour, sunRts.Minute, sunRts.Second, sunRts.DeltaUt1, sunRts.Timezone); CalculateGeocentricSunRightAscensionAndDeclination(ref sunRts); var nu = sunRts.Nu; sunRts.DeltaT = 0; sunRts.Jd--; for (i = 0; i < (int)TERM4.JD_COUNT; i++) { CalculateGeocentricSunRightAscensionAndDeclination(ref sunRts); alpha[i] = sunRts.Alpha; delta[i] = sunRts.Delta; sunRts.Jd++; } mRts[(int)TERM5.SUN_TRANSIT] = ApproxSunTransitTime(alpha[(int)TERM4.JD_ZERO], spa.Longitude, nu); var h0 = SunHourAngleAtRiseSet(spa.Latitude, delta[(int)TERM4.JD_ZERO], h0Prime); if (h0 >= 0) { ApproxSunRiseAndSet(ref mRts, h0); for (i = 0; i < (int)TERM5.SUN_COUNT; i++) { nuRts[i] = nu + 360.985647 * mRts[i]; var n = mRts[i] + spa.DeltaT / 86400.0; alphaPrime[i] = RtsAlphaDeltaPrime(ref alpha, n); deltaPrime[i] = RtsAlphaDeltaPrime(ref delta, n); hPrime[i] = LimitDegrees180pm(nuRts[i] + spa.Longitude - alphaPrime[i]); hRts[i] = RtsSunAltitude(spa.Latitude, deltaPrime[i], hPrime[i]); } spa.Srha = hPrime[(int)TERM5.SUN_RISE]; spa.Ssha = hPrime[(int)TERM5.SUN_SET]; spa.Sta = hRts[(int)TERM5.SUN_TRANSIT]; spa.Suntransit = DayFracToLocalHr(mRts[(int)TERM5.SUN_TRANSIT] - hPrime[(int)TERM5.SUN_TRANSIT] / 360.0, spa.Timezone); spa.Sunrise = DayFracToLocalHr(SunRiseAndSet(ref mRts, ref hRts, ref deltaPrime, spa.Latitude, ref hPrime, h0Prime, (int)TERM5.SUN_RISE), spa.Timezone); spa.Sunset = DayFracToLocalHr(SunRiseAndSet(ref mRts, ref hRts, ref deltaPrime, spa.Latitude, ref hPrime, h0Prime, (int)TERM5.SUN_SET), spa.Timezone); } else spa.Srha = spa.Ssha = spa.Sta = spa.Suntransit = spa.Sunrise = spa.Sunset = -99999; }