Class AstronomicalCalculator

java.lang.Object
com.kosherjava.zmanim.util.AstronomicalCalculator
All Implemented Interfaces:
Cloneable
Direct Known Subclasses:
NOAACalculator, SunTimesCalculator

public abstract class AstronomicalCalculator extends Object implements Cloneable
An abstract class that all sun time calculating classes extend. This allows the algorithm used to be changed at runtime, easily allowing comparison the results of using different algorithms.
Author:
© Eliyahu Hershfeld 2004 - 2023
TODO:
Consider methods that would allow atmospheric modeling. This can currently be adjusted by setting the refraction.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private double
    The commonly used average earth radius in KM.
    private static final double
    The zenith of astronomical sunrise and sunset.
    private double
    The commonly used average solar refraction.
    private double
    The commonly used average solar radius in minutes of a degree.
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    (package private) double
    adjustZenith(double zenith, double elevation)
    Adjusts the zenith of astronomical sunrise and sunset to account for solar refraction, solar radius and elevation.
     
    abstract String
    Returns the name of the algorithm.
    Returns the default class for calculating sunrise and sunset.
    double
    A method that returns the earth radius in KM.
    (package private) double
    getElevationAdjustment(double elevation)
    Method to return the adjustment to the zenith required to account for the elevation.
    double
    Method to get the refraction value to be used when calculating sunrise and sunset.
    double
    Method to get the sun's radius.
    abstract double
    getUTCNoon(Calendar calendar, GeoLocation geoLocation)
    Return solar noon (UTC) for the given day at the given location on earth.
    abstract double
    getUTCSunrise(Calendar calendar, GeoLocation geoLocation, double zenith, boolean adjustForElevation)
    A method that calculates UTC sunrise as well as any time based on an angle above or below sunrise.
    abstract double
    getUTCSunset(Calendar calendar, GeoLocation geoLocation, double zenith, boolean adjustForElevation)
    A method that calculates UTC sunset as well as any time based on an angle above or below sunset.
    void
    setEarthRadius(double earthRadius)
    A method that allows setting the earth's radius.
    void
    setRefraction(double refraction)
    A method to allow overriding the default refraction of the calculator.
    void
    setSolarRadius(double solarRadius)
    Method to set the sun's radius.

    Methods inherited from class java.lang.Object

    equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • refraction

      private double refraction
      The commonly used average solar refraction. Calendrical Calculations lists a more accurate global average of 34.478885263888294
      See Also:
    • solarRadius

      private double solarRadius
      The commonly used average solar radius in minutes of a degree.
      See Also:
    • earthRadius

      private double earthRadius
      The commonly used average earth radius in KM. At this time, this only affects elevation adjustment and not the sunrise and sunset calculations. The value currently defaults to 6356.9 KM.
      See Also:
    • GEOMETRIC_ZENITH

      private static final double GEOMETRIC_ZENITH
      The zenith of astronomical sunrise and sunset. The sun is 90° from the vertical 0°
      See Also:
  • Constructor Details

  • Method Details

    • getEarthRadius

      public double getEarthRadius()
      A method that returns the earth radius in KM. The value currently defaults to 6356.9 KM if not set.
      Returns:
      the earthRadius the earth radius in KM.
    • setEarthRadius

      public void setEarthRadius(double earthRadius)
      A method that allows setting the earth's radius.
      Parameters:
      earthRadius - the earthRadius to set in KM
    • getDefault

      Returns the default class for calculating sunrise and sunset. This is currently the NOAACalculator, but this may change.
      Returns:
      AstronomicalCalculator the default class for calculating sunrise and sunset. In the current implementation the default calculator returned is the NOAACalculator.
    • getCalculatorName

      public abstract String getCalculatorName()
      Returns the name of the algorithm.
      Returns:
      the descriptive name of the algorithm.
    • getUTCSunrise

      public abstract double getUTCSunrise(Calendar calendar, GeoLocation geoLocation, double zenith, boolean adjustForElevation)
      A method that calculates UTC sunrise as well as any time based on an angle above or below sunrise. This abstract method is implemented by the classes that extend this class.
      Parameters:
      calendar - Used to calculate day of year.
      geoLocation - The location information used for astronomical calculating sun times.
      zenith - the azimuth below the vertical zenith of 90 degrees. for sunrise typically the zenith used for the calculation uses geometric zenith of 90° and adjusts this slightly to account for solar refraction and the sun's radius. Another example would be AstronomicalCalendar.getBeginNauticalTwilight() that passes AstronomicalCalendar.NAUTICAL_ZENITH to this method.
      adjustForElevation - Should the time be adjusted for elevation
      Returns:
      The UTC time of sunrise in 24 hour format. 5:45:00 AM will return 5.75.0. If an error was encountered in the calculation (expected behavior for some locations such as near the poles, Double.NaN will be returned.
      See Also:
    • getUTCSunset

      public abstract double getUTCSunset(Calendar calendar, GeoLocation geoLocation, double zenith, boolean adjustForElevation)
      A method that calculates UTC sunset as well as any time based on an angle above or below sunset. This abstract method is implemented by the classes that extend this class.
      Parameters:
      calendar - Used to calculate day of year.
      geoLocation - The location information used for astronomical calculating sun times.
      zenith - the azimuth below the vertical zenith of 90°. For sunset typically the zenith used for the calculation uses geometric zenith of 90° and adjusts this slightly to account for solar refraction and the sun's radius. Another example would be AstronomicalCalendar.getEndNauticalTwilight() that passes AstronomicalCalendar.NAUTICAL_ZENITH to this method.
      adjustForElevation - Should the time be adjusted for elevation
      Returns:
      The UTC time of sunset in 24 hour format. 5:45:00 AM will return 5.75.0. If an error was encountered in the calculation (expected behavior for some locations such as near the poles, Double.NaN will be returned.
      See Also:
    • getUTCNoon

      public abstract double getUTCNoon(Calendar calendar, GeoLocation geoLocation)
      Return solar noon (UTC) for the given day at the given location on earth. The the NOAACalculator implementation calculates true solar noon, while the SunTimesCalculator approximates it, calculating the time as halfway between sunrise and sunset.
      Parameters:
      calendar - Used to calculate day of year.
      geoLocation - The location information used for astronomical calculating sun times.
      Returns:
      the time in minutes from zero UTC
    • getElevationAdjustment

      double getElevationAdjustment(double elevation)
      Method to return the adjustment to the zenith required to account for the elevation. Since a person at a higher elevation can see farther below the horizon, the calculation for sunrise / sunset is calculated below the horizon used at sea level. This is only used for sunrise and sunset and not times before or after it such as nautical twilight since those calculations are based on the level of available light at the given dip below the horizon, something that is not affected by elevation, the adjustment should only made if the zenith == 90° adjusted for refraction and solar radius. The algorithm used is
       elevationAdjustment = Math.toDegrees(Math.acos(earthRadiusInMeters / (earthRadiusInMeters + elevationMeters)));
       
      The source of this algorithm is Calendrical Calculations by Edward M. Reingold and Nachum Dershowitz. An alternate algorithm that produces an almost identical (but not accurate) result found in Ma'aglay Tzedek by Moishe Kosower and other sources is:
       elevationAdjustment = 0.0347 * Math.sqrt(elevationMeters);
       
      Parameters:
      elevation - elevation in Meters.
      Returns:
      the adjusted zenith
    • adjustZenith

      double adjustZenith(double zenith, double elevation)
      Adjusts the zenith of astronomical sunrise and sunset to account for solar refraction, solar radius and elevation. The value for Sun's zenith and true rise/set Zenith (used in this class and subclasses) is the angle that the center of the Sun makes to a line perpendicular to the Earth's surface. If the Sun were a point and the Earth were without an atmosphere, true sunset and sunrise would correspond to a 90° zenith. Because the Sun is not a point, and because the atmosphere refracts light, this 90° zenith does not, in fact, correspond to true sunset or sunrise, instead the center of the Sun's disk must lie just below the horizon for the upper edge to be obscured. This means that a zenith of just above 90° must be used. The Sun subtends an angle of 16 minutes of arc (this can be changed via the setSolarRadius(double) method , and atmospheric refraction accounts for 34 minutes or so (this can be changed via the setRefraction(double) method), giving a total of 50 arcminutes. The total value for ZENITH is 90+(5/6) or 90.8333333° for true sunrise/sunset. Since a person at an elevation can see blow the horizon of a person at sea level, this will also adjust the zenith to account for elevation if available. Note that this will only adjust the value if the zenith is exactly 90 degrees. For values below and above this no correction is done. As an example, astronomical twilight is when the sun is 18° below the horizon or 108° below the zenith. This is traditionally calculated with none of the above mentioned adjustments. The same goes for various tzais and alos times such as the 16.1° dip used in ComplexZmanimCalendar.getAlos16Point1Degrees().
      Parameters:
      zenith - the azimuth below the vertical zenith of 90°. For sunset typically the zenith used for the calculation uses geometric zenith of 90° and adjusts this slightly to account for solar refraction and the sun's radius. Another example would be AstronomicalCalendar.getEndNauticalTwilight() that passes AstronomicalCalendar.NAUTICAL_ZENITH to this method.
      elevation - elevation in Meters.
      Returns:
      The zenith adjusted to include the sun's radius, refraction and elevation adjustment. This will only be adjusted for sunrise and sunset (if the zenith == 90°)
      See Also:
    • getRefraction

      public double getRefraction()
      Method to get the refraction value to be used when calculating sunrise and sunset. The default value is 34 arc minutes. The Errata and Notes for Calendrical Calculations: The Millennium Edition by Edward M. Reingold and Nachum Dershowitz lists the actual average refraction value as 34.478885263888294 or approximately 34' 29". The refraction value as well as the solarRadius and elevation adjustment are added to the zenith used to calculate sunrise and sunset.
      Returns:
      The refraction in arc minutes.
    • setRefraction

      public void setRefraction(double refraction)
      A method to allow overriding the default refraction of the calculator.
      Parameters:
      refraction - The refraction in arc minutes.
      See Also:
      TODO:
      At some point in the future, an AtmosphericModel or Refraction object that models the atmosphere of different locations might be used for increased accuracy.
    • getSolarRadius

      public double getSolarRadius()
      Method to get the sun's radius. The default value is 16 arc minutes. The sun's radius as it appears from earth is almost universally given as 16 arc minutes but in fact it differs by the time of the year. At the perihelion it has an apparent radius of 16.293, while at the aphelion it has an apparent radius of 15.755. There is little affect for most location, but at high and low latitudes the difference becomes more apparent. My Calculations for the difference at the location of the Royal Observatory, Greenwich shows only a 4.494 second difference between the perihelion and aphelion radii, but moving into the arctic circle the difference becomes more noticeable. Tests for Tromso, Norway (latitude 69.672312, longitude 19.049787) show that on May 17, the rise of the midnight sun, a 2 minute 23 second difference is observed between the perihelion and aphelion radii using the USNO algorithm, but only 1 minute and 6 seconds difference using the NOAA algorithm. Areas farther north show an even greater difference. Note that these test are not real valid test cases because they show the extreme difference on days that are not the perihelion or aphelion, but are shown for illustrative purposes only.
      Returns:
      The sun's radius in arc minutes.
    • setSolarRadius

      public void setSolarRadius(double solarRadius)
      Method to set the sun's radius.
      Parameters:
      solarRadius - The sun's radius in arc minutes.
      See Also:
    • clone

      public Object clone()
      Overrides:
      clone in class Object
      Since:
      1.1
      See Also: