File: astrosphere.f95

package info (click to toggle)
munipack 0.6.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 33,104 kB
  • sloc: cpp: 29,677; sh: 4,909; f90: 2,872; makefile: 278; python: 140; xml: 72; awk: 12
file content (274 lines) | stat: -rw-r--r-- 5,808 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
!
!  Spherical astronomy module
!
!  Copyright © 1996 - 2013, 2015-8 F.Hroch (hroch@physics.muni.cz)
!
!  This file is part of Munipack.
!
!  Munipack is free software: you can redistribute it and/or modify
!  it under the terms of the GNU General Public License as published by
!  the Free Software Foundation, either version 3 of the License, or
!  (at your option) any later version.
!
!  Munipack is distributed in the hope that it will be useful,
!  but WITHOUT ANY WARRANTY; without even the implied warranty of
!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
!  GNU General Public License for more details.
!
!  You should have received a copy of the GNU General Public License
!  along with Munipack.  If not, see <http://www.gnu.org/licenses/>.



module astrosphere


  implicit none

  integer, parameter, private :: db = selected_real_kind(15)
  real(db), parameter, private :: rad =  57.29577951308232286464772_db

contains

  function gmst(jd)

    real(db) :: gmst
    real(db), intent(in) :: jd


!  Greenwich sidereal time in hours
!
!  jd is a full Julian date
!
!  The precision is better than 1 second.
!  According to Astronomical Almanac 2000.


    real(db) :: tu,t

    tu = (jd - 2451545.0_db)/36525.0_db
    t = 24110.54841_db + tu*(8640184.812866_db + tu*(0.093104_db-6.2e-6_db*tu))
    gmst = mod(t/3600.0_db + 24.0_db*(jd - aint(jd)) + 12.0_db,24.0_db)

  end function gmst


  function lmst(jd,longitude)

    real(db) :: lmst
    real(db), intent(in) :: jd, longitude


!  local sidereal time in hours
!
!  jd is a full Julian date
!  lambda is a longitude in degrees: -west ... +east
!
!  The precision is better than 1 second.
!  According to Astronomical Almanac 2000.

    lmst = mod(gmst(jd) + longitude/15.0_db,24.0_db)

  end function lmst



  function hangle(lmst,ra)

!   hour angle in degrees

    real(db) :: hangle
    real(db), intent(in) :: lmst, ra

    hangle = mod(lmst - ra,360.0_db)

  end function hangle


  subroutine eq2hor(ha, dec, latitude, az, elev)

    real(db), intent(in) :: ha,dec,latitude
    real(db), intent(out) :: az, elev


!
! equatorial to horizontal coordinates
!
!  all arguments in degrees
!

    real(db) :: sinh, cosh, sind, cosd, sinl, cosl, x,y,z,r

    sinh = sin(ha/RAD)
    cosh = cos(ha/RAD)
    sind = sin(dec/RAD)
    cosd = cos(dec/RAD)
    sinl = sin(latitude/RAD)
    cosl = cos(latitude/RAD)

    x = -cosh*cosd*sinl + sind*cosl
    y = -sinh*cosd
    z = cosh*cosd*cosl + sind*sinl

    r = sqrt(x**2 + y**2)
    if( abs(r) > epsilon(r) )then
       az = RAD*atan2(y,x)
    else
       az = 0.0_db
    end if
    if( az < 0_db ) az = az + 360.0_db
    elev = RAD*atan2(z,r)

  end subroutine eq2hor


  subroutine hor2eq(az, elev, latitude, ha,dec)

    real(db), intent(in) :: az,elev,latitude
    real(db), intent(out) :: ha, dec

!
!  horizontal to equatorial coordinates
!
!  all arguments in degrees
!

    real(db) :: sina, cosa, sine, cose, sinl, cosl, x, y, z, r

    sina = sin(az/RAD)
    cosa = cos(az/RAD)
    sine = sin(elev/RAD)
    cose = cos(elev/RAD)
    sinl = sin(latitude/RAD)
    cosl = cos(latitude/RAD)

    x = -cosa*cose*sinl + sine*cosl
    y = -sina*cose
    z = cosa*cose*cosl + sine*sinl

    r = sqrt(x**2 + y**2)
    if( abs(r) > epsilon(r) )then
       ha = RAD*atan2(y,x)
    else
       ha = 0.0_db
    endif
    dec = RAD*atan2(z,r)

  end subroutine hor2eq


  function refract(z)

    real(db) :: refract
    real(db), intent(in) :: z

!
!     compute refraction angle in degrees
!
!    Smart: Textbook on spherical astronomy
!
!    constants for pressure 760mmHg, 10deg C with
!    suffucient accuracy for z < 75 deg
!

    real(db) :: tanz

    tanz = tan(z/RAD)
    refract = (58.16_db*tanz - 0.067_db*tanz*tanz*tanz)/3600.0_db

  end function refract


  function airmass(z)

    real(db) :: airmass
    real(db), intent(in) :: z

    !
    !     compute airmass,
    !
    !      young&irvine: aj,72,945,(1967)
    !
    ! the airmass is limited on the given range of zenit distances

    real(db) :: secz

    if( 0 <= z .and. z < 86.5 ) then
       secz = 1.0_db/cos(z/RAD)
       airmass = secz*(1.0_db - 1.2e-3_db*(secz**2 - 1.0_db))
    else
       airmass = -1
    end if

  end function airmass

  function xairmass(jd,long,lat,ra,dec)

    real(db) :: xairmass
    real(db), intent(in) :: jd,long,lat,ra,dec
    real(db) :: t,h,ha,a

    t = lmst(jd,long)
    ha = hangle(15.0_db*t,ra)
    call eq2hor(ha,dec,lat,a,h)
    xairmass = airmass(90.0_db - h)

  end function xairmass


!  function longsun(jd,y)
  function longsun(d)

!    use trajd

!    real(db), intent(in) :: jd,y
    real(db), intent(in) :: d   ! days since 1. january
    real(db) :: longsun

   !  approx (!!!!) of length of the Sun
    longsun = mod(279.465 + 0.985647*d,360.0_db)
!    longsun = 279.465 + 0.985647*(jd - datjd(y,1.0_db,1.0_db))

  end function longsun


  function helcor(alpha,delta,ls)

    real(db), intent(in) ::  alpha,delta,ls
    real(db) ::  helcor

    ! heliocentric correction in days, angles in degrees

    helcor = 0.9174077_db*sin(alpha/rad)*cos(delta/rad) + &
         0.3979486_db*sin(delta/rad)
    helcor = helcor*sin(ls/rad) + cos(ls/rad)*cos(alpha/rad)*cos(delta/rad)
    helcor = -0.0057755_db*helcor

  end function helcor

  function phase(jd,min0,per)

    real(db), intent(in) ::  jd,min0,per
    real(db) ::  phase

    phase = mod(jd - min0,per) / per

    ! Phase is negative for jd < min0.

  end function phase

  subroutine propercoo(jd0,jd,a,d,pma,pmd,alpha,delta)

    real(db), intent(in) :: jd0,jd
    real(db), intent(in) :: a,d,pma,pmd
    real(db), intent(out) :: alpha,delta
    real(db) :: dt

    dt = (jd - jd0)/365.25_db
    alpha = a + dt*pma
    delta = d + dt*pmd

  end subroutine propercoo


end module astrosphere