/[lmdze]/trunk/IOIPSL/calendar.f
ViewVC logotype

Contents of /trunk/IOIPSL/calendar.f

Parent Directory Parent Directory | Revision Log Revision Log


Revision 91 - (show annotations)
Wed Mar 26 17:18:58 2014 UTC (10 years, 2 months ago) by guez
File size: 15912 byte(s)
Removed unused variables lock_startdate and time_stamp of module
calendar.

Noticed that physiq does not change the surface pressure. So removed
arguments ps and dpfi of subroutine addfi. dpfi was always 0. The
computation of ps in addfi included some averaging at the poles. In
principle, this does not change ps but in practice it does because of
finite numerical precision. So the results of the simulation are
changed. Removed arguments ps and dpfi of calfis. Removed argument
d_ps of physiq.

du at the poles is not computed by dudv1, so declare only the
corresponding latitudes in dudv1. caldyn passes only a section of the
array dudyn as argument.

Removed variable niadv of module iniadvtrac_m.

Declared arguments of exner_hyb as assumed-shape arrays and made all
other horizontal sizes in exner_hyb dynamic. This allows the external
program test_disvert to use exner_hyb at a single horizontal position.

1 MODULE calendar
2
3 ! From IOIPSL/src/calendar.f90, version 2.0 2004/04/05 14:47:47
4
5 ! This is the calendar used to do all calculations on time. Three
6 ! types of calendars are possible:
7
8 ! - Gregorian:
9 ! The normal calendar. The time origin for the julian day in this
10 ! case is 24 Nov -4713.
11
12 ! - No leap:
13 ! A 365 day year without leap years. The origin for the julian days
14 ! is in this case 1 Jan 0.
15
16 ! - xxxd:
17 ! Year of xxx days with months of equal length. The origin for the
18 ! julian days is then also 1 Jan 0.
19
20 ! As one can see it is difficult to go from one calendar to the
21 ! other. All operations involving julian days will be wrong. This
22 ! calendar will lock as soon as possible the length of the year and
23 ! forbid any further modification.
24
25 ! For the non leap-year calendar the method is still brute force.
26 ! We need to find an integer series which takes care of the length
27 ! of the various month. (Jan)
28
29 USE strlowercase_m, ONLY: strlowercase
30 USE errioipsl, ONLY: histerr
31
32 IMPLICIT NONE
33
34 PRIVATE
35 PUBLIC ymds2ju, ju2ymds, isittime, ioconf_calendar, itau2date, lock_unan, &
36 calendar_used, un_an, un_jour
37
38 REAL, PARAMETER:: un_jour = 86400. ! one day in seconds
39
40 ! Description of calendar
41
42 CHARACTER(LEN=20):: calendar_used = "gregorian"
43 LOGICAL:: lock_unan = .FALSE.
44 REAL:: un_an = 365.2425 ! one year in days
45 INTEGER:: mon_len(12) = (/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/)
46
47 CHARACTER(LEN=3), PARAMETER:: cal(12) = (/'JAN', 'FEB', 'MAR', 'APR', &
48 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'/)
49
50 REAL, SAVE:: start_day, start_sec
51
52 CONTAINS
53
54 SUBROUTINE ymds2ju (year, month, day, sec, julian)
55
56 INTEGER, INTENT(IN):: year, month, day
57 REAL, INTENT(IN):: sec
58 REAL, INTENT(OUT):: julian
59
60 INTEGER:: julian_day
61 REAL:: julian_sec
62
63 !--------------------------------------------------------------------
64
65 CALL ymds2ju_internal(year, month, day, sec, julian_day, julian_sec)
66 julian = julian_day + julian_sec / un_jour
67
68 END SUBROUTINE ymds2ju
69
70 !===
71
72 SUBROUTINE ymds2ju_internal (year, month, day, sec, julian_day, julian_sec)
73
74 ! Converts year, month, day and seconds into a julian day
75
76 ! In 1968 in a letter to the editor of Communications of the ACM
77 ! (CACM, volume 11, number 10, October 1968, p.657) Henry F. Fliegel
78 ! and Thomas C. Van Flandern presented such an algorithm.
79
80 ! See also: http://www.magnet.ch/serendipity/hermetic/cal_stud/jdn.htm
81
82 ! In the case of the Gregorian calendar we have chosen to use
83 ! the Lilian day numbers. This is the day counter which starts
84 ! on the 15th October 1582.
85 ! This is the day at which Pope Gregory XIII introduced the
86 ! Gregorian calendar.
87 ! Compared to the true Julian calendar, which starts some
88 ! 7980 years ago, the Lilian days are smaler and are dealt with
89 ! easily on 32 bit machines. With the true Julian days you can only
90 ! the fraction of the day in the real part to a precision of
91 ! a 1/4 of a day with 32 bits.
92
93 INTEGER, INTENT(IN):: year, month, day
94 REAL, INTENT(IN):: sec
95
96 INTEGER, INTENT(OUT):: julian_day
97 REAL, INTENT(OUT):: julian_sec
98
99 INTEGER:: jd, m, y, d, ml
100 !--------------------------------------------------------------------
101 lock_unan = .TRUE.
102
103 m = month
104 y = year
105 d = day
106
107 ! We deduce the calendar from the length of the year as it
108 ! is faster than an INDEX on the calendar variable.
109
110 ! Gregorian
111 IF ( (un_an > 365.0).AND.(un_an < 366.0) ) THEN
112 jd = (1461*(y+4800+INT(( m-14 )/12)))/4 &
113 & +(367*(m-2-12*(INT(( m-14 )/12))))/12 &
114 & -(3*((y+4900+INT((m-14)/12))/100))/4 &
115 & +d-32075
116 jd = jd-2299160
117 ! No leap or All leap
118 ELSE IF (ABS(un_an-365.0) <= EPSILON(un_an) .OR. &
119 & ABS(un_an-366.0) <= EPSILON(un_an)) THEN
120 ml = SUM(mon_len(1:m-1))
121 jd = y*INT(un_an)+ml+(d-1)
122 ! Calendar with regular month
123 ELSE
124 ml = INT(un_an)/12
125 jd = y*INT(un_an)+(m-1)*ml+(d-1)
126 ENDIF
127
128 julian_day = jd
129 julian_sec = sec
130
131 END SUBROUTINE ymds2ju_internal
132
133 !===
134
135 SUBROUTINE ju2ymds (julian, year, month, day, sec)
136
137 REAL, INTENT(IN):: julian
138
139 INTEGER, INTENT(OUT):: year, month, day
140 REAL, INTENT(OUT):: sec
141
142 INTEGER:: julian_day
143 REAL:: julian_sec
144 !--------------------------------------------------------------------
145 julian_day = INT(julian)
146 julian_sec = (julian-julian_day)*un_jour
147
148 CALL ju2ymds_internal(julian_day, julian_sec, year, month, day, sec)
149
150 END SUBROUTINE ju2ymds
151
152 !===
153
154 SUBROUTINE ju2ymds_internal (julian_day, julian_sec, year, month, day, sec)
155
156 ! This subroutine computes from the julian day the year,
157 ! month, day and seconds
158
159 ! In 1968 in a letter to the editor of Communications of the ACM
160 ! (CACM, volume 11, number 10, October 1968, p.657) Henry F. Fliegel
161 ! and Thomas C. Van Flandern presented such an algorithm.
162
163 ! See also: http://www.magnet.ch/serendipity/hermetic/cal_stud/jdn.htm
164
165 ! In the case of the Gregorian calendar we have chosen to use
166 ! the Lilian day numbers. This is the day counter which starts
167 ! on the 15th October 1582. This is the day at which Pope
168 ! Gregory XIII introduced the Gregorian calendar.
169 ! Compared to the true Julian calendar, which starts some 7980
170 ! years ago, the Lilian days are smaler and are dealt with easily
171 ! on 32 bit machines. With the true Julian days you can only the
172 ! fraction of the day in the real part to a precision of a 1/4 of
173 ! a day with 32 bits.
174
175 INTEGER, INTENT(IN):: julian_day
176 REAL, INTENT(IN):: julian_sec
177
178 INTEGER, INTENT(OUT):: year, month, day
179 REAL, INTENT(OUT):: sec
180
181 INTEGER:: l, n, i, jd, j, d, m, y, ml
182 INTEGER:: add_day
183 !--------------------------------------------------------------------
184 lock_unan = .TRUE.
185
186 jd = julian_day
187 sec = julian_sec
188 IF (sec > un_jour) THEN
189 add_day = INT(sec/un_jour)
190 sec = sec-add_day*un_jour
191 jd = jd+add_day
192 ENDIF
193
194 ! Gregorian
195 IF ( (un_an > 365.0).AND.(un_an < 366.0) ) THEN
196 jd = jd+2299160
197
198 l = jd+68569
199 n = (4*l)/146097
200 l = l-(146097*n+3)/4
201 i = (4000*(l+1))/1461001
202 l = l-(1461*i)/4+31
203 j = (80*l)/2447
204 d = l-(2447*j)/80
205 l = j/11
206 m = j+2-(12*l)
207 y = 100*(n-49)+i+l
208 ! No leap or All leap
209 ELSE IF (ABS(un_an-365.0) <= EPSILON(un_an) .OR. &
210 & ABS(un_an-366.0) <= EPSILON(un_an) ) THEN
211 y = jd/INT(un_an)
212 l = jd-y*INT(un_an)
213 m = 1
214 ml = 0
215 DO WHILE (ml+mon_len(m) <= l)
216 ml = ml+mon_len(m)
217 m = m+1
218 ENDDO
219 d = l-ml+1
220 ! others
221 ELSE
222 ml = INT(un_an)/12
223 y = jd/INT(un_an)
224 l = jd-y*INT(un_an)
225 m = (l/ml)+1
226 d = l-(m-1)*ml+1
227 ENDIF
228
229 day = d
230 month = m
231 year = y
232
233 END SUBROUTINE ju2ymds_internal
234
235 !===
236
237 REAL FUNCTION itau2date (itau, date0, deltat)
238
239 ! This function transforms itau into a date. The date whith which
240 ! the time axis is going to be labeled
241
242 ! INPUT
243 ! itau: current time step
244 ! date0: Date at which itau was equal to 0
245 ! deltat: time step between itau s
246
247 ! OUTPUT
248 ! itau2date: Date for the given itau
249
250 INTEGER:: itau
251 REAL:: date0, deltat
252 !--------------------------------------------------------------------
253 itau2date = REAL(itau)*deltat/un_jour+date0
254
255 END FUNCTION itau2date
256
257 !===
258
259 SUBROUTINE isittime &
260 & (itau, date0, dt, freq, last_action, last_check, do_action)
261
262 ! This subroutine checks the time has come for a given action.
263 ! This is computed from the current time-step(itau).
264 ! Thus we need to have the time delta (dt), the frequency
265 ! of the action (freq) and the last time it was done
266 ! (last_action in units of itau).
267 ! In order to extrapolate when will be the next check we need
268 ! the time step of the last call (last_check).
269
270 ! The test is done on the following condition:
271 ! the distance from the current time to the time for the next
272 ! action is smaller than the one from the next expected
273 ! check to the next action.
274 ! When the test is done on the time steps simplifactions make
275 ! it more difficult to read in the code.
276 ! For the real time case it is easier to understand !
277
278 INTEGER, INTENT(IN):: itau
279 REAL, INTENT(IN):: dt, freq
280 INTEGER, INTENT(IN):: last_action, last_check
281 REAL, INTENT(IN):: date0
282
283 LOGICAL, INTENT(OUT):: do_action
284
285 REAL:: dt_action, dt_check
286 REAL:: date_last_act, date_next_check, date_next_act, &
287 & date_now, date_mp1, date_mpf
288 INTEGER:: year, month, monthp1, day, next_check_itau, next_act_itau
289 INTEGER:: yearp, dayp
290 REAL:: sec, secp
291 LOGICAL:: check = .FALSE.
292 !--------------------------------------------------------------------
293 IF (check) THEN
294 WRITE(*, *) &
295 & "isittime 1.0 ", itau, date0, dt, freq, last_action, last_check
296 ENDIF
297
298 IF (last_check >= 0) THEN
299 dt_action = (itau-last_action)*dt
300 dt_check = (itau-last_check)*dt
301 next_check_itau = itau+(itau-last_check)
302
303 !- We are dealing with frequencies in seconds and thus operation
304 !- can be done on the time steps.
305
306 IF (freq > 0) THEN
307 IF (ABS(dt_action-freq) <= ABS(dt_action+dt_check-freq)) THEN
308 do_action = .TRUE.
309 ELSE
310 do_action = .FALSE.
311 ENDIF
312
313 !--- Here we deal with frequencies in month and work on julian days.
314
315 ELSE
316 date_now = itau2date (itau, date0, dt)
317 date_last_act = itau2date (last_action, date0, dt)
318 CALL ju2ymds (date_last_act, year, month, day, sec)
319 monthp1 = month - freq
320 yearp = year
321
322 !--- Here we compute what logically should be the next month
323
324 IF (month >= 13) THEN
325 yearp = year+1
326 monthp1 = monthp1-12
327 ENDIF
328 CALL ymds2ju (year, monthp1, day, sec, date_mpf)
329
330 !--- But it could be that because of a shorter month or a bad
331 !--- starting date that we end up further than we should be.
332 !--- Thus we compute the first day of the next month.
333 !--- We can not be beyond this date and if we are close
334 !--- then we will take it as it is better.
335
336 monthp1 = month+ABS(freq)
337 yearp=year
338 IF (monthp1 >= 13) THEN
339 yearp = year+1
340 monthp1 = monthp1 -12
341 ENDIF
342 dayp = 1
343 secp = 0.0
344 CALL ymds2ju (yearp, monthp1, dayp, secp, date_mp1)
345
346 !--- If date_mp1 is smaller than date_mpf or only less than 4 days
347 !--- larger then we take it. This needed to ensure that short month
348 !--- like February do not mess up the thing !
349
350 IF (date_mp1-date_mpf < 4.) THEN
351 date_next_act = date_mp1
352 ELSE
353 date_next_act = date_mpf
354 ENDIF
355 date_next_check = itau2date (next_check_itau, date0, dt)
356
357 !--- Transform the dates into time-steps for the needed precisions.
358
359 next_act_itau = &
360 & last_action+INT((date_next_act-date_last_act)*(un_jour/dt))
361
362 IF ( ABS(itau-next_act_itau) &
363 & <= ABS( next_check_itau-next_act_itau)) THEN
364 do_action = .TRUE.
365 IF (check) THEN
366 WRITE(*, *) &
367 & 'ACT-TIME: itau, next_act_itau, next_check_itau: ', &
368 & itau, next_act_itau, next_check_itau
369 CALL ju2ymds (date_now, year, month, day, sec)
370 WRITE(*, *) 'ACT-TIME: y, m, d, s: ', year, month, day, sec
371 WRITE(*, *) &
372 & 'ACT-TIME: date_mp1, date_mpf: ', date_mp1, date_mpf
373 ENDIF
374 ELSE
375 do_action = .FALSE.
376 ENDIF
377 ENDIF
378
379 IF (check) THEN
380 WRITE(*, *) "isittime 2.0 ", &
381 & date_next_check, date_next_act, ABS(dt_action-freq), &
382 & ABS(dt_action+dt_check-freq), dt_action, dt_check, &
383 & next_check_itau, do_action
384 ENDIF
385 ELSE
386 do_action=.FALSE.
387 ENDIF
388
389 END SUBROUTINE isittime
390
391 !===
392
393 SUBROUTINE ioconf_calendar (str)
394
395 ! This routine allows to configure the calendar to be used.
396 ! This operation is only allowed once and the first call to
397 ! ymds2ju or ju2ymsd will lock the current configuration.
398 ! the argument to ioconf_calendar can be any of the following:
399 ! - gregorian: This is the gregorian calendar (default here)
400 ! - noleap: A calendar without leap years = 365 days
401 ! - xxxd: A calendar of xxx days (has to be a modulo of 12)
402 ! with 12 month of equal length
403
404 CHARACTER(LEN=*), INTENT(IN):: str
405
406 INTEGER:: leng, ipos
407 CHARACTER(LEN=10):: str10
408 !--------------------------------------------------------------------
409
410 ! 1.0 Clean up the sring !
411
412 CALL strlowercase (str)
413
414 IF (.NOT.lock_unan) THEN
415
416 lock_unan=.TRUE.
417
418 SELECT CASE(str)
419 CASE('gregorian')
420 calendar_used = 'gregorian'
421 un_an = 365.2425
422 mon_len(:)=(/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/)
423 CASE('standard')
424 calendar_used = 'gregorian'
425 un_an = 365.2425
426 mon_len(:)=(/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/)
427 CASE('proleptic_gregorian')
428 calendar_used = 'gregorian'
429 un_an = 365.2425
430 mon_len(:)=(/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/)
431 CASE('noleap')
432 calendar_used = 'noleap'
433 un_an = 365.0
434 mon_len(:)=(/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/)
435 CASE('365_day')
436 calendar_used = 'noleap'
437 un_an = 365.0
438 mon_len(:)=(/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/)
439 CASE('365d')
440 calendar_used = 'noleap'
441 un_an = 365.0
442 mon_len(:)=(/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/)
443 CASE('all_leap')
444 calendar_used = 'all_leap'
445 un_an = 366.0
446 mon_len(:)=(/31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/)
447 CASE('366_day')
448 calendar_used = 'all_leap'
449 un_an = 366.0
450 mon_len(:)=(/31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/)
451 CASE('366d')
452 calendar_used = 'all_leap'
453 un_an = 366.0
454 mon_len(:)=(/31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/)
455 CASE DEFAULT
456 ipos = INDEX(str, 'd')
457 IF (ipos == 4) THEN
458 READ(str(1:3), '(I3)') leng
459 IF ( (MOD(leng, 12) == 0).AND.(leng > 1) ) THEN
460 calendar_used = str
461 un_an = leng
462 mon_len(:) = leng
463 ELSE
464 CALL histerr (3, 'ioconf_calendar', &
465 & 'The length of the year as to be a modulo of 12', &
466 & 'so that it can be divided into 12 month of equal length', &
467 & str)
468 ENDIF
469 ELSE
470 CALL histerr (3, 'ioconf_calendar', &
471 & 'Unrecognized input, please ceck the man pages.', str, ' ')
472 ENDIF
473 END SELECT
474 ELSE
475 WRITE(str10, '(f10.4)') un_an
476 CALL histerr (2, 'ioconf_calendar', &
477 & 'The calendar was already used or configured. You are not', &
478 & 'allowed to change it again. '// &
479 & 'The following length of year is used:', str10)
480 ENDIF
481
482 END SUBROUTINE ioconf_calendar
483
484 END MODULE calendar

  ViewVC Help
Powered by ViewVC 1.1.21