/////////////////////////////////////////////////////////////////////////////////////////// // Calculate all SPA parameters and put into structure // Note: All inputs values (listed in header file) must already be in structure /////////////////////////////////////////////////////////////////////////////////////////// #region Calculate all SPA parameters and put into structure public int spa_calculate(ref SpaData spa) { int result; result = validate_inputs(ref spa); if (result == 0) { spa.Jd = julian_day(spa.Year, spa.Month, spa.Day, spa.Hour, spa.Minute, spa.Second, spa.Timezone); calculate_geocentric_sun_right_ascension_and_declination(ref spa); spa.H = observer_hour_angle(spa.Nu, spa.Longitude, spa.Alpha); spa.Xi = sun_equatorial_horizontal_parallax(spa.R); sun_right_ascension_parallax_and_topocentric_dec(spa.Latitude, spa.Elevation, spa.Xi, spa.H, spa.Delta, ref spa.DelAlpha, ref spa.DeltaPrime); spa.AlphaPrime = topocentric_sun_right_ascension(spa.Alpha, spa.DelAlpha); spa.HPrime = topocentric_local_hour_angle(spa.H, spa.DelAlpha); spa.E0 = topocentric_elevation_angle(spa.Latitude, spa.DeltaPrime, spa.HPrime); spa.DelE = atmospheric_refraction_correction(spa.Pressure, spa.Temperature, spa.AtmosRefract, spa.E0); spa.E = topocentric_elevation_angle_corrected(spa.E0, spa.DelE); spa.Zenith = topocentric_zenith_angle(spa.E); spa.Azimuth180 = topocentric_azimuth_angle_neg180_180(spa.HPrime, spa.Latitude, spa.DeltaPrime); spa.Azimuth = topocentric_azimuth_angle_zero_360(spa.Azimuth180); if ((spa.Function == (int)SpaSelect.SpaZaInc) || (spa.Function == (int)SpaSelect.SpaAll)) { spa.Incidence = surface_incidence_angle(spa.Zenith, spa.Azimuth180, spa.AzmRotation, spa.Slope); } if ((spa.Function == (int)SpaSelect.SpaZaRts) || (spa.Function == (int)SpaSelect.SpaAll)) { calculate_eot_and_sun_rise_transit_set(ref spa); } } return(result); }
//////////////////////////////////////////////////////////////////////////////////////////////// // Calculate required SPA parameters to get the right ascension (alpha) and declination (delta) // Note: JD must be already calculated and in structure //////////////////////////////////////////////////////////////////////////////////////////////// #region SPA public void calculate_geocentric_sun_right_ascension_and_declination(ref SpaData spa) { double[] x = new double[(int)TermX.TermXCount]; spa.Jc = julian_century(spa.Jd); spa.Jde = julian_ephemeris_day(spa.Jd, spa.DeltaT); spa.Jce = julian_ephemeris_century(spa.Jde); spa.Jme = julian_ephemeris_millennium(spa.Jce); spa.L = earth_heliocentric_longitude(spa.Jme); spa.B = earth_heliocentric_latitude(spa.Jme); spa.R = earth_radius_vector(spa.Jme); spa.Theta = geocentric_longitude(spa.L); spa.Beta = geocentric_latitude(spa.B); x[(int)TermX.TermX0] = spa.X0 = mean_elongation_moon_sun(spa.Jce); x[(int)TermX.TermX1] = spa.X1 = mean_anomaly_sun(spa.Jce); x[(int)TermX.TermX2] = spa.X2 = mean_anomaly_moon(spa.Jce); x[(int)TermX.TermX3] = spa.X3 = argument_latitude_moon(spa.Jce); x[(int)TermX.TermX4] = spa.X4 = ascending_longitude_moon(spa.Jce); nutation_longitude_and_obliquity(spa.Jce, x, ref spa.DelPsi, ref spa.DelEpsilon); spa.Epsilon0 = ecliptic_mean_obliquity(spa.Jme); spa.Epsilon = ecliptic_true_obliquity(spa.DelEpsilon, spa.Epsilon0); spa.DelTau = aberration_correction(spa.R); spa.Lamda = apparent_sun_longitude(spa.Theta, spa.DelPsi, spa.DelTau); spa.Nu0 = greenwich_mean_sidereal_time(spa.Jd, spa.Jc); spa.Nu = greenwich_sidereal_time(spa.Nu0, spa.DelPsi, spa.Epsilon); spa.Alpha = geocentric_sun_right_ascension(spa.Lamda, spa.Epsilon, spa.Beta); spa.Delta = geocentric_sun_declination(spa.Beta, spa.Epsilon, spa.Lamda); }
/////////////////////////////////////////////////////////////////////////////////////////////// public int validate_inputs(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 > 59)) { return(6); } if ((spa.Pressure < 0) || (spa.Pressure > 5000)) { return(12); } if ((spa.Temperature <= -273) || (spa.Temperature > 6000)) { return(13); } 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 == (int)SpaSelect.SpaZaInc) || (spa.Function == (int)SpaSelect.SpaAll)) { if (Math.Abs(spa.Slope) > 360) { return(14); } if (Math.Abs(spa.AzmRotation) > 360) { return(15); } } return(0); }
public Spa() { spa = new SpaData(); }
//////////////////////////////////////////////////////////////////////// // Calculate Equation of Time (EOT) and Sun Rise, Transit, & Set (RTS) //////////////////////////////////////////////////////////////////////// #region Calculate Equation of Time (EOT) and Sun Rise, Transit, & Set (RTS) private void calculate_eot_and_sun_rise_transit_set(ref SpaData spa) { SpaData sunRts; double nu, m, h0, n; double[] alpha = new double[(int)Julian.JdCount]; double[] delta = new double[(int)Julian.JdCount]; double[] mRts = new double[(int)SunTerm.SunCount]; double[] nuRts = new double[(int)SunTerm.SunCount]; double[] hRts = new double[(int)SunTerm.SunCount]; double[] alphaPrime = new double[(int)SunTerm.SunCount]; double[] deltaPrime = new double[(int)SunTerm.SunCount]; double[] hPrime = new double[(int)SunTerm.SunCount]; double h0Prime = -1 * (SunRadius + spa.AtmosRefract); int i; sunRts = spa; m = sun_mean_longitude(spa.Jme); spa.Eot = Eot(m, spa.Alpha, spa.DelPsi, spa.Epsilon); sunRts.Hour = sunRts.Minute = sunRts.Second = 0; sunRts.Timezone = 0.0; sunRts.Jd = julian_day(sunRts.Year, sunRts.Month, sunRts.Day, sunRts.Hour, sunRts.Minute, sunRts.Second, sunRts.Timezone); calculate_geocentric_sun_right_ascension_and_declination(ref sunRts); nu = sunRts.Nu; sunRts.DeltaT = 0; sunRts.Jd--; for (i = 0; i < (int)Julian.JdCount; i++) { calculate_geocentric_sun_right_ascension_and_declination(ref sunRts); alpha[i] = sunRts.Alpha; delta[i] = sunRts.Delta; sunRts.Jd++; } mRts[(int)SunTerm.SunTransit] = approx_sun_transit_time(alpha[(int)Julian.JdZero], spa.Longitude, nu); h0 = sun_hour_angle_at_rise_set(spa.Latitude, delta[(int)Julian.JdZero], h0Prime); if (h0 >= 0) { approx_sun_rise_and_set(ref mRts, h0); for (i = 0; i < (int)SunTerm.SunCount; i++) { nuRts[i] = nu + 360.985647 * mRts[i]; n = mRts[i] + spa.DeltaT / 86400.0; alphaPrime[i] = rts_alpha_delta_prime(ref alpha, n); deltaPrime[i] = rts_alpha_delta_prime(ref delta, n); hPrime[i] = limit_degrees180pm(nuRts[i] + spa.Longitude - alphaPrime[i]); hRts[i] = rts_sun_altitude(spa.Latitude, deltaPrime[i], hPrime[i]); } spa.Srha = hPrime[(int)SunTerm.SunRise]; spa.Ssha = hPrime[(int)SunTerm.SunSet]; spa.Sta = hRts[(int)SunTerm.SunTransit]; spa.Suntransit = dayfrac_to_local_hr(mRts[(int)SunTerm.SunTransit] - hPrime[(int)SunTerm.SunTransit] / 360.0, spa.Timezone); spa.Sunrise = dayfrac_to_local_hr(sun_rise_and_set(ref mRts, ref hRts, ref deltaPrime, spa.Latitude, ref hPrime, h0Prime, (int)SunTerm.SunRise), spa.Timezone); spa.Sunset = dayfrac_to_local_hr(sun_rise_and_set(ref mRts, ref hRts, ref deltaPrime, spa.Latitude, ref hPrime, h0Prime, (int)SunTerm.SunSet), spa.Timezone); } else { spa.Srha = spa.Ssha = spa.Sta = spa.Suntransit = spa.Sunrise = spa.Sunset = -99999; } }