prism_calendar.F90

Go to the documentation of this file.
00001 !
00002 ! --------------------  PRISM module file calendar.f90 ------------------
00003 !
00004 ! $Id
00005 
00006 Module PRISM_calendar
00007   !-----------------------------------------------------------------------
00008   ! Proleptic Gregorian Calendar routines:
00009   !
00010   ! Copyright 2007-2010, Max-Planck-Institute for Meteorology, Hamburg, Germany.
00011 ! All rights reserved. Use is subject to OASIS4 license terms.
00012   !
00013   !
00014   ! PSMILe_* routines:
00015   !
00016   ! Copyright 2007-2010, CERFACS, Toulouse, France.
00017   ! Copyright 2007-2010, SGI Germany, Munich, Germany.
00018   ! Copyright 2007-2010, NEC Europe Ltd., London, UK.
00019 ! All rights reserved. Use is subject to OASIS4 license terms.
00020   !-----------------------------------------------------------------------
00021   !+
00022   !
00023   ! mo_time_base [module]
00024   !    routines to handle Julian dates and times
00025   !
00026   ! Version:    E5/R1.07+  04-February-2003
00027   !
00028   ! Authors:
00029   !   L. Kornblueh, MPI                prepared basic version
00030   !   I. Kirchner,  MPI July 2000      large revision
00031   !   L. Kornblueh, MPI August 2000    adapting for right real kind (dp)
00032   !                                    and other minor corrections, removed
00033   !                                    30 day support, removed print overload.
00034   !   L. Kornblueh, MPI February 2003  adaption to PRISM calendar
00035   !                                    dates before the change to the gregorian
00036   !                                    calendar are treated as gregorian as 
00037   !                                    well to have a consitent view on the 
00038   !                                    seasons in climte sense - introduce
00039   !                                    preprocessor flag IAU for the original
00040   !                                    code (IAU - International Astrophysical
00041   !                                    Union).
00042   !   I. Kirchner,  FUB February 2003  code review
00043   !
00044   !   R. Redler, NEC-CCRLE, 2003       adaptation to OASIS4 software
00045   !
00046   !   R. Redler, NEC-CCRLE, Aug 2004   simple calendars with 360 days per year
00047   !                                    and 365 days per year added. Julian days
00048   !                                    calulated by theses calendars are not
00049   !                                    compatible with those calculated by the
00050   !                                    proleptic gregorian one.
00051   !                                    The new calendars need to be revised.
00052   !
00053   !-
00054 #undef IAU
00055 !!!#define IAU
00056   !
00057   ! References:
00058   !
00059   ! Montenbruck, Oliver, "Practical Ephmeris Calculations", Ch. 2, pp 33-40.
00060   ! The 1992 Astronomical Almanac, page B4.
00061   !
00062   ! The Julian Date is defined as the the number of days which have elapsed
00063   ! since the 1st of January of the year 4713 BC 12:00 Universal Time.
00064   !
00065   ! Up to 4th October 1582 AD the Julian Calendar was in force with leap
00066   ! years every four years, but from then on the Gregorian Calendar carried 
00067   ! on from 15th October 1582 with the leap years defined by the rule:
00068   !
00069   ! Leap year is every year whose yearly number is divisible by four, but
00070   ! not by a hundred, or is divisible by four hundred.
00071   !
00072   ! At midday on 4th October 1582 2299160.5 Julian days had elapsed.
00073   ! The Gregorian Calendar then carried on at this point from 15th October
00074   ! 1582, so its beginning occured on the Julian date 2299160.5.
00075   ! 
00076   ! Note: the astronomical year -4712 corresponds to the year 4713 BC, the
00077   !       year 0 to the year 1 BC; thereafter the astronomical year match
00078   !       the year AD, e.g. year 1 = year 1 AD.
00079   !
00080   !       This routines work for the years -5877402 BC until 5868098 AD.  
00081   !       However, there are not covered dates by the current GRIB edition 1, 
00082   !       which can handle dates between 1 AD and 25599 AD.
00083   !
00084   !       The "Modified Julian Date" is the Julian Date - 2400000.5 and so 
00085   !       has a zero point of 17th November 1858 AD 00:00 Universal Time.
00086   ! 
00087   !       Due to the small time span coverable by the GRIB output there is 
00088   !       no need to use a "Modified Julian Date".
00089   !
00090   ! The Julian day number is stored as two doubles to guarantee sufficient
00091   ! precision on all machines. The complete value is (day+fraction)
00092   ! although this addition will sometimes lose precision. Note that day
00093   ! might not be an integer value and fraction might be greater than one.
00094   !
00095   !----------------------------------------------------------------------
00096   USE PRISM_Constants
00097   USE PSMILe
00098  
00099   IMPLICIT NONE
00100   !
00101   ! WORKAROUND:
00102   ! We assume that SELECTED_REAL_KIND(12,307) corresponds
00103   ! to double precision on all systems.
00104   !
00105   INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(12,307)
00106 
00107   LOGICAL, PARAMETER :: eq_months = .false.
00108   LOGICAL, PARAMETER :: eq_years  = .false.
00109 
00110   PRIVATE
00111 
00112   !----------------------------------------------------------------------
00113   ! Subroutines/Functions
00114   !
00115   ! Note: negative years are valid
00116   !
00117   PUBLIC  :: PSMILe_date2ju     ! convert PRISM_Time_Struct into Julian day
00118   PUBLIC  :: PSMILe_ju2date     ! convert Julian day into PRISM_Time_Struct
00119   PUBLIC  :: PSMILe_addtime     ! adds time
00120   PUBLIC  :: PSMILe_subtime     ! subtracts time
00121   !
00122   PRIVATE :: Set_JulianDay      ! convert calendar date/time into Julian day
00123   PRIVATE :: Set_JulianCalendar ! convert Julian day into calendar date/time
00124   PRIVATE :: Get_JulianYearDay  ! select the day number of the year
00125   PRIVATE :: Get_JulianYearLen  ! get the length of the year
00126   PRIVATE :: Get_JulianMonLen   ! get the length of the months
00127   PRIVATE :: Print_JulianDay    ! print out the date information
00128   PRIVATE :: sec2frac, frac2sec ! convert sec to fraction and vice versa
00129 
00130   !----------------------------------------------------------------------
00131   ! Structure declarations, variables
00132   !
00133   TYPE, PRIVATE :: julian_date
00134     !+
00135     !
00136     ! julian_date [structure]
00137     !     day      [real_dp]  (day in calendar)
00138     !     fraction [real_dp]  (fraction of the day)
00139     !
00140     !-
00141     Double Precision :: day       ! day since 1. January 4713 BC, 12UTC
00142     Double Precision :: fraction  ! fraction of day
00143   END TYPE julian_date
00144 
00145   !+
00146   !
00147   ! idaylen [integer, constant]
00148   !    length of a day in seconds
00149   !
00150   !-
00151   INTEGER, PRIVATE, PARAMETER :: IDAYLEN = 86400
00152 
00153 CONTAINS
00154   !
00155   !----------------------------------------------------------------------
00156   !
00157   subroutine psmile_addtime ( date_in, date_inc, date_out )
00158     !+
00159     !
00160     ! PSMILe_addtime [subroutine]
00161     ! Adds time to a given date/time in julian days and seconds per day
00162     ! 1st array element keeps the days, the 2nd keeps the seconds
00163     !    (
00164     !    date_in      [double]  input (input date/time)
00165     !    date_inc     [double]  input (increment date/time)
00166     !    date_out     [double]  output (resulting date/time)
00167     !    )
00168     !
00169     !-
00170     !
00171     IMPLICIT NONE
00172     !
00173     Double Precision, INTENT(In)  :: date_in(2)
00174     Double Precision, INTENT(In)  :: date_inc(2)
00175     Double Precision, INTENT(Out) :: date_out(2)
00176     !
00177     INTEGER               :: days
00178     !
00179     days = date_inc(2)/86400.0_dp
00180     date_out(1) = date_in(1)+date_inc(1)+days
00181     date_out(2) = date_in(2)+date_inc(2)-(days*86400.0_dp)
00182 
00183   END SUBROUTINE PSMILe_addtime
00184 
00185   subroutine psmile_subtime ( date_in, date_inc, date_out )
00186     !+
00187     !
00188     ! PSMILe_subtime [subroutine]
00189     ! Subtracts time from a given date/time in julian days and seconds per day
00190     ! 1st array element keeps the days, the 2nd keeps the seconds
00191     !    (
00192     !    date_in      [double]  input (input date/time)
00193     !    date_inc     [double]  input (increment date/time)
00194     !    date_out     [double]  output (resulting date/time)
00195     !    )
00196     !
00197     !-
00198     !
00199     IMPLICIT NONE
00200     !
00201     Double Precision, INTENT(In)  :: date_in(2)
00202     Double Precision, INTENT(In)  :: date_inc(2)
00203     Double Precision, INTENT(Out) :: date_out(2)
00204     !
00205     INTEGER               :: days
00206     !
00207     days = date_inc(2)/86400.0_dp
00208     date_out(1) = date_in(1)-date_inc(1)-days
00209     date_out(2) = date_in(2)-date_inc(2)+(days*86400.0_dp)
00210 
00211   END SUBROUTINE PSMILe_subtime
00212 
00213   subroutine psmile_date2ju ( date, julian_day, julian_seconds )
00214     !+
00215     !
00216     ! PSMILe_date2ju [subroutine]
00217     !    convert PRISM time struct into Julian calendar day and seconds
00218     !    (
00219     !    date           [type]    input (PRISM date/time)
00220     !    julian_day     [double]  output (julian day)
00221     !    julian_seconds [double]  output (seconds of the julian day)
00222     !    )
00223     !
00224     !-
00225     !
00226     IMPLICIT NONE
00227     !
00228     !     INPUT
00229     !
00230     TYPE (PRISM_Time_Struct), INTENT(In) :: date
00231     !
00232     !     OUTPUT
00233     !
00234     REAL (PSMILe_float_kind), INTENT(Out) :: julian_day
00235     REAL (PSMILe_float_kind), INTENT(Out) :: julian_seconds
00236     !
00237     !     LOCAL
00238     !
00239     TYPE (julian_date) :: my_day
00240 
00241     julian_seconds = real( (date%hour*60.0 + date%minute) * 60.0, dp ) + date%second
00242 
00243 #ifdef DEBUGX
00244     print *, trim(ch_id), ': PSMILe_date2ju: ', date%year, date%month, date%day
00245     print *, trim(ch_id), ': PSMILe_date2ju: ', date%hour, date%minute, date%second
00246 #endif
00247 
00248     CALL Set_JulianDay ( date%year, date%month, date%day, julian_seconds, my_day )
00249     !
00250     ! Shift seconds since Julian days start at noon
00251     ! For reference: 1. January 1998 00 UTC === Julian Day 2450814, Julian Sec 43200
00252     !
00253     if ( julian_seconds >= 43200.0_dp ) then
00254          julian_seconds = julian_seconds - 43200.0_dp
00255     else
00256          julian_seconds = julian_seconds + 43200.0_dp
00257     endif
00258 
00259     julian_day = my_day%day
00260 
00261 #ifdef DEBUGX
00262     print *, trim(ch_id), ': PSMILe_date2ju: ', julian_day, julian_seconds
00263 #endif
00264 
00265   END SUBROUTINE PSMILe_date2ju
00266   !
00267   !----------------------------------------------------------------------
00268   !
00269   subroutine psmile_ju2date ( date, julian_day, julian_seconds )
00270     !+
00271     !
00272     ! PSMILe_ju2date [subroutine]
00273     !    convert Julian calendar day and seconds into PRISM time struct
00274     !    (
00275     !    date           [type]    output (PRISM date/time)
00276     !    julian_day     [double]  input (julian day)
00277     !    julian_seconds [double]  input (seconds of the julian day)
00278     !    )
00279     !
00280     !-
00281     !
00282     IMPLICIT NONE
00283     !
00284     !     INPUT
00285     !
00286     REAL (PSMILe_float_kind), INTENT(In) :: julian_day
00287     REAL (PSMILe_float_kind), INTENT(In) :: julian_seconds
00288     !
00289     !     OUTPUT
00290     !
00291     TYPE (PRISM_Time_Struct), INTENT(Out) :: date
00292     !
00293     !     LOCAL
00294     !
00295     TYPE (julian_date) :: my_day
00296     Double Precision           :: sec
00297 
00298     my_day%day      = julian_day
00299     my_day%fraction = sec2frac(julian_seconds)
00300 
00301     CALL Set_JulianCalendar(my_day, date%year, date%month, date%day, sec)
00302     !
00303     ! Seconds are returned but are ignored here since they are truncated
00304     !
00305     sec = julian_seconds
00306     if ( sec < 43200.0_dp ) then
00307          sec = sec + 43200.0_dp
00308     else
00309          sec = sec - 43200.0_dp
00310     endif
00311 
00312     date%hour   = INT(sec/REAL(3600,dp))
00313     date%minute = INT((sec-date%hour*REAL(3600,dp))/REAL(60,dp) )
00314     date%second = sec-date%hour*REAL(3600,dp)-date%minute*REAL(60,dp)
00315 #ifdef DEBUGX
00316     print *, trim(ch_id), ': PSMILe_ju2date: ', my_day%day, my_day%fraction
00317     print *, trim(ch_id), ': PSMILe_ju2date: ', date%year, date%month, date%day
00318     print *, trim(ch_id), ': PSMILe_ju2date: ', date%hour, date%minute, date%second
00319 #endif
00320   END SUBROUTINE PSMILe_ju2date
00321   !
00322   !----------------------------------------------------------------------
00323   !
00324   SUBROUTINE Set_JulianDay(ky, km, kd, sec, my_day)
00325     !+
00326     !
00327     ! Set_JulianDay  [subroutine]
00328     !    convert year, month, day, seconds into Julian calendar day
00329     !    (
00330     !    year   [integer] input (calendar year)
00331     !    month  [integer] input (month of the year)
00332     !    day    [integer] input (day of the month)
00333     !    second [dble]    input (seconds of the day)
00334     !    date   [julian_date] output (Julian day)
00335     !    )
00336     !
00337     !-
00338     !
00339     INTEGER, INTENT(IN)  :: ky
00340     INTEGER, INTENT(IN)  :: km
00341     INTEGER, INTENT(IN)  :: kd
00342     Double Precision, INTENT(IN) :: sec
00343     !
00344     ! for reference: 1. January 1998 00 UTC === Julian Day 2450814.5
00345     !
00346     TYPE (julian_date), INTENT(out) :: my_day
00347 
00348     INTEGER :: ib, iy, im, idmax
00349     Double Precision :: zd, zsec
00350 
00351     Double Precision :: yr_len
00352     Double Precision :: mon_len
00353 
00354     Double Precision :: mon_lens(12)
00355 
00356     DATA mon_lens / 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 /
00357 
00358     IF ( sec < 0 .OR. sec > 86400.0 ) THEN
00359       WRITE(*,*) 'mo_time_base: Set_JulianDay', ' invalid number of seconds', sec
00360       call psmile_abort
00361     ENDIF
00362     zsec = sec2frac(sec)
00363 
00364     IF ( eq_years .and. eq_months ) THEN
00365           mon_len = 30.0000_dp
00366           yr_len  = 360.0000_dp
00367           iy = ky
00368           im = km
00369     ELSE IF ( eq_years .and. .not. eq_months ) THEN
00370           yr_len  = 365.00_dp
00371           iy = ky
00372           im = km
00373     ELSE
00374        IF (km <= 2) THEN
00375           iy = ky-1
00376           im = km+12
00377        ELSE 
00378           iy = ky
00379           im = km
00380        ENDIF
00381        mon_len = 30.6001_dp
00382        yr_len  = 365.25_dp
00383     ENDIF
00384 
00385     ib = INT(iy/400)-INT(iy/100)
00386 
00387 #ifdef IAU
00388     IF (ky > 1582 .OR. (ky == 1582 .AND. km > 10 &
00389          .OR. (km == 10 .AND. kd >= 15))) THEN
00390       ! 15th October 1582 AD or later no changes
00391 
00392     ELSE IF (ky == 1582 .AND. km == 10 .AND. (4 < kd .AND. kd < 15) ) THEN
00393       ! a small pice from the history:
00394       !     Papst Gregor XIII corrected the calendar,
00395       !     he skipped 10 days between the 4th and the 15th of October 1582
00396       !
00397       WRITE (*, '(a29,a5,i2.2,a1,i2.2,a1,i4.4,a)') &
00398            'mpi-calendar: Set_JulianDay: '         &
00399            'date ', km, '/', kd, '/', ky, ' not valid'
00400       call psmile_abort
00401     ELSE 
00402 
00403       ! 4th October 1582 AD or earlier
00404       ib = -2
00405 
00406     ENDIF
00407 #endif
00408 
00409     ! check the length of the month
00410     idmax = Get_JulianMonLen (ky, km)
00411 
00412     IF (kd < 1 .OR. idmax < kd) then
00413       WRITE(*,'(a,a,i10,i10)') 'mo_time_base: Set_JulianDay' ,' day in months invalid', kd, idmax
00414       call psmile_abort
00415     ENDIF
00416 
00417     IF ( eq_years .and. eq_months ) THEN
00418 
00419        zd = FLOOR(yr_len*iy)+INT(mon_len*(im-1)) &
00420             +REAL(kd,dp)-1.0_dp+zsec
00421 
00422     ELSE IF ( eq_years .and. .not. eq_months ) THEN
00423 
00424        zd = FLOOR(yr_len*iy)+INT(mon_lens(im)) &
00425             +REAL(kd,dp)+zsec
00426 
00427     ELSE
00428 
00429        zd = FLOOR(yr_len*iy)+INT(mon_len*(im+1)) &
00430             +REAL(ib,dp)+1720996.5_dp+REAL(kd,dp)+zsec
00431 
00432     ENDIF
00433 
00434     my_day%day      = AINT(zd,dp)
00435     my_day%fraction = zd-AINT(zd,dp)
00436 
00437   END SUBROUTINE Set_JulianDay
00438 
00439   SUBROUTINE Set_JulianCalendar(my_day, ky, km, kd, sec)
00440     !+
00441     !
00442     ! Set_JulianCalendar [subroutine]
00443     !    convert Julian date into year, months, day, seconds of day
00444     !    (
00445     !    date   [julian_date]  input (Julian day)
00446     !    year   [integer] output (calendar year)
00447     !    month  [integer] output (month of the year)
00448     !    day    [integer] output (day of the month)
00449     !    second [dble]    output (seconds of the day)
00450     !    )
00451     !
00452     !-
00453     TYPE (julian_date), INTENT(IN) :: my_day
00454     INTEGER, INTENT(OUT)           :: ky
00455     INTEGER, INTENT(OUT)           :: km
00456     INTEGER, INTENT(OUT)           :: kd
00457     Double Precision, INTENT(OUT)          :: sec
00458     
00459     Double Precision :: za, zb, zc, zd, ze, zf, zday, zfrac, zsec
00460 
00461     Double Precision :: yr_len
00462     Double Precision :: mon_len
00463 
00464     zday  = my_day%day
00465     zfrac = my_day%fraction
00466 
00467     IF ( eq_years .and. eq_months ) THEN
00468 
00469        mon_len = 30.0000_dp
00470        yr_len  = 360.0000_dp
00471        if ( zfrac >= 0.5 ) zfrac = zfrac - 0.5_dp
00472        za = FLOOR(zday+zfrac+0.5_dp)
00473        ky = FLOOR(za/yr_len)
00474        zb = za - (ky*yr_len)
00475        km = FLOOR(zb/mon_len) + 1
00476        zc = zb - ((km-1)*mon_len)
00477        kd = zc + 1
00478        RETURN
00479 
00480     ELSE IF ( eq_years .and. .not. eq_months ) THEN
00481 
00482        yr_len  = 365.0000_dp
00483        if ( zfrac >= 0.5 ) zfrac = zfrac - 0.5_dp
00484        za = FLOOR(zday+zfrac+0.5_dp)
00485        ky = FLOOR(za/yr_len)
00486        zb = za - (ky*yr_len)
00487        CALL Get_MonDay ( zb, km, kd )
00488        RETURN
00489 
00490     ELSE
00491 
00492        mon_len = 30.6001_dp
00493        yr_len  = 365.25_dp
00494 
00495     ENDIF
00496 
00497     za = FLOOR(zday+zfrac+0.5_dp)
00498     zb = FLOOR((za-1867216.25_dp)/36524.25_dp)
00499     zc = za+zb-FLOOR(zb/4)+1525
00500 
00501 #ifdef IAU
00502     IF (za < 2299161.0_dp) zc = za+1524.0_dp
00503 #endif
00504 
00505     zd = FLOOR((zc-122.1_dp)/365.25_dp)
00506     ze = FLOOR(365.25_dp*zd)
00507     zf = FLOOR((zc-ze)/30.6001_dp)
00508 
00509     kd = INT(zc-ze- FLOOR(30.6001_dp*zf))
00510     km = INT(zf-1-12*FLOOR(zf/14))
00511     ky = INT(zd-4715-((7+km)/10))
00512 
00513     ! convert fraction in seconds of the day
00514     IF (zfrac < -0.5_dp) THEN
00515        zsec = 1.5_dp + zfrac
00516     ELSE IF (zfrac < 0.5_dp) THEN
00517        zsec = 0.5_dp + zfrac
00518     ELSE
00519        zsec = zfrac - 0.5_dp
00520     END IF
00521     sec = frac2sec(zsec)
00522 
00523   END SUBROUTINE Set_JulianCalendar
00524 
00525   SUBROUTINE Get_JulianYearDay(my_day, kjy, kd, sec)
00526     !+
00527     !
00528     ! Get_JulianYearDay [subroutine]
00529     !    get Julian year, day of year and seconds of day from Julian date
00530     !    (
00531     !    date   [julian_date]  input (Julian day)
00532     !    year   [integer] output (Julian calendar year)
00533     !    day    [integer] output (day of the year)
00534     !    second [dble]    output (seconds of the day)
00535     !    )
00536     !
00537     !-
00538     ! Day of Astronomical Year (approximated)
00539     !
00540     ! it is used for the correct annual cycle
00541     ! remember the mismatch between calendar and
00542     ! astronomical year accumulated until 1582
00543     !
00544     ! this version gives adjustment until 1583
00545     !
00546     TYPE (julian_date), INTENT(IN) :: my_day
00547     INTEGER, INTENT(OUT)           :: kjy
00548     INTEGER, INTENT(OUT)           :: kd
00549     Double Precision, INTENT(OUT)          :: sec
00550 
00551     TYPE (julian_date) :: first_jan, present_day
00552     INTEGER :: iy, id, im
00553 
00554     ! AD 1 is year 4713 in Julian calender, 31st of December 1997 the Julian 
00555     ! day 2450814.0 is elapsed at 12 UTC and the Julian year is 6711, so:
00556     ! year_len = 2450814. / 6710. = 365.25
00557 
00558     ! get the date of the present julian day
00559     CALL Set_JulianCalendar(my_day, iy, im, id, sec)
00560     
00561     ! find the first of January 00UTC
00562     CALL Set_JulianDay(iy,  1,  1, 0.0_dp, first_jan)
00563 
00564     ! find the present Julian Day at 00UTC
00565     CALL Set_JulianDay(iy, im, id, 0.0_dp, present_day)
00566 
00567     ! the day in the year is given
00568     kd = present_day%day-first_jan%day+1
00569 
00570     ! get the Julian year
00571     kjy = iy+4712
00572 
00573   END SUBROUTINE Get_JulianYearDay
00574 
00575   INTEGER FUNCTION Get_JulianYearLen(ky)
00576     !+
00577     !
00578     ! Get_JulianYearLen  [function, integer]
00579     !    get the length of a Julian year in days
00580     !    (
00581     !    year [integer] input (Calendar year)
00582     !    )
00583     !
00584     !-
00585     INTEGER, INTENT(in) :: ky
00586 
00587     INTEGER :: ylen
00588 
00589     IF ( eq_months .and. eq_years ) THEN
00590         Get_JulianYearLen = 360
00591         RETURN
00592     ENDIF
00593     IF ( eq_years ) THEN
00594         Get_JulianYearLen = 365
00595         RETURN
00596     ENDIF
00597 
00598     IF (ky == 1582) THEN
00599        ylen = 355
00600     ELSE IF ( (MOD(ky,4)==0 .AND. MOD(ky,100)/=0) .OR. MOD(ky,400)==0 ) THEN
00601        ylen = 366
00602     ELSE
00603        ylen = 365
00604     END IF
00605     Get_JulianYearLen = ylen
00606 
00607   END FUNCTION Get_JulianYearLen
00608 
00609   INTEGER FUNCTION Get_JulianMonLen(ky, km)
00610     !+
00611     !
00612     ! Get_JulianMonLen [function, integer]
00613     !    get the length of a months in a Julian year
00614     !    (
00615     !    year  [integer] input (Calendar year)
00616     !    month [integer] input (month of the year)
00617     !    )
00618     !
00619     !-
00620     INTEGER, INTENT(in) :: km, ky
00621 
00622     INTEGER :: idmax
00623 
00624     IF ( eq_months ) THEN
00625         Get_JulianMonLen = 30
00626         RETURN
00627     ENDIF
00628 
00629     SELECT CASE(km)
00630     CASE(1,3,5,7,8,10,12);  idmax = 31
00631     CASE(4,6,9,11);         idmax = 30
00632     CASE(2)
00633       IF ( (MOD(ky,4)==0 .AND. MOD(ky,100)/=0) .OR. MOD(ky,400)==0 ) THEN
00634         ! leap year found
00635         idmax = 29
00636       ELSE
00637         idmax = 28
00638       END IF
00639 
00640     CASE default
00641       WRITE(*,'(a,a)') 'mo_time_base: Get_JulianMonLen', ' month invalid', km
00642       call psmile_abort
00643     END SELECT
00644     Get_JulianMonLen = idmax
00645 
00646   END FUNCTION Get_JulianMonLen
00647 
00648   SUBROUTINE Print_JulianDay(my_day)
00649     !+
00650     !
00651     ! Print_JulianDay [subroutine] interface [print]
00652     !   print Julian/model day on standard output
00653     !   (
00654     !   date [julian_date] input (model/Julian calendar day)
00655     !   )
00656     !
00657     !-
00658     TYPE (julian_date), INTENT(in) :: my_day
00659 
00660     WRITE(*,*) 'Print_JulianDay: ', my_day%day+my_day%fraction
00661 
00662   END SUBROUTINE Print_JulianDay
00663 
00664   FUNCTION sec2frac(sec) RESULT (zfrac)
00665     !+
00666     !
00667     ! sec2frac [function, real_dp]
00668     !    convert seconds of day into fraction
00669     !    (
00670     !    second [dble] input (seconds of the day)
00671     !    )
00672     !
00673     !-
00674     Double Precision, INTENT(in) :: sec
00675     Double Precision             :: zfrac
00676 
00677     zfrac = sec/REAL(IDAYLEN,dp)
00678 
00679   END FUNCTION Sec2frac
00680 
00681   FUNCTION frac2sec(zfrac) RESULT (sec)
00682     !+
00683     !
00684     ! frac2sec [function, dble]
00685     !    convert fraction of day into seconds
00686     !    (
00687     !    fraction [real_dp] input (fraction of the day)
00688     !    )
00689     !
00690     !-
00691     Double Precision, INTENT(in) :: zfrac
00692     Double Precision             :: sec
00693 
00694     sec = INT(zfrac*REAL(IDAYLEN,dp))
00695 
00696   END FUNCTION frac2sec
00697 
00698   SUBROUTINE Get_MonDay ( days, km, kd )
00699     Double Precision, INTENT(IN) :: days
00700     INTEGER, INTENT(OUT) :: km 
00701     INTEGER, INTENT(OUT) :: kd
00702 
00703     INTEGER              :: m
00704 
00705     Double Precision :: mon_lens(12)
00706 
00707     DATA mon_lens / 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 /
00708 
00709     DO m = 1, 11
00710        IF ( days <= mon_lens(m+1) ) EXIT
00711     END DO
00712 
00713     kd = FLOOR(days-mon_lens(m))
00714     km = m
00715 
00716   END SUBROUTINE Get_MonDay
00717 
00718 END MODULE PRISM_calendar

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1