92 use mpiutil,
only : ccpp_bcast
93 use machine,
only : kind_phys
101 character(40),
parameter :: &
102 & VTAGAST=
'NCEP-Radiation_astronomy v5.2 Jan 2013 '
106 real (kind=kind_phys) :: degrad
107 real (kind=kind_phys) :: tpi
108 real (kind=kind_phys) :: hpi
109 real (kind=kind_phys) :: pid12
110 real (kind=kind_phys),
parameter :: f12 = 12.0
111 real (kind=kind_phys),
parameter :: f3600 = 3600.0
112 real (kind=kind_phys),
parameter :: czlimt = 0.0001
116 real (kind=kind_phys),
public :: solc0
117 integer :: isolflg = 10
118 character(26) :: solar_fname =
' '
123 real (kind=kind_phys) :: sollag=0.0
125 real (kind=kind_phys) :: sindec=0.0
127 real (kind=kind_phys) :: cosdec=0.0
129 real (kind=kind_phys) :: anginc=0.0
131 real (kind=kind_phys) :: smon_sav(12)
134 integer :: iyr_sav =0
150 & ( mpicomm, mpirank, mpiroot, &
151 & isolar, solar_file, con_solr, con_solr_old, con_pi )
186 type(mpi_comm),
intent(in) :: mpicomm
187 integer,
intent(in) :: mpirank, mpiroot
188 integer,
intent(in) :: isolar
189 character(len=26),
intent(in) :: solar_file
190 real(kind=kind_phys),
intent(in) :: con_solr, con_solr_old, con_pi
194 logical :: file_exist
200 if (mpirank==mpiroot) print *, vtagast
202 degrad = 180.0/con_pi
210 solar_fname = solar_file
214 smon_sav(imonth) = con_solr
217 if ( isolar == 0 )
then
219 if (mpirank==mpiroot)
then
220 print *,
' - Using old fixed solar constant =', solc0
222 elseif ( isolar == 10 )
then
223 if (mpirank==mpiroot)
then
224 print *,
' - Using new fixed solar constant =', solc0
226 elseif ( isolar == 1 )
then
227 solar_fname(15:26) =
'noaa_a0.txt'
229 if (mpirank==mpiroot)
then
230 print *,
' - Using NOAA annual mean TSI table in ABS scale', &
231 &
' with cycle approximation (old values)!'
234 if ( mpirank == mpiroot )
then
235 inquire (file=solar_fname, exist=file_exist)
237 call ccpp_bcast(file_exist, mpiroot, mpicomm, ierr)
238 if ( .not. file_exist )
then
241 if (mpirank==mpiroot)
then
242 print *,
' Requested solar data file "',solar_fname, &
244 print *,
' Using the default solar constant value =',solc0,&
245 &
' reset control flag isolflg=',isolflg
248 elseif ( isolar == 2 )
then
249 solar_fname(15:26) =
'noaa_an.txt'
251 if (mpirank==mpiroot)
then
252 print *,
' - Using NOAA annual mean TSI table in TIM scale', &
253 &
' with cycle approximation (new values)!'
256 if ( mpirank == mpiroot )
then
257 inquire (file=solar_fname, exist=file_exist)
259 call ccpp_bcast(file_exist, mpiroot, mpicomm, ierr)
260 if ( .not. file_exist )
then
263 if (mpirank==mpiroot)
then
264 print *,
' Requested solar data file "',solar_fname, &
266 print *,
' Using the default solar constant value =',solc0,&
267 &
' reset control flag isolflg=',isolflg
270 elseif ( isolar == 3 )
then
271 solar_fname(15:26) =
'cmip_an.txt'
273 if (mpirank==mpiroot)
then
274 print *,
' - Using CMIP5 annual mean TSI table in TIM scale', &
275 &
' with cycle approximation'
278 if ( mpirank == mpiroot )
then
279 inquire (file=solar_fname, exist=file_exist)
281 call ccpp_bcast(file_exist, mpiroot, mpicomm, ierr)
282 if ( .not. file_exist )
then
285 if (mpirank==mpiroot)
then
286 print *,
' Requested solar data file "',solar_fname, &
288 print *,
' Using the default solar constant value =',solc0,&
289 &
' reset control flag isolflg=',isolflg
292 elseif ( isolar == 4 )
then
293 solar_fname(15:26) =
'cmip_mn.txt'
295 if (mpirank==mpiroot)
then
296 print *,
' - Using CMIP5 monthly mean TSI table in TIM scale', &
297 &
' with cycle approximation'
300 if ( mpirank == mpiroot )
then
301 inquire (file=solar_fname, exist=file_exist)
303 call ccpp_bcast(file_exist, mpiroot, mpicomm, ierr)
304 if ( .not. file_exist )
then
307 if (mpirank==mpiroot)
then
308 print *,
' Requested solar data file "',solar_fname, &
310 print *,
' Using the default solar constant value =',solc0,&
311 &
' reset control flag isolflg=',isolflg
317 if (mpirank==mpiroot)
then
318 print *,
' - !!! ERROR in selection of solar constant data', &
319 &
' source, ISOL =',isolar
320 print *,
' Using the default solar constant value =',solc0, &
321 &
' reset control flag isolflg=',isolflg
346 & ( jdate,kyear,deltsw,deltim,lsol_chg, &
347 & mpicomm,mpirank,mpiroot, &
348 & slag, sdec, cdec, solcon, con_pi, errmsg, errflg &
402 integer,
intent(in) :: jdate(:), kyear
403 type(mpi_comm),
intent(in) :: mpicomm
404 integer,
intent(in) :: mpirank, mpiroot
405 logical,
intent(in) :: lsol_chg
407 real (kind=kind_phys),
intent(in) :: deltsw, deltim, con_pi
410 real (kind=kind_phys),
intent(out) :: slag, sdec, cdec, solcon
411 character(len=*),
intent(out) :: errmsg
412 integer,
intent(out) :: errflg
415 real (kind=kind_phys),
parameter :: hrday = 1.0/24.0
416 real (kind=kind_phys),
parameter :: minday= 1.0/1440.0
417 real (kind=kind_phys),
parameter :: secday= 1.0/86400.0
419 real (kind=kind_phys) :: smean, solc1, dtswh, smon(12)
420 real (kind=kind_phys) :: fjd, fjd1, dlt, r1, alp
422 integer :: jd, jd1, iyear, imon, iday, ihr, imin, isec
424 integer :: i, iyr, iyr1, iyr2, jyr, nn, nswr, icy1, icy2, icy
426 logical :: file_exist
427 character :: cline*60
446 if ( iyr_sav == iyear )
then
447 if ( isolflg==4 )
then
448 solc0 = smon_sav(imon)
453 if (mpirank == mpiroot)
then
455 inquire (file=solar_fname, exist=file_exist)
456 if ( .not. file_exist )
then
457 print *,
' !!! ERROR! Can not find solar constant file!!!'
459 errmsg =
"ERROR(radiation_astronomy): solar constant file"&
466 open (niradsf,file=solar_fname,form=
'formatted', &
470 read (niradsf, * ) iyr1,iyr2,icy1,icy2,smean,cline(1:60)
474 print *,
' Updating solar constant with cycle approx'
475 print *,
' Opened solar constant data file: ',solar_fname
483 call ccpp_bcast(iyr1, mpiroot, mpicomm, ierr)
484 call ccpp_bcast(iyr2, mpiroot, mpicomm, ierr)
485 call ccpp_bcast(icy1, mpiroot, mpicomm, ierr)
486 call ccpp_bcast(icy2, mpiroot, mpicomm, ierr)
487 call ccpp_bcast(smean, mpiroot, mpicomm, ierr)
524 if ( iyr < iyr1 )
then
525 icy = icy1 - iyr1 + 1
526 lab_dowhile1 :
do while ( iyr < iyr1 )
530 if ( mpirank == mpiroot )
then
531 print *,
' *** Year',iyear,
' out of table range!', &
533 print *,
' Using the closest-cycle year (',iyr,
')'
535 elseif ( iyr > iyr2 )
then
536 icy = iyr2 - icy2 + 1
537 lab_dowhile2 :
do while ( iyr > iyr2 )
541 if ( mpirank == mpiroot )
then
542 print *,
' *** Year',iyear,
' out of table range!', &
544 print *,
' Using the closest-cycle year (',iyr,
')'
550 if ( isolflg < 4 )
then
552 lab_dowhile3 :
do while ( i >= iyr1 )
555 if (mpirank == mpiroot)
then
556 read (niradsf,*) jyr, solc1
558 call ccpp_bcast(jyr, mpiroot, mpicomm, ierr)
559 call ccpp_bcast(solc1, mpiroot, mpicomm, ierr)
561 if ( i == iyr .and. iyr == jyr )
then
562 solc0 = smean + solc1
564 if (mpirank == mpiroot)
then
565 print *,
' CHECK: Solar constant data used for year',&
574 elseif ( isolflg == 4 )
then
576 lab_dowhile4 :
do while ( i >= iyr1 )
579 if (mpirank == mpiroot)
then
580 read (niradsf,*) jyr, smon(1:12)
582 call ccpp_bcast(jyr, mpiroot, mpicomm, ierr)
583 call ccpp_bcast(smon, mpiroot, mpicomm, ierr)
585 if ( i == iyr .and. iyr == jyr )
then
587 smon_sav(nn) = smean + smon(nn)
589 solc0 = smean + smon(imon)
591 if (mpirank == mpiroot)
then
592 print *,
' CHECK: Solar constant data used for year',&
593 & iyr,
' and month',imon
603 if (mpirank==mpiroot)
close ( niradsf )
610 jd1 = iw3jdn(iyear,imon,iday)
617 fjd1= 0.5 + float(ihr)*hrday + float(imin)*minday &
618 & + float(isec)*secday
620 fjd1= float(ihr - 12)*hrday + float(imin)*minday &
621 & + float(isec)*secday
632 & ( jd, fjd, con_pi, &
638 solcon = solc0 / (r1*r1)
646 if (mpirank == mpiroot)
then
651 & ( jd, fjd, dlt, alp, r1, solcon )
658 nswr = max(1, nint(deltsw/deltim))
659 dtswh = deltsw / f3600
672 anginc = pid12 * dtswh / float(nstp)
674 if ( mpirank == mpiroot )
then
675 print *,
' for cosz calculations: nswr,deltim,deltsw,dtswh =', &
676 & nswr,deltim,deltsw,dtswh,
' anginc,nstp =',anginc,nstp
695 & ( jd, fjd, con_pi, &
727 real (kind=kind_phys),
intent(in) :: fjd, con_pi
728 integer,
intent(in) :: jd
731 real (kind=kind_phys),
intent(out) :: r1, dlt, alp
734 real (kind=kind_phys),
parameter :: cyear = 365.25
735 real (kind=kind_phys),
parameter :: ccr = 1.3e-6
736 real (kind=kind_phys),
parameter :: tpp = 1.55
738 real (kind=kind_phys),
parameter :: svt6 = 78.035
740 integer,
parameter :: jdor = 2415020
743 real (kind=kind_phys) :: dat, t1, year, tyear, ec, angin, ador, &
744 & deleqn, sni, tini, er, qq, e1, ep, cd, eq, date, em, &
747 integer :: jdoe, iter
753 t1 = float(jd - jdor) / 36525.0
757 year = 0.25964134e0 + 0.304e-5 * t1
758 tyear= 0.24219879e0 - 0.614e-5 * t1
762 ec = 0.01675104e0 - (0.418e-4 + 0.126e-6 * t1) * t1
763 angin= 23.452294e0 - (0.0130125e0 + 0.164e-5 * t1) * t1
766 jdoe = ador + (svt6 * cyear) / (year - tyear)
770 deleqn= float(jdoe - jd) * (year - tyear) / cyear
772 sni = sin( angin / degrad )
773 tini = 1.0 / tan( angin / degrad )
774 er = sqrt( (1.0 + ec) / (1.0 - ec) )
775 qq = deleqn * tpi / year
783 lab_do_1 :
do while ( cd > ccr )
785 ep = e1 - (e1 - ec*sin(e1) - qq) / (1.0 - ec*cos(e1))
791 write(6,*)
' ITERATION COUNT FOR LOOP 32 =', iter
792 write(6,*)
' E, EP, CD =', e1, ep, cd
798 eq = 2.0 * atan( er * tan( 0.5*e1 ) )
802 dat = float(jd - jdor) - tpp + fjd
803 date = mod(dat, year)
807 em = tpi * date / year
812 lab_do_2 :
do while ( cr > ccr )
814 ep = e1 - (e1 - ec*sin(e1) - em) / (1.0 - ec*cos(e1))
820 write(6,*)
' ITERATION COUNT FOR LOOP 31 =', iter
826 w1 = 2.0 * atan( er * tan( 0.5*e1 ) )
828 r1 = 1.0 - ec*cos(e1)
830 sindec = sni * sin(w1 - eq)
831 cosdec = sqrt( 1.0 - sindec*sindec )
834 alp = asin( tan(dlt)*tini )
837 if (tst < 0.0) alp = con_pi - alp
838 if (alp < 0.0) alp = alp + tpi
840 sun = tpi * (date - deleqn) / year
841 if (sun < 0.0) sun = sun + tpi
842 sollag = sun - alp - 0.03255e0
863 & ( xlon,sinlat,coslat,solhr, im, me, &
900 integer,
intent(in) :: im, me
902 real (kind=kind_phys),
intent(in) :: sinlat(:), coslat(:), &
906 real (kind=kind_phys),
intent(out) :: coszen(:), coszdg(:)
909 real (kind=kind_phys) :: coszn, cns, solang, rstp
911 integer :: istsun(im), i, it, j, lat
915 solang = pid12 * (solhr - f12)
916 rstp = 1.0 / float(nstp)
924 cns = solang + (float(it)-0.5)*anginc + sollag
926 coszn = sindec * sinlat(i) + cosdec * coslat(i) &
928 coszen(i) = coszen(i) + max(0.0, coszn)
929 if (coszn > czlimt) istsun(i) = istsun(i) + 1
936 coszdg(i) = coszen(i) * rstp
937 if (istsun(i) > 0 .and. coszen(i) /= 0.0_kind_phys)
then
938 coszen(i) = coszen(i) / istsun(i)
957 & ( jd, fjd, dlt, alp, r1, solc &
986 integer,
intent(in) :: jd
988 real (kind=kind_phys),
intent(in) :: fjd, dlt, alp, r1, solc
993 real (kind=kind_phys),
parameter :: sixty = 60.0
995 character(LEN=1),
parameter :: sign =
'-'
996 character(LEN=1),
parameter :: sigb =
' '
998 character(LEN=1) :: dsig
999 character(LEN=4) :: month(12)
1001 data month /
'JAN.',
'FEB.',
'MAR.',
'APR.',
'MAY ',
'JUNE', &
1002 &
'JULY',
'AUG.',
'SEP.',
'OCT.',
'NOV ',
'DEC.' /
1004 integer :: iday, imon, iyear, ihr, ltd, ltm, &
1005 & ihalp, iyy, jda, mfjd, idaywk, idayyr
1006 real (kind=kind_phys) :: xmin, dltd, dltm, dlts, halp, ymin, &
1013 if (fjd >= 0.5)
then
1015 mfjd= nint( fjd*1440.0 )
1016 ihr = mfjd / 60 - 12
1017 xmin= float(mfjd) - (ihr + 12)*sixty
1020 mfjd= nint( fjd*1440.0 )
1021 ihr = mfjd / 60 + 12
1022 xmin= float(mfjd) - (ihr - 12)*sixty
1027 call w3fs26(jda, iyear,imon,iday, idaywk,idayyr)
1033 dltm = sixty * (abs(dltd) - abs(float(ltd)))
1035 dlts = sixty * (dltm - float(ltm))
1037 if ((dltd < 0.0) .and. (ltd == 0.0))
then
1043 halp = 6.0 * alp / hpi
1045 ymin = abs(halp - float(ihalp)) * sixty
1047 asec = (ymin - float(iyy)) * sixty
1049 eqt = 228.55735 * sollag
1052 print 101, iday, month(imon), iyear, ihr, xmin, jd, fjd
1053 101
format(
'0 FORECAST DATE',9x,i3,a5,i6,
' AT',i3,
' HRS',f6.2,
' MINS'/&
1054 &
' JULIAN DAY',12x,i8,2x,
'PLUS',f11.6)
1056 print 102, r1, halp, ihalp, iyy, asec
1057 102
format(
' RADIUS VECTOR',9x,f10.7/
' RIGHT ASCENSION OF SUN', &
1058 & f12.7,
' HRS, OR',i4,
' HRS',i4,
' MINS',f6.1,
' SECS')
1060 print 103, dltd, dsig, ltd, ltm, dlts, eqt, eqsec, sollag, solc
1061 103
format(
' DECLINATION OF THE SUN',f12.7,
' DEGS, OR ',a1,i3, &
1062 &
' DEGS',i4,
' MINS',f6.1,
' SECS'/
' EQUATION OF TIME',6x, &
1063 & f12.7,
' MINS, OR',f10.2,
' SECS, OR',f9.6,
' RADIANS'/ &
1064 &
' SOLAR CONSTANT',8x,f12.7,
' (DISTANCE AJUSTED)'//)
1068 end subroutine prtime
subroutine, public sol_init(mpicomm, mpirank, mpiroot, isolar, solar_file, con_solr, con_solr_old, con_pi)
This subroutine initializes astronomy process, and set up module constants.
subroutine, public sol_update(jdate, kyear, deltsw, deltim, lsol_chg, mpicomm, mpirank, mpiroot, slag, sdec, cdec, solcon, con_pi, errmsg, errflg)
This subroutine computes solar parameters at forecast time.
subroutine, public coszmn(xlon, sinlat, coslat, solhr, im, me, coszen, coszdg)
This subroutine computes mean cos solar zenith angle over SW calling interval.
this module defines fortran unit numbers for input/output data files for the ncep gfs model.
This module sets up astronomy quantities for solar radiation calculations.