Sun position
Sun position algorithm
main.c
Go to the documentation of this file.
1 /*============================================================================*/
2 /*!\file
3  *
4  * \brief main.c - Simple demo program for Sun position using rectangular
5  * coordinates
6  *
7  * \author David Hoadley <vcrumble@westnet.com.au>
8  *
9  * \details
10  * See [the main page](@ref index) (or the end of this source file) for a
11  * description of this file.
12  *
13  * \copyright
14  * \parblock
15  * Copyright (c) 2020, David Hoadley <vcrumble@westnet.com.au>
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are met:
20  *
21  * * Redistributions of source code must retain the above copyright notice, this
22  * list of conditions and the following disclaimer.
23  * * Redistributions in binary form must reproduce the above copyright notice,
24  * this list of conditions and the following disclaimer in the documentation
25  * and/or other materials provided with the distribution.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  * \endparblock
39  *
40  *==============================================================================
41  */
42 
43 /* ANSI includes etc. */
44 #include <stdio.h>
45 #include <time.h>
46 #include <unistd.h>
47 
48 /* Local and project includes */
49 #include "general.h"
50 #include "sky.h"
51 #include "skyio.h"
52 #include "sun.h"
53 #include "skyfast.h"
54 #include "vectors3d.h"
55 
56 #define SITE_LATITUDE_deg -37.8236 /*!< North lats +ve, south -ve (deg) */
57 #define SITE_LONGITUDE_deg 144.9913 /*!< East lons +ve, west -ve (degrees)*/
58 #define SITE_HEIGHT_m 30.0 /*!< Height above sea level (metres) */
59 #define SITE_PRESSURE_hPa 1013.0 /*!< Atmospheric pressure (hPa = mbar)*/
60 #define SITE_TEMPERATURE_degC 15.0 /*!< Temperature (degrees Celsius) */
61 #define SITE_TIMEZONE_h 10.0 /*!< East zones +ve, west -ve (hours) */
62 
63 
64 void demo1(void);
65 void demo2(void);
66 void demo4(void);
67 void sunTopocentricFast(double j2kUtc_d,
68  const Sky_DeltaTs *dTs,
69  const Sky_SiteProp *site,
70  Sky_SiteHorizon *topo);
71 
72 
73 
74 int main(void)
75 {
76  demo1();
77  demo2();
78 }
79 
80 
81 
82 void sunTopocentricFast(double j2kUtc_d,
83  const Sky_DeltaTs *dTs,
84  const Sky_SiteProp *site,
85  Sky_SiteHorizon *topo)
86 /*! Uses previously calculated values of the Sun's apparent coordinates and
87  interpolation to quickly calculate the Sun's topocentric position.
88  \param[in] j2kUtc_d Days since Greenwich noon, 1-Jan-2000, UTC timescale
89  \param[in] deltas Delta T values, as set by the sky_initTime() (or
90  sky_initTimeSimple() or sky_initTimeDetailed()) routines
91  \param[in] site Properties of the observing site, particularly its
92  geometric location on the surface of the Earth, as set by
93  the sky_setSiteLocation() function (or sky_setSiteLoc2())
94  \param[out] topo Topocentric position, in both rectangular (unit vector)
95  form, and as Azimuth and Elevation (altitude) angles
96 
97  \par When to call this function
98  This function is designed to be called at high frequency (more than once
99  per second, even up to, say, 20 Hz).
100  \par
101  Use this function when you have made a previous call to skyfast_init().
102  Depending on how long a period you want to track the sun using this
103  routine, you may also need to run the function skyfast_backgroundUpdate() as
104  a low frequency, low priority routine, to update the interpolation ranges.
105  If you have not done this, call sun_nrelTopocentric() instead.
106 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
107 {
108  Sky_Times atime;
109  Sky_TrueEquatorial approx;
110  V3D_Vector terInterV;// unit vector in Terrestrial Intermed Ref Sys
111 
112  REQUIRE_NOT_NULL(dTs);
113  REQUIRE_NOT_NULL(site);
114  REQUIRE_NOT_NULL(topo);
115 
116  sky_updateTimes(j2kUtc_d, dTs, &atime);
117 
118  /* Get the approximate apparent coordinates by interpolation */
119  skyfast_getApprox(atime.j2kTT_cy, &approx);
120 
121  /* Convert apparent coordinates to topocentric coordinates at the site */
122  sky0_appToTirs(&approx.appCirsV,
123  atime.j2kUT1_d,
124  approx.eqEq_rad,
125  &terInterV);
126  sky_siteTirsToTopo(&terInterV, approx.distance_au, site, topo);
127 }
128 
129 
130 
131 void demo1(void)
132 /*! Sample code demonstrating the calculation of the position of the Sun using
133  * rectangular coordinates
134 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
135 {
136  Sky_DeltaTs deltaTs; /* Differences between timescales */
137  Sky_SiteProp site; /* Properties of the site */
138  Sky_SiteHorizon topo; /* Sun position, as seen from the site */
139  double j2kUtc_d; /* Time, expressed as a count of days */
140  char azStr[24], elStr[24];
141 
142  /* Set up the various delta T values */
143  sky_initTime(37, 0, &deltaTs);
144 
145  /* Set up the fixed site data */
149  &site);
152  &site);
154 
155  /* Get the current time in days since 2000-01-01 Greenwich noon */
156  j2kUtc_d = sky_unixTimeToJ2kd(time(NULL));
157 
158  /* Get sun position */
159  sun_nrelTopocentric(j2kUtc_d, &deltaTs, &site, &topo);
160 
161  /* Print out time and place */
162  printf("Full sun calculation\n");
163  skyio_printJ2kd(j2kUtc_d + site.timeZone_d);
164  skyio_radToDmsStr(azStr, sizeof(azStr), topo.azimuth_rad, 2);
165  skyio_radToDmsStr(elStr, sizeof(elStr), topo.elevation_rad, 2);
166  printf(" Sun Azimuth: %s, Elevation: %s\n", azStr, elStr);
167 }
168 
169 
170 
171 void demo2(void)
172 /*! Sample code using the greatly simplified calculation of the position
173  * of the Sun using interpolated coordinates.
174 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
175 {
176  Sky_DeltaTs deltaTs; /* Differences between timescales */
177  Sky_SiteProp site; /* Properties of the site */
178  Sky_SiteHorizon topo; /* Sun position, as seen from the site */
179  double j2kUtc_d; /* Time, expressed as a count of days */
180  char azStr[24], elStr[24];
181  int i;
182 
183  /* Set up the various delta T values. Values are taken from Bulletin A of
184  * 16-Jul-2020, using the approximate "DUT1" value for deltaUT_s */
185  sky_initTime(37, -0.2, &deltaTs);
186 
187  /* Set up the fixed site data */
191  &site);
194  &site);
196 
197  /* Get the current time in days since 2000-01-01 Greenwich noon */
198  j2kUtc_d = sky_unixTimeToJ2kd(time(NULL));
199 
200  /* Set up the interpolation algorithm to calculate Sun positions */
201  skyfast_init(j2kUtc_d, 720, &deltaTs, &sun_nrelApparent);
202 
203  printf("Fast sun calculation\n");
204  for (i = 0; i < 100; i++) {
205  /* Get sun position using interpolation */
206  j2kUtc_d = sky_unixTimeToJ2kd(time(NULL));
207  sunTopocentricFast(j2kUtc_d, &deltaTs, &site, &topo);
208 
209  skyio_printJ2kd(j2kUtc_d + site.timeZone_d);
210  skyio_radToDmsStr(azStr, sizeof(azStr), topo.azimuth_rad, 2);
211  skyio_radToDmsStr(elStr, sizeof(elStr), topo.elevation_rad, 2);
212  printf(" Sun Azimuth: %s, Elevation: %s\n", azStr, elStr);
213 
214  sleep(1); /* Just use a simple delay for this demo. */
215  }
216 }
217 
218 /*!
219  * \mainpage
220  *
221  * \author David Hoadley <vcrumble@westnet.com.au>
222  *
223  * \version $(DOXYGEN_APP_VER)
224  *
225  * \details
226  * This program calls two demo routines to calculate the Sun's position.
227  * The first (called demo1()) calculates it using the NREL SPA algorithm
228  * (see reference), but implemented in rectangular coordinates.
229  * The second (called demo2()) runs a loop to repeatedly calculate the
230  * position, but using interpolation between two previously calculated
231  * positions.
232  *
233  * The interpolation will introduce a very small error in position. For the
234  * value of 720 minutes supplied to routine skyfast_init(), the maximum
235  * error that is introduced is less than 0.075 arcseconds.
236  * Given that the NREL-SPA algorithm itself is only
237  * accurate to approximately 1 arcsecond, this is pretty good.
238  *
239  * This demo shows some of the use of the routines in sky.h and sun.h,
240  * and for interpolation, skyfast.h.
241  *
242  * \par Reference:
243  * Reda, Ibrahim and Andreas, Afshin.
244  * _Solar Position Algorithm for Solar Radiation Applications._
245  * National Renewable Energy Laboratory, publication no.
246  * NREL/TP-560-34302, June 2003, revised January 2008
247  *
248  * \copyright
249  * \parblock
250  * Copyright (c) 2020, David Hoadley <vcrumble@westnet.com.au>
251  * All rights reserved.
252  *
253  * Redistribution and use in source and binary forms, with or without
254  * modification, are permitted provided that the following conditions are met:
255  *
256  * * Redistributions of source code must retain the above copyright notice, this
257  * list of conditions and the following disclaimer.
258  * * Redistributions in binary form must reproduce the above copyright notice,
259  * this list of conditions and the following disclaimer in the documentation
260  * and/or other materials provided with the distribution.
261  *
262  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
263  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
264  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
265  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
266  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
267  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
268  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
269  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
270  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
271  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
272  * POSSIBILITY OF SUCH DAMAGE.
273  * \endparblock
274  */
275 /*! \example demo1_sun.c Single calculation of the Sun's position
276  * \example demo2_sun_tracking.c
277  * Repeated calculation (tracking) of the Sun using
278  * interpolation
279  * \example demo3_moon.c
280  * Single calculation of the Moon's position
281  * \example demo4_multiple_sites.c
282  * Repeated calculation of the Sun's position for three
283  * European sites simultaneously. This demo also shows the
284  * use of the sky_initTimeDetailed() function.
285  */
286 
general.h
general.h - definitions of general use to (standard) C programs
Sky_TrueEquatorial::appCirsV
V3D_Vector appCirsV
Direction of object in apparent or CIRS coordinates (effectively a unit vector).
Definition: sky.h:110
SITE_TIMEZONE_h
#define SITE_TIMEZONE_h
East zones +ve, west -ve (hours)
Definition: main.c:61
Sky_DeltaTs
This structure contains relatively constant data, and is set up by one of the three functions sky_ini...
Definition: sky.h:166
skyio.h
skyio.h - output and formatting routines and a read routine
skyio_radToDmsStr
static char * skyio_radToDmsStr(char destStr[], size_t destStrSize, double angle_rad, unsigned decimals)
Routine to take an angle in radian and return a string in degrees, arcminutes and arcseconds form - [...
Definition: skyio.h:111
sky_siteTirsToTopo
void sky_siteTirsToTopo(const V3D_Vector *terInterV, double dist_au, const Sky_SiteProp *site, Sky_SiteHorizon *topo)
Transform a coordinate vector from the Terrestrial Intermediate Reference System to topocentric Az/El...
Definition: sky-site.c:378
sky_updateTimes
void sky_updateTimes(double j2kUtc_d, const Sky_DeltaTs *d, Sky_Times *t)
Convert the given "J2KD" in the UTC timescale to the other timescales, and pre-calculate some other q...
Definition: sky-time.c:206
Sky_TrueEquatorial
Struct used for holding an object's coordinates in equatorial apparent or Intermediate coordinates.
Definition: sky.h:106
sun_nrelTopocentric
void sun_nrelTopocentric(double j2kUtc_d, const Sky_DeltaTs *deltas, const Sky_SiteProp *site, Sky_SiteHorizon *topo)
Calls sun_nrelApparent() to calculate the Sun's position in apparent coordinates using the NREL Sun P...
Definition: sun.c:266
skyfast_getApprox
void skyfast_getApprox(double t_cy, Sky_TrueEquatorial *approx)
Get the best approximation to the celestial object's apparent coordinates and distance,...
Definition: skyfast.c:234
SITE_PRESSURE_hPa
#define SITE_PRESSURE_hPa
Atmospheric pressure (hPa = mbar)
Definition: main.c:59
sky_setSiteLocation
void sky_setSiteLocation(double latitude_deg, double longitude_deg, double height_m, Sky_SiteProp *site)
Initialise the site structure by calculating those site-related values that do not change with time.
Definition: sky-site.c:105
Sky_Times::j2kTT_cy
double j2kTT_cy
Julian centuries since J2000.0, TT timescale [T].
Definition: sky.h:188
demo2
void demo2(void)
Sample code using the greatly simplified calculation of the position of the Sun using interpolated co...
Definition: main.c:171
REQUIRE_NOT_NULL
#define REQUIRE_NOT_NULL(pointer_)
,
Definition: general.h:308
SITE_TEMPERATURE_degC
#define SITE_TEMPERATURE_degC
Temperature (degrees Celsius)
Definition: main.c:60
Sky_Times
This structure contains the continuously varying time (and earth rotation) data, in various forms tha...
Definition: sky.h:184
SITE_LONGITUDE_deg
#define SITE_LONGITUDE_deg
East lons +ve, west -ve (degrees)
Definition: main.c:57
SITE_HEIGHT_m
#define SITE_HEIGHT_m
Height above sea level (metres)
Definition: main.c:58
Sky_TrueEquatorial::eqEq_rad
double eqEq_rad
Equation of the Equinoxes (radian).
Definition: sky.h:115
Sky_SiteProp
Site properties.
Definition: sky.h:315
sky0_appToTirs
void sky0_appToTirs(const V3D_Vector *appV, double j2kUT1_d, double eqEq_rad, V3D_Vector *terInterV)
Convert a position in geocentric apparent coordinates to geocentric coordinates in the Terrestrial In...
Definition: sky0.c:432
Sky_SiteHorizon::azimuth_rad
double azimuth_rad
azimuth (radian)
Definition: sky.h:131
skyfast_init
void skyfast_init(double tStartUtc_d, int fullRecalcInterval_mins, const Sky_DeltaTs *deltas, void(*getApparent)(double j2kTT_cy, Sky_TrueEquatorial *pos))
Initialise those items that take a long time to calculate, but which do not need to be recalculated f...
Definition: skyfast.c:111
SITE_LATITUDE_deg
#define SITE_LATITUDE_deg
North lats +ve, south -ve (deg)
Definition: main.c:56
Sky_SiteProp::timeZone_d
double timeZone_d
time zone offset from UTC (fraction of a day)
Definition: sky.h:323
Sky_TrueEquatorial::distance_au
double distance_au
Distance to object (Astronomical Units) or 0.0 for far distant objects (that is, those with negligibl...
Definition: sky.h:112
sunTopocentricFast
void sunTopocentricFast(double j2kUtc_d, const Sky_DeltaTs *dTs, const Sky_SiteProp *site, Sky_SiteHorizon *topo)
Uses previously calculated values of the Sun's apparent coordinates and interpolation to quickly calc...
Definition: main.c:82
V3D_Vector
3x1 vector.
Definition: vectors3d.h:57
sky_unixTimeToJ2kd
double sky_unixTimeToJ2kd(time_t unixTime)
Convert a time in Unix system time format to days since 2000 Jan 1, noon UTC.
Definition: sky-time.c:275
sky_setSiteTimeZone
void sky_setSiteTimeZone(double timeZone_h, Sky_SiteProp *site)
Set the time zone offset for this site.
Definition: sky-site.c:293
demo1
void demo1(void)
Sample code demonstrating the calculation of the position of the Sun using rectangular coordinates.
Definition: main.c:131
sky_setSiteTempPress
void sky_setSiteTempPress(double temperature_degC, double pressure_hPa, Sky_SiteProp *site)
Set refraction coefficients based on atmospheric temperature and pressure at the site.
Definition: sky-site.c:261
sky_initTime
void sky_initTime(int deltaAT_s, double deltaUT_s, Sky_DeltaTs *d)
This is one of three alternative routines for setting up the various delta time values for use in ong...
Definition: sky-time.c:96
sky.h
sky.h - structures and routines for astronomical observing & tracking
vectors3d.h
vectors3d.h - Three dimensional geometry, vectors and matrices
sun_nrelApparent
void sun_nrelApparent(double j2kTT_cy, Sky_TrueEquatorial *pos)
Calculate the Sun's position as a unit vector and a distance, in apparent coordinates.
Definition: sun.c:211
skyio_printJ2kd
void skyio_printJ2kd(double j2kd)
Write out a J2KD as a calendar date and time.
Definition: skyio.c:426
Sky_SiteHorizon::elevation_rad
double elevation_rad
elevation (or altitude) (radian)
Definition: sky.h:132
Sky_Times::j2kUT1_d
double j2kUT1_d
days since J2000.0, UT1 timescale [Du]
Definition: sky.h:186
skyfast.h
skyfast.h - set up and use interpolation for rapid calculation of a celestial object's apparent coord...
sun.h
sun.h - routines to calculate the Sun's position
Sky_SiteHorizon
Coordinates of a celestial object in the horizon frame, in both rectangular and polar forms.
Definition: sky.h:129