# Code from http://stackoverflow.com/a/8764866/1468366 by Josh O'Brien,
# augmented for for http://stackoverflow.com/q/19165498/1468366
sunPosition <- function(year, month, day, hour=12, min=0, sec=0,
lat=46.5, long=6.5) {
twopi <- 2 * pi
cat("twopi =", twopi, "\n")
deg2rad <- pi / 180
cat("deg2rad =", deg2rad, "\n")
# Get day of the year, e.g. Feb 1 = 32, Mar 1 = 61 on leap years
month.days <- c(0,31,28,31,30,31,30,31,31,30,31,30)
cat("month.days =", month.days, "\n")
day <- day + cumsum(month.days)[month]
cat("day =", day, "\n")
leapdays <- year %% 4 == 0 & (year %% 400 == 0 | year %% 100 != 0) &
day >= 60 & !(month==2 & day==60)
cat("leapdays =", leapdays, "\n")
day[leapdays] <- day[leapdays] + 1
cat("day[", leapdays, "] =", day[leapdays], "\n")
cat("day =", day, "\n")
# Get Julian date - 2400000
hour <- hour + min / 60 + sec / 3600 # hour plus fraction
cat("hour =", hour, "\n")
delta <- year - 1949
cat("delta =", delta, "\n")
leap <- trunc(delta / 4) # former leapyears
cat("leap =", leap, "\n")
jd <- 32916.5 + delta * 365 + leap + day + hour / 24
cat("jd =", jd, "\n")
# The input to the Atronomer's almanach is the difference between
# the Julian date and JD 2451545.0 (noon, 1 January 2000)
cat("time =", time, "\n")
# Ecliptic coordinates
# Mean longitude
mnlong
<- 280.460 + .9856474 * time cat("mnlong =", mnlong, "\n")
mnlong <- mnlong %% 360
cat("mnlong =", mnlong, "\n")
cat("mnlong[", mnlong < 0, "] =", mnlong[mnlong < 0] + 360, "\n")
mnlong[mnlong < 0] <- mnlong[mnlong < 0] + 360
cat("mnlong =", mnlong, "\n")
# Mean anomaly
mnanom
<- 357.528 + .9856003 * time cat("mnanom =", mnanom, "\n")
mnanom <- mnanom %% 360
cat("mnanom =", mnanom, "\n")
cat("mnanom[", mnanom < 0, "] =", mnanom[mnanom < 0] + 360, "\n")
mnanom[mnanom < 0] <- mnanom[mnanom < 0] + 360
cat("mnanom =", mnanom, "\n")
mnanom <- mnanom * deg2rad
cat("mnanom =", mnanom, "\n")
# Ecliptic longitude and obliquity of ecliptic
eclong
<- mnlong
+ 1.915 * sin(mnanom
) + 0.020 * sin(2 * mnanom
) cat("eclong =", eclong, "\n")
eclong <- eclong %% 360
cat("eclong =", eclong, "\n")
cat("eclong[", eclong < 0, "] =", eclong[eclong < 0] + 360, "\n")
eclong[eclong < 0] <- eclong[eclong < 0] + 360
cat("eclong =", eclong, "\n")
oblqec
<- 23.439 - 0.0000004 * time cat("oblqec =", oblqec, "\n")
eclong <- eclong * deg2rad
cat("eclong =", eclong, "\n")
oblqec <- oblqec * deg2rad
cat("oblqec =", oblqec, "\n")
# Celestial coordinates
# Right ascension and declination
num
<- cos(oblqec
) * sin(eclong
) cat("num =", num, "\n")
cat("den =", den, "\n")
cat("ra =", ra, "\n")
ra[den < 0] <- ra[den < 0] + pi
cat("ra[", den < 0, "] =", ra[den < 0], "\n")
ra[den >= 0 & num < 0] <- ra[den >= 0 & num < 0] + twopi
cat("ra[", den >= 0 & num < 0, "] =", ra[den >= 0 & num < 0], "\n")
cat("ra =", ra, "\n")
cat("dec =", dec, "\n")
# Local coordinates
# Greenwich mean sidereal time
gmst
<- 6.697375 + .0657098242 * time + hour
cat("gmst =", gmst, "\n")
gmst <- gmst %% 24
cat("gmst =", gmst, "\n")
cat("gmst[", gmst < 0, "] =", gmst[gmst < 0] + 24., "\n")
gmst[gmst < 0] <- gmst[gmst < 0] + 24.
# Local mean sidereal time
lmst <- gmst + long / 15.
cat("lmst =", lmst, "\n")
lmst <- lmst %% 24.
cat("lmst =", lmst, "\n")
cat("lmst[", lmst < 0, "] =", lmst[lmst < 0] + 24., "\n")
lmst[lmst < 0] <- lmst[lmst < 0] + 24.
lmst <- lmst * 15. * deg2rad
cat("lmst =", lmst, "\n")
# Hour angle
ha <- lmst - ra
cat("ha =", ha, "\n")
cat("ha[", ha < -pi, "] =", ha[ha < -pi] + twopi, "\n")
ha[ha < -pi] <- ha[ha < -pi] + twopi
cat("ha[", ha > pi, "] =", ha[ha > pi] - twopi, "\n")
ha[ha > pi] <- ha[ha > pi] - twopi
# Latitude to radians
lat <- lat * deg2rad
cat("lat =", lat, "\n")
# Azimuth and elevation
cat("el =", el, "\n")
cat("az =", az, "\n")
# For logic and names, see Spencer, J.W. 1989. Solar Energy. 42(4):353
cosAzPos
<- (0 <= sin(dec
) - sin(el
) * sin(lat
)) cat("cosAzPos =", cosAzPos, "\n")
sinAzNeg
<- (sin(az
) < 0) cat("sinAzNeg =", sinAzNeg, "\n")
az[cosAzPos & sinAzNeg] <- az[cosAzPos & sinAzNeg] + twopi
cat("az[", cosAzPos & sinAzNeg, "] =", az[cosAzPos & sinAzNeg], "\n")
az[!cosAzPos] <- pi - az[!cosAzPos]
cat("az[", !cosAzPos, "] =", az[!cosAzPos], "\n")
el <- el / deg2rad
cat("el =", el, "\n")
az <- az / deg2rad
cat("az =", az, "\n")
lat <- lat / deg2rad
cat("lat =", lat, "\n")
return(list(elevation=el, azimuth=az))
}
sunPosition(2013, 9, 1, 10, 0, 0, -4.77867, 11.86364)
IyBDb2RlIGZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvODc2NDg2Ni8xNDY4MzY2IGJ5IEpvc2ggTydCcmllbiwKIyBhdWdtZW50ZWQgZm9yIGZvciBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcS8xOTE2NTQ5OC8xNDY4MzY2CgpzdW5Qb3NpdGlvbiA8LSBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5LCBob3VyPTEyLCBtaW49MCwgc2VjPTAsCiAgICAgICAgICAgICAgICAgICAgbGF0PTQ2LjUsIGxvbmc9Ni41KSB7CgogICAgdHdvcGkgPC0gMiAqIHBpCiAgICBjYXQoInR3b3BpID0iLCB0d29waSwgIlxuIikKICAgIGRlZzJyYWQgPC0gcGkgLyAxODAKICAgIGNhdCgiZGVnMnJhZCA9IiwgZGVnMnJhZCwgIlxuIikKCiAgICAjIEdldCBkYXkgb2YgdGhlIHllYXIsIGUuZy4gRmViIDEgPSAzMiwgTWFyIDEgPSA2MSBvbiBsZWFwIHllYXJzCiAgICBtb250aC5kYXlzIDwtIGMoMCwzMSwyOCwzMSwzMCwzMSwzMCwzMSwzMSwzMCwzMSwzMCkKICAgIGNhdCgibW9udGguZGF5cyA9IiwgbW9udGguZGF5cywgIlxuIikKICAgIGRheSA8LSBkYXkgKyBjdW1zdW0obW9udGguZGF5cylbbW9udGhdCiAgICBjYXQoImRheSA9IiwgZGF5LCAiXG4iKQogICAgbGVhcGRheXMgPC0geWVhciAlJSA0ID09IDAgJiAoeWVhciAlJSA0MDAgPT0gMCB8IHllYXIgJSUgMTAwICE9IDApICYgCiAgICAgICAgICAgICAgICBkYXkgPj0gNjAgJiAhKG1vbnRoPT0yICYgZGF5PT02MCkKICAgIGNhdCgibGVhcGRheXMgPSIsIGxlYXBkYXlzLCAiXG4iKQogICAgZGF5W2xlYXBkYXlzXSA8LSBkYXlbbGVhcGRheXNdICsgMQogICAgY2F0KCJkYXlbIiwgbGVhcGRheXMsICJdID0iLCBkYXlbbGVhcGRheXNdLCAiXG4iKQogICAgY2F0KCJkYXkgPSIsIGRheSwgIlxuIikKCiAgICAjIEdldCBKdWxpYW4gZGF0ZSAtIDI0MDAwMDAKICAgIGhvdXIgPC0gaG91ciArIG1pbiAvIDYwICsgc2VjIC8gMzYwMCAjIGhvdXIgcGx1cyBmcmFjdGlvbgogICAgY2F0KCJob3VyID0iLCBob3VyLCAiXG4iKQogICAgZGVsdGEgPC0geWVhciAtIDE5NDkKICAgIGNhdCgiZGVsdGEgPSIsIGRlbHRhLCAiXG4iKQogICAgbGVhcCA8LSB0cnVuYyhkZWx0YSAvIDQpICMgZm9ybWVyIGxlYXB5ZWFycwogICAgY2F0KCJsZWFwID0iLCBsZWFwLCAiXG4iKQogICAgamQgPC0gMzI5MTYuNSArIGRlbHRhICogMzY1ICsgbGVhcCArIGRheSArIGhvdXIgLyAyNAogICAgY2F0KCJqZCA9IiwgamQsICJcbiIpCgogICAgIyBUaGUgaW5wdXQgdG8gdGhlIEF0cm9ub21lcidzIGFsbWFuYWNoIGlzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4KICAgICMgdGhlIEp1bGlhbiBkYXRlIGFuZCBKRCAyNDUxNTQ1LjAgKG5vb24sIDEgSmFudWFyeSAyMDAwKQogICAgdGltZSA8LSBqZCAtIDUxNTQ1LgogICAgY2F0KCJ0aW1lID0iLCB0aW1lLCAiXG4iKQoKICAgICMgRWNsaXB0aWMgY29vcmRpbmF0ZXMKCiAgICAjIE1lYW4gbG9uZ2l0dWRlCiAgICBtbmxvbmcgPC0gMjgwLjQ2MCArIC45ODU2NDc0ICogdGltZQogICAgY2F0KCJtbmxvbmcgPSIsIG1ubG9uZywgIlxuIikKICAgIG1ubG9uZyA8LSBtbmxvbmcgJSUgMzYwCiAgICBjYXQoIm1ubG9uZyA9IiwgbW5sb25nLCAiXG4iKQogICAgY2F0KCJtbmxvbmdbIiwgbW5sb25nIDwgMCwgIl0gPSIsIG1ubG9uZ1ttbmxvbmcgPCAwXSArIDM2MCwgIlxuIikKICAgIG1ubG9uZ1ttbmxvbmcgPCAwXSA8LSBtbmxvbmdbbW5sb25nIDwgMF0gKyAzNjAKICAgIGNhdCgibW5sb25nID0iLCBtbmxvbmcsICJcbiIpCgogICAgIyBNZWFuIGFub21hbHkKICAgIG1uYW5vbSA8LSAzNTcuNTI4ICsgLjk4NTYwMDMgKiB0aW1lCiAgICBjYXQoIm1uYW5vbSA9IiwgbW5hbm9tLCAiXG4iKQogICAgbW5hbm9tIDwtIG1uYW5vbSAlJSAzNjAKICAgIGNhdCgibW5hbm9tID0iLCBtbmFub20sICJcbiIpCiAgICBjYXQoIm1uYW5vbVsiLCBtbmFub20gPCAwLCAiXSA9IiwgbW5hbm9tW21uYW5vbSA8IDBdICsgMzYwLCAiXG4iKQogICAgbW5hbm9tW21uYW5vbSA8IDBdIDwtIG1uYW5vbVttbmFub20gPCAwXSArIDM2MAogICAgY2F0KCJtbmFub20gPSIsIG1uYW5vbSwgIlxuIikKICAgIG1uYW5vbSA8LSBtbmFub20gKiBkZWcycmFkCiAgICBjYXQoIm1uYW5vbSA9IiwgbW5hbm9tLCAiXG4iKQoKICAgICMgRWNsaXB0aWMgbG9uZ2l0dWRlIGFuZCBvYmxpcXVpdHkgb2YgZWNsaXB0aWMKICAgIGVjbG9uZyA8LSBtbmxvbmcgKyAxLjkxNSAqIHNpbihtbmFub20pICsgMC4wMjAgKiBzaW4oMiAqIG1uYW5vbSkKICAgIGNhdCgiZWNsb25nID0iLCBlY2xvbmcsICJcbiIpCiAgICBlY2xvbmcgPC0gZWNsb25nICUlIDM2MAogICAgY2F0KCJlY2xvbmcgPSIsIGVjbG9uZywgIlxuIikKICAgIGNhdCgiZWNsb25nWyIsIGVjbG9uZyA8IDAsICJdID0iLCBlY2xvbmdbZWNsb25nIDwgMF0gKyAzNjAsICJcbiIpCiAgICBlY2xvbmdbZWNsb25nIDwgMF0gPC0gZWNsb25nW2VjbG9uZyA8IDBdICsgMzYwCiAgICBjYXQoImVjbG9uZyA9IiwgZWNsb25nLCAiXG4iKQogICAgb2JscWVjIDwtIDIzLjQzOSAtIDAuMDAwMDAwNCAqIHRpbWUKICAgIGNhdCgib2JscWVjID0iLCBvYmxxZWMsICJcbiIpCiAgICBlY2xvbmcgPC0gZWNsb25nICogZGVnMnJhZAogICAgY2F0KCJlY2xvbmcgPSIsIGVjbG9uZywgIlxuIikKICAgIG9ibHFlYyA8LSBvYmxxZWMgKiBkZWcycmFkCiAgICBjYXQoIm9ibHFlYyA9Iiwgb2JscWVjLCAiXG4iKQoKICAgICMgQ2VsZXN0aWFsIGNvb3JkaW5hdGVzCiAgICAjIFJpZ2h0IGFzY2Vuc2lvbiBhbmQgZGVjbGluYXRpb24KICAgIG51bSA8LSBjb3Mob2JscWVjKSAqIHNpbihlY2xvbmcpCiAgICBjYXQoIm51bSA9IiwgbnVtLCAiXG4iKQogICAgZGVuIDwtIGNvcyhlY2xvbmcpCiAgICBjYXQoImRlbiA9IiwgZGVuLCAiXG4iKQogICAgcmEgPC0gYXRhbihudW0gLyBkZW4pCiAgICBjYXQoInJhID0iLCByYSwgIlxuIikKICAgIHJhW2RlbiA8IDBdIDwtIHJhW2RlbiA8IDBdICsgcGkKICAgIGNhdCgicmFbIiwgZGVuIDwgMCwgIl0gPSIsIHJhW2RlbiA8IDBdLCAiXG4iKQogICAgcmFbZGVuID49IDAgJiBudW0gPCAwXSA8LSByYVtkZW4gPj0gMCAmIG51bSA8IDBdICsgdHdvcGkKICAgIGNhdCgicmFbIiwgZGVuID49IDAgJiBudW0gPCAwLCAiXSA9IiwgcmFbZGVuID49IDAgJiBudW0gPCAwXSwgIlxuIikKICAgIGNhdCgicmEgPSIsIHJhLCAiXG4iKQogICAgZGVjIDwtIGFzaW4oc2luKG9ibHFlYykgKiBzaW4oZWNsb25nKSkKICAgIGNhdCgiZGVjID0iLCBkZWMsICJcbiIpCgogICAgIyBMb2NhbCBjb29yZGluYXRlcwogICAgIyBHcmVlbndpY2ggbWVhbiBzaWRlcmVhbCB0aW1lCiAgICBnbXN0IDwtIDYuNjk3Mzc1ICsgLjA2NTcwOTgyNDIgKiB0aW1lICsgaG91cgogICAgY2F0KCJnbXN0ID0iLCBnbXN0LCAiXG4iKQogICAgZ21zdCA8LSBnbXN0ICUlIDI0CiAgICBjYXQoImdtc3QgPSIsIGdtc3QsICJcbiIpCiAgICBjYXQoImdtc3RbIiwgZ21zdCA8IDAsICJdID0iLCBnbXN0W2dtc3QgPCAwXSArIDI0LiwgIlxuIikKICAgIGdtc3RbZ21zdCA8IDBdIDwtIGdtc3RbZ21zdCA8IDBdICsgMjQuCgogICAgIyBMb2NhbCBtZWFuIHNpZGVyZWFsIHRpbWUKICAgIGxtc3QgPC0gZ21zdCArIGxvbmcgLyAxNS4KICAgIGNhdCgibG1zdCA9IiwgbG1zdCwgIlxuIikKICAgIGxtc3QgPC0gbG1zdCAlJSAyNC4KICAgIGNhdCgibG1zdCA9IiwgbG1zdCwgIlxuIikKICAgIGNhdCgibG1zdFsiLCBsbXN0IDwgMCwgIl0gPSIsIGxtc3RbbG1zdCA8IDBdICsgMjQuLCAiXG4iKQogICAgbG1zdFtsbXN0IDwgMF0gPC0gbG1zdFtsbXN0IDwgMF0gKyAyNC4KICAgIGxtc3QgPC0gbG1zdCAqIDE1LiAqIGRlZzJyYWQKICAgIGNhdCgibG1zdCA9IiwgbG1zdCwgIlxuIikKCiAgICAjIEhvdXIgYW5nbGUKICAgIGhhIDwtIGxtc3QgLSByYQogICAgY2F0KCJoYSA9IiwgaGEsICJcbiIpCiAgICBjYXQoImhhWyIsIGhhIDwgLXBpLCAiXSA9IiwgaGFbaGEgPCAtcGldICsgdHdvcGksICJcbiIpCiAgICBoYVtoYSA8IC1waV0gPC0gaGFbaGEgPCAtcGldICsgdHdvcGkKICAgIGNhdCgiaGFbIiwgaGEgPiBwaSwgIl0gPSIsIGhhW2hhID4gcGldIC0gdHdvcGksICJcbiIpCiAgICBoYVtoYSA+IHBpXSA8LSBoYVtoYSA+IHBpXSAtIHR3b3BpCgogICAgIyBMYXRpdHVkZSB0byByYWRpYW5zCiAgICBsYXQgPC0gbGF0ICogZGVnMnJhZAogICAgY2F0KCJsYXQgPSIsIGxhdCwgIlxuIikKCiAgICAjIEF6aW11dGggYW5kIGVsZXZhdGlvbgogICAgZWwgPC0gYXNpbihzaW4oZGVjKSAqIHNpbihsYXQpICsgY29zKGRlYykgKiBjb3MobGF0KSAqIGNvcyhoYSkpCiAgICBjYXQoImVsID0iLCBlbCwgIlxuIikKICAgIGF6IDwtIGFzaW4oLWNvcyhkZWMpICogc2luKGhhKSAvIGNvcyhlbCkpCiAgICBjYXQoImF6ID0iLCBheiwgIlxuIikKCiAgICAjIEZvciBsb2dpYyBhbmQgbmFtZXMsIHNlZSBTcGVuY2VyLCBKLlcuIDE5ODkuIFNvbGFyIEVuZXJneS4gNDIoNCk6MzUzCiAgICBjb3NBelBvcyA8LSAoMCA8PSBzaW4oZGVjKSAtIHNpbihlbCkgKiBzaW4obGF0KSkKICAgIGNhdCgiY29zQXpQb3MgPSIsIGNvc0F6UG9zLCAiXG4iKQogICAgc2luQXpOZWcgPC0gKHNpbihheikgPCAwKQogICAgY2F0KCJzaW5Bek5lZyA9Iiwgc2luQXpOZWcsICJcbiIpCiAgICBheltjb3NBelBvcyAmIHNpbkF6TmVnXSA8LSBheltjb3NBelBvcyAmIHNpbkF6TmVnXSArIHR3b3BpCiAgICBjYXQoImF6WyIsIGNvc0F6UG9zICYgc2luQXpOZWcsICJdID0iLCBheltjb3NBelBvcyAmIHNpbkF6TmVnXSwgIlxuIikKICAgIGF6WyFjb3NBelBvc10gPC0gcGkgLSBhelshY29zQXpQb3NdCiAgICBjYXQoImF6WyIsICFjb3NBelBvcywgIl0gPSIsIGF6WyFjb3NBelBvc10sICJcbiIpCgogICAgZWwgPC0gZWwgLyBkZWcycmFkCiAgICBjYXQoImVsID0iLCBlbCwgIlxuIikKICAgIGF6IDwtIGF6IC8gZGVnMnJhZAogICAgY2F0KCJheiA9IiwgYXosICJcbiIpCiAgICBsYXQgPC0gbGF0IC8gZGVnMnJhZAogICAgY2F0KCJsYXQgPSIsIGxhdCwgIlxuIikKCiAgICByZXR1cm4obGlzdChlbGV2YXRpb249ZWwsIGF6aW11dGg9YXopKQp9CgpzdW5Qb3NpdGlvbigyMDEzLCA5LCAxLCAxMCwgMCwgMCwgLTQuNzc4NjcsIDExLjg2MzY0KQo=