New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
daymod.F90 in trunk/NEMO/OFF_SRC – NEMO

source: trunk/NEMO/OFF_SRC/daymod.F90 @ 1656

Last change on this file since 1656 was 1450, checked in by cetlod, 15 years ago

implementation of iom_put in TOP, see ticket:432

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.1 KB
Line 
1MODULE daymod
2   !!======================================================================
3   !!                       ***  MODULE  daymod  ***
4   !! Ocean        :  calendar
5   !!=====================================================================
6   !! History :        !  94-09  (M. Pontaud M. Imbard)  Original code
7   !!                  !  97-03  (O. Marti)
8   !!                  !  97-05  (G. Madec)
9   !!                  !  97-08  (M. Imbard)
10   !!             9.0  !  03-09  (G. Madec)  F90 + nyear, nmonth, nday
11   !!                  !  04-01  (A.M. Treguier) new calculation based on adatrj
12   !!                  !  06-08  (G. Madec)  surface module major update
13   !!----------------------------------------------------------------------     
14
15   !!----------------------------------------------------------------------
16   !!   day        : calendar
17   !! 
18   !!           -------------------------------
19   !!           ----------- WARNING -----------
20   !!
21   !!   we suppose that the time step is deviding the number of second of in a day
22   !!             ---> MOD( rday, rdttra(1) ) == 0
23   !!
24   !!           ----------- WARNING -----------
25   !!           -------------------------------
26   !! 
27   !!----------------------------------------------------------------------
28   USE dom_oce         ! ocean space and time domain
29   USE phycst          ! physical constants
30   USE in_out_manager  ! I/O manager
31   USE prtctl          ! Print control
32   USE ioipsl, ONLY :   ymds2ju        ! for calendar
33
34   IMPLICIT NONE
35   PRIVATE
36
37   PUBLIC day        ! called by step.F90
38   PUBLIC day_init   ! called by istate.F90
39
40   INTEGER , PUBLIC ::   nyear       !: current year
41   INTEGER , PUBLIC ::   nmonth      !: current month
42   INTEGER , PUBLIC ::   nday        !: current day of the month
43   INTEGER , PUBLIC ::   ndastp      !: time step date in yyyymmdd format
44   INTEGER , PUBLIC ::   nday_year   !: current day counted from jan 1st of the current year
45   REAL(wp), PUBLIC ::   rsec_year   !: current time step counted in second since 00h jan 1st of the current year
46   REAL(wp), PUBLIC ::   rsec_month  !: current time step counted in second since 00h 1st day of the current month
47   REAL(wp), PUBLIC ::   rsec_day    !: current time step counted in second since 00h of the current day
48
49   REAL(wp), PUBLIC ::   fjulday     !: julian day
50   REAL(wp), PUBLIC ::   adatrj      !: number of elapsed days since the begining of the run
51   !                                 !: it is the accumulated duration of previous runs
52   !                                 !: that may have been run with different time steps.
53   INTEGER , PUBLIC, DIMENSION(0:1)  ::   nyear_len    !: length in days of the previous/current year
54   INTEGER , PUBLIC, DIMENSION(0:13) ::   nmonth_len   !: length in days of the months of the current year
55   REAL(wp), PUBLIC, DIMENSION(0:13) ::   rmonth_half  !: second since the beginning of the year and the halft of the months
56   REAL(wp), PUBLIC, DIMENSION(0:13) ::   rmonth_end   !: second since the beginning of the year and the end of the months
57   REAL(wp), PUBLIC                  ::   sec1jan000   !: second since Jan. 1st 00h of nit000 year and Jan. 1st 00h of the current year
58
59   ! this two variables are wrong DO NOT USE THEM !!!
60   INTEGER, PUBLIC, DIMENSION(12) ::   nbiss = (/ 31, 29, 31, 30, 31, 30,    &  !: number of days per month
61      &                                           31, 31, 30, 31, 30, 31 /)     !: (leap-year)
62   INTEGER, PUBLIC, DIMENSION(12) ::   nobis = (/ 31, 28, 31, 30, 31, 30,    &  !: number of days per month
63      &                                           31, 31, 30, 31, 30, 31 /)     !: (365 days a year)
64
65
66   !!----------------------------------------------------------------------
67   !!  OPA 9.0 , LOCEAN-IPSL (2006)
68   !! $Id$
69   !! Software governed by the CeCILL licence (modipsl/doc/NEMO_CeCILL.txt)
70   !!----------------------------------------------------------------------
71
72CONTAINS
73
74   SUBROUTINE day_init
75      !!----------------------------------------------------------------------
76      !!                   ***  ROUTINE day_init  ***
77      !!
78      !! ** Purpose :   Initialization of the calendar values to their values 1 time step before nit000
79      !!                because day will be called at the beginning of step
80      !!
81      !! ** Action  : - nyear        : current year
82      !!              - nmonth       : current month of the year nyear
83      !!              - nday         : current day of the month nmonth
84      !!              - nday_year    : current day of the year nyear
85      !!              - rsec_year    : current time step counted in second since 00h jan 1st of the current year
86      !!              - rsec_month   : current time step counted in second since 00h 1st day of the current month
87      !!              - rsec_day     : current time step counted in second since 00h of the current day
88      !!              - sec1jan000   : second since Jan. 1st 00h of nit000 year and Jan. 1st 00h of the current year
89      !!              - nmonth_len, nyear_len, rmonth_half, rmonth_end through day_mth
90      !!----------------------------------------------------------------------
91
92      ! all calendar staff is based on the fact that MOD( rday, rdttra(1) ) == 0
93      IF( MOD( rday, rdttra(1) ) /= 0 )   CALL ctl_stop( 'the time step must devide the number of second of in a day' )
94
95      ! set the calandar from ndastp (read in restart file and namelist)
96      nyear   =   ndastp / 10000
97      nmonth  = ( ndastp - (nyear * 10000) ) / 100
98      nday    =   ndastp - (nyear * 10000) - ( nmonth * 100 ) 
99
100      CALL ymds2ju( nyear, nmonth, nday, 0.0, fjulday )  ! we assume that we start run at 00:00
101      fjulday = fjulday + 1.                             ! move back to the day at nit000 (and not at nit000 - 1)
102
103
104      sec1jan000 = 0.e0
105      CALL day_mth
106     
107      IF ( nday == 0 ) THEN     !   for ex if ndastp = ndate0 - 1
108         nmonth = nmonth - 1 
109         nday = nmonth_len(nmonth)
110      ENDIF
111      IF ( nmonth == 0 ) THEN   ! go at the end of previous year
112         nmonth = 12
113         nyear = nyear - 1
114         sec1jan000 = sec1jan000 - rday * REAL( nyear_len(0), wp )
115         IF( nleapy == 1 )   CALL day_mth
116      ENDIF
117     
118      ! day since january 1st
119      nday_year = nday + SUM( nmonth_len(1:nmonth - 1) )
120     
121      ! number of seconds since the beginning of current year/month at the middle of the time-step
122      rsec_year  = REAL( nday_year, wp ) * rday - 0.5 * rdttra(1)   ! 1 time step before the middle of the first time step
123      rsec_month = REAL( nday     , wp ) * rday - 0.5 * rdttra(1)   ! because day will be called at the beginning of step
124      rsec_day   =                         rday - 0.5 * rdttra(1)
125
126      ! control print
127      IF(lwp) WRITE(numout,*)' ==============>> 1/2 time step before the start of the run DATE Y/M/D = ',   &
128           &                   nyear, '/', nmonth, '/', nday, '  rsec_day:', rsec_day
129     
130   END SUBROUTINE day_init
131
132
133   SUBROUTINE day_mth
134      !!----------------------------------------------------------------------
135      !!                   ***  ROUTINE day_init  ***
136      !!
137      !! ** Purpose :   calendar values related to the months
138      !!
139      !! ** Action  : - nmonth_len    : length in days of the months of the current year
140      !!              - nyear_len     : length in days of the previous/current year
141      !!              - rmonth_half   : second since the beginning of the year and the halft of the months
142      !!              - rmonth_end    : second since the beginning of the year and the end of the months
143      !!----------------------------------------------------------------------
144      INTEGER  ::   jm               ! dummy loop indice
145      !!----------------------------------------------------------------------
146
147      ! length of the month of the current year (from nleapy, read in namelist)
148      IF ( nleapy < 2 ) THEN
149         nmonth_len(:) = (/ 31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31 /)
150         nyear_len(:) = 365
151         IF ( nleapy == 1 ) THEN   ! we are using calandar with leap years
152            IF ( MOD(nyear-1, 4) == 0 .AND. ( MOD(nyear-1, 400) == 0 .OR. MOD(nyear-1, 100) /= 0 ) ) THEN
153               nyear_len(0) = 366
154            ENDIF
155            IF ( MOD(nyear, 4) == 0 .AND. ( MOD(nyear, 400) == 0 .OR. MOD(nyear, 100) /= 0 ) ) THEN
156               nmonth_len(2) = 29
157               nyear_len(1) = 366
158            ENDIF
159         ENDIF
160      ELSE
161         nmonth_len(:) = nleapy   ! all months with nleapy days per year
162         nyear_len(:) = 12 * nleapy
163      ENDIF
164
165      ! half month in second since the begining of the year:
166      ! time since Jan 1st   0     1     2    ...    11    12    13
167      !          ---------*--|--*--|--*--| ... |--*--|--*--|--*--|--------------------------------------
168      !                 <---> <---> <--->  ...  <---> <---> <--->       
169      ! month number      0     1     2    ...    11    12    13
170      !
171      ! rmonth_half(jm) = rday * REAL( 0.5 * nmonth_len(jm) + SUM(nmonth_len(1:jm-1)) )
172      rmonth_half(0) = - 0.5 * rday * REAL( nmonth_len(0), wp )
173      DO jm = 1, 13
174         rmonth_half(jm) = rmonth_half(jm-1) + 0.5 * rday * REAL( nmonth_len(jm-1) + nmonth_len(jm), wp )
175      END DO
176
177      rmonth_end(0) = 0.
178      DO jm = 1, 13
179         rmonth_end(jm) = rmonth_end(jm-1) + rday * REAL( nmonth_len(jm), wp )
180      END DO
181                 
182   END SUBROUTINE
183
184
185   SUBROUTINE day( kt )
186      !!----------------------------------------------------------------------
187      !!                      ***  ROUTINE day  ***
188      !!
189      !! ** Purpose :   Compute the date with a day iteration IF necessary.
190      !!
191      !! ** Method  : - ???
192      !!
193      !! ** Action  : - nyear     : current year
194      !!              - nmonth    : current month of the year nyear
195      !!              - nday      : current day of the month nmonth
196      !!              - nday_year : current day of the year nyear
197      !!              - ndastp    : = nyear*10000 + nmonth*100 + nday
198      !!              - adatrj    : date in days since the beginning of the run
199      !!              - rsec_year : current time of the year (in second since 00h, jan 1st)
200      !!----------------------------------------------------------------------     
201      INTEGER, INTENT(in) ::   kt        ! ocean time-step indices
202      !
203      CHARACTER (len=25) ::   charout
204      !!----------------------------------------------------------------------
205
206      !                                                 ! New time-step
207      rsec_year  = rsec_year  + rdttra(1) 
208      rsec_month = rsec_month + rdttra(1)                 
209      rsec_day   = rsec_day   + rdttra(1)                 
210      adatrj = adatrj + rdttra(1) / rday
211      fjulday = fjulday + rdttra(1) / rday
212   
213      IF( rsec_day > rday ) THEN                        ! NEW day
214         !
215         nday      = nday + 1
216         nday_year = nday_year + 1
217         rsec_day  = 0.5 * rdttra(1)                 
218         !
219         IF( nday == nmonth_len(nmonth) + 1 ) THEN      ! NEW month
220            nday   = 1
221            nmonth = nmonth + 1
222            rsec_month = 0.5 * rdttra(1)
223            IF( nmonth == 13 ) THEN                     ! NEW year
224               nyear     = nyear + 1
225               nmonth    = 1
226               nday_year = 1
227               rsec_year = 0.5 * rdttra(1)
228               sec1jan000 = sec1jan000 + rday * REAL( nyear_len(1), wp )
229               IF( nleapy == 1 )   CALL day_mth
230            ENDIF
231         ENDIF
232         !
233         ndastp = nyear * 10000 + nmonth * 100 + nday   ! NEW date
234         !
235         IF(lwp) WRITE(numout,'(a,i8,a,i4.4,a,i2.2,a,i2.2,a,i3.3)') '======>> time-step =', kt,   &
236              &   '      New day, DATE Y/M/D = ', nyear, '/', nmonth, '/', nday, '      nday_year = ', nday_year
237         IF(lwp) WRITE(numout,'(a,F9.0,a,F9.0,a,F9.0)') '         rsec_year = ', rsec_year,   &
238              &   '   rsec_month = ', rsec_month, '   rsec_day = ', rsec_day
239      ENDIF
240     
241      IF(ln_ctl) THEN
242         WRITE(charout,FMT="('kt =', I4,'  d/m/y =',I2,I2,I4)") kt, nday, nmonth, nyear
243         CALL prt_ctl_info(charout)
244      ENDIF
245
246      !
247   END SUBROUTINE day
248   !!======================================================================
249END MODULE daymod
Note: See TracBrowser for help on using the repository browser.