太阳路径的计算 [英] Calculations of the path of the Sun

查看:99
本文介绍了太阳路径的计算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写几种必要的方法来计算太阳在特定点上的路径.我已经使用两个不同的来源编写了代码,以进行计算,但都没有产生期望的结果.来源是: http://www.pveducation.org/pvcdrom/"sunlight/suns-position"属性 http://www.esrl.noaa.gov/gmd/grad/solcalc/solareqns.PDF

I'm writing several methods necessary to calculate the path of the Sun across a specific point. I have written the code using two different sources for my calculations and neither is producing the desired result. The sources are: http://www.pveducation.org/pvcdrom/properties-of-sunlight/suns-position and http://www.esrl.noaa.gov/gmd/grad/solcalc/solareqns.PDF

注意:弧分的度数是度* 60分钟.

Note: Degrees to arcminutes is Deg * 60 min.

  1. localSolartime:我将经度转换为分钟",从localStandardTimeMeridian方法派生的本地标准时间子午线(lstm)返回的值以分钟"为单位,而equationOfTime也以"返回分钟'.使用来自体育的方程式,我计算了时间校正,该校正考虑了给定时区内的较小时间变化.当我将此结果和localTime(以分钟为单位)应用于本地太阳时间(lst)公式时,结果为676.515(此刻),这对我来说没有任何意义.据我了解,当地的太阳时间代表相对于太阳的时间,当它在天空中的最高点时,在当地被视为太阳正午. 676.515没有任何意义.有谁知道可能是什么原因造成的.

  1. localSolartime: I have converted the longitude to 'minutes', the local standard time meridian(lstm) derived from the localStandardTimeMeridian method returns a value that is in 'minutes', and the equationOfTime which is also returned in 'minutes'. Using the equation from pveducation, I've calculated the time correction which accounts for the small time variations within a given time zone. When I apply this result and the localTime, each in minutes, to the local solar time (lst) equation, the result is 676.515 (at this moment), which does not make any sense to me. The local solar time, as I understand it, represents the time with respect to the Sun and when it is at its highest point in the sky, locally, is considered solar noon. 676.515 does not make sense. Does anybody understand what might be causing this.

HourAngle:我希望一旦修复了localSolarTime方法,就无需对此进行更正.

HourAngle: I'm hoping that once I fix the localSolarTime method, this will not need to be corrected.

我选择华盛顿特区作为纬度和经度. Zenith和Azimuth读数均应为正值,并且对于我现在的区域,分别为66和201.

I've chosen Washington DC for the latitude and longitude. Both the Zenith and Azimuth readings should be positive values, and for my region at this moment, are 66 and 201 respectively.

public class PathOfSun {
    static LocalTime localTime = LocalTime.now();
    static double dcLat = 38.83;
    static double dcLong =  -77.02;
    static DecimalFormat df = new DecimalFormat("#.0");

    public static void main(String [] args) {
        int day = dayOfYear();
        double equationOfTime = equationOfTime(day);
        double lstm = localTimeMeridian();
        double lst = localSolarTime(equationOfTime, dcLong, lstm);
        double declination = declination(day);
        double hourAngle = hourAngle(lst);

        double zenith = zenith(dcLat, declination, hourAngle);
        double azimuth = azimuth(dcLong, declination, zenith, hourAngle); 

    }

    //Longitude of timezone meridian
    public static double localTimeMeridian() {
        TimeZone gmt = TimeZone.getTimeZone("GMT");
        TimeZone est = TimeZone.getTimeZone("EST");
        int td = gmt.getRawOffset() - est.getRawOffset();
        double localStandardTimeMeridian = 15 * (td/(1000*60*60)); //convert td to hours
        //System.out.println("Local Time Meridian: " + localStandardTimeMeridian);
        return localStandardTimeMeridian;
    }

    //Get the number of days since Jan. 1
    public static int dayOfYear() {
        Calendar localCalendar = Calendar.getInstance(TimeZone.getDefault());
        int dayOfYear = localCalendar.get(Calendar.DAY_OF_YEAR); 
        //System.out.println("Day: " + dayOfYear);
        return dayOfYear;
    }

    //Emperical equation to correct the eccentricity of Earth's orbit and axial tilt
    public static double equationOfTime (double day) {
        double d =(360.0/365.0)*(day - 81);
        d = Math.toRadians(d);
        double equationTime = 9.87*sin(2*d)-7.53*cos(d)-1.54*sin(d); 
        //System.out.println("Equation Of Time: " + equationTime);
        return equationTime;
    }
    //The angle between the equator and a line drawn from the center of the Sun(degrees)
    public static double declination(int dayOfYear) {
        double declination = 23.5*sin((Math.toRadians(360.0/365.0))*(dayOfYear - 81));
        //System.out.println("Declination: " + df.format(declination));
        return declination;
    }

    //Add the number of minutes past midnight localtime//
    public static double hourAngle(double localSolarTime) {
        double hourAngle = 15 * (localSolarTime - 13); 
        System.out.println("Hour Angle: " + df.format(hourAngle)); //(degrees)
        return hourAngle;
    }

    //Account for the variation within timezone - increases accuracy
    public static double localSolarTime(double equationOfTime, double longitude, double lstm) { 
        //LocalSolarTime = 4min * (longitude + localStandardTimeMeridian) + equationOfTime
        //Time Correction is time variation within given time zone (minutes)
        //longitude = longitude/60; //convert degrees to arcminutes
        double localStandardTimeMeridian = lstm;
        double timeCorrection = (4 * (longitude + localStandardTimeMeridian) + equationOfTime);
        System.out.println("Time Correction: " + timeCorrection); //(in minutes)
        //localSolarTime represents solar time where noon represents sun's is highest position 
        // in sky and the hour angle is 0 -- hour angle is negative in morning, and positive after solar noon.
        double localSolarTime = (localTime.toSecondOfDay() + (timeCorrection*60)); //(seconds)
        localSolarTime = localSolarTime/(60*60);  //convert from seconds to hours
        //Convert double to Time (HH:mm:ss) for console output
        int hours = (int) Math.floor(localSolarTime);
        int minutes = (int) ((localSolarTime - hours) * 60);
        //-1 for the daylight savings
        Time solarTime = new Time((hours-1), minutes, 0);
        System.out.println("Local Solar Time: " + solarTime); //hours

        return localSolarTime;
    }

    public static double azimuth(double lat, double declination, double zenith, double hourAngle) {
        double azimuthDegree = 0;
        double elevation = 90 - zenith;
        elevation = Math.toRadians(elevation);
        zenith = Math.toRadians(zenith);
        lat = Math.toRadians(lat);
        declination = Math.toRadians(declination);
        hourAngle = Math.round(hourAngle);
        hourAngle = Math.toRadians(hourAngle);

        //double azimuthRadian = -sin(hourAngle)*cos(declination) / cos(elevation);
        double azimuthRadian = ((sin(declination)*cos(lat)) - (cos(hourAngle)*cos(declination)*
                sin(lat)))/cos(elevation);

        //Account for time quadrants
        Calendar cal = Calendar.getInstance();
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        if(hour > 0 && hour < 6) {
        azimuthDegree =  Math.toDegrees(acos(azimuthRadian));
        }
        else if(hour >= 6 && hour < 12) {
            azimuthDegree = Math.toDegrees(acos(azimuthRadian));
            azimuthDegree = 180 - azimuthDegree;
        } else if (hour >= 12 && hour < 18) {
            azimuthDegree = Math.toDegrees(acos(azimuthRadian));
            azimuthDegree = azimuthDegree - 180;
        } else if (hour >= 18 && hour < 24) {
            azimuthDegree = Math.toDegrees(acos(azimuthRadian));
            azimuthDegree = 360 - azimuthDegree;
        }

        System.out.println("Azimuth: " + df.format(azimuthDegree));
        return azimuthDegree;
    }

    public static double zenith(double lat, double declination, double hourAngle) {
        lat = Math.toRadians(lat);
        declination = Math.toRadians(declination);
        hourAngle = Math.round(hourAngle);
        hourAngle = Math.toRadians(hourAngle);
        //Solar Zenith Angle 
        double zenith = Math.toDegrees(acos(sin(lat)*sin(declination) + (cos(lat)*cos(declination)*cos(hourAngle))));
        //Solar Elevation Angle
        double elevation = Math.toDegrees(asin(sin(lat)*sin(declination) + (cos(lat)*cos(declination)*cos(hourAngle))));
        System.out.println("Elevation: " + df.format(elevation));
        System.out.println("Zenith: " + df.format(zenith));
        return zenith;
    }
}

仅需重申,日期,当地时间子午线是完全正确的,并且时间和纬度等式是准确的,但不是精确的. ----更新输出----

Just to reiterate, the day, local time meridian are exactly correct, and the equation of time and declination are accurate but not exact. ----UPDATE OUTPUT----

-----更新----- 使用散点图显示全天太阳的仰角/方位角.我仍然无法确定方位角的输出.长期以来它是正确的,但随后会从增加变为减少(〜270-> 0).最终确定正确的输出后,我将确保更新代码.

-----UPDATE----- Used the scatterchart to display the sun's elevation/azimuth throughout day. I am still having trouble figuring out the azimuth output. It is correct for long time, but then it will change from increasing and start to decrease (~270-->0). I will be sure to update the code once I finally get the output right.

推荐答案

您将经度以度为单位传递给localSolarTime(),然后将其除以60,并有一条注释声称这是为了转换为弧度分钟.这是错误的;您以后的计算需要度数,即使您需要弧的分钟数,也要乘以60,而不是除.

You pass the longitude to localSolarTime() as degrees, and then you divide that by 60, with a comment claiming this is in order to convert to minutes of arc. This is wrong; your later calculations require degrees, and even if you needed minutes of arc, you'd multiply by 60, not divide.

这种错误的划分会导致经度为-1.3°,并且当您找到当地时间子午线与位置之间的角度时,您会得到一个大角度(大约75°).它应该是一个小角度,通常为7.5°.大角度会导致较大的时间校正,并且会丢掉所有内容.

This mistaken division results in a longitude of -1.3°, and when you find the angle between your local time meridian and your position, you get a large angle (about 75°). It should be a small angle, generally ±7.5°. The large angle results in a large time correction, and throws everything off.

更新:azimuth()方法的更新版本中,象限选择应基于太阳的时角,或者等效地基于当地太阳时间,而不是标准墙时钟时间.并且,在所有计算中使用的小时角不应四舍五入.与其测试四个不同的象限,不如说是这样的方法:

Update: In the updated version of the azimuth() method, the quadrant selection should be based on the hour angle of the sun, or, equivalently, on local solar time, rather than standard wall clock time. And, the hour angle used in all calculations should not be rounded. Rather than testing four different quadrants, the method could look like this:

public static double azimuth(double lat, double declination, double zenith, double hourAngle)
{
  double elevation = Math.toRadians(90 - zenith);
  lat = Math.toRadians(lat);
  declination = Math.toRadians(declination);
  hourAngle = Math.toRadians(hourAngle);
  double azimuthRadian = acos(((sin(declination) * cos(lat)) - (cos(hourAngle) * cos(declination) * sin(lat))) / cos(elevation));
  double azimuthDegree = Math.toDegrees(azimuthRadian);
  if (hourAngle > 0)
    azimuthDegree = 360 - azimuthDegree;
  System.out.println("Azimuth: " + df.format(azimuthDegree));
  return azimuthDegree;
}

最后,您将dcLong作为azimuth()方法的lat参数传入.这应该是dcLat.

Finally, you are passing dcLong in as the lat parameter of the azimuth() method; this should be dcLat.

我建议整个内部都使用弧度,并且仅在输入和输出之间进行度数转换.这将有助于防止错误,并减少舍入错误和不必要的混乱.

I'd recommend using radians internally throughout, and only converting from and to degrees on input and output. This will help prevent mistakes, and cut down on rounding errors and unnecessary clutter.

这篇关于太阳路径的计算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆