/[lmdze]/trunk/libf/IOIPSL/calendar.f90
ViewVC logotype

Annotation of /trunk/libf/IOIPSL/calendar.f90

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (hide annotations)
Tue Apr 6 17:52:58 2010 UTC (14 years, 2 months ago) by guez
File size: 20425 byte(s)
Split "stringop.f90" into single-procedure files. Gathered files in directory
"IOIPSL/Stringop".

Split "flincom.f90" into "flincom.f90" and "flinget.f90". Removed
unused procedures from module "flincom". Removed unused argument
"filename" of procedure "flinopen_nozoom".

Removed unused files.

Split "grid_change.f90" into "grid_change.f90" and
"gr_phy_write_3d.f90".

Removed unused procedures from modules "calendar", "ioipslmpp",
"grid_atob", "gath_cpl" and "getincom". Removed unused procedures in
files "ppm3d.f" and "thermcell.f".

Split "mathelp.f90" into "mathelp.f90" and "mathop.f90".

Removed unused variable "dpres" of module "comvert".

Use argument "itau" instead of local variables "iadvtr" and "first" to
control algorithm in procedure "fluxstokenc".

Removed unused arguments of procedure "integrd".

Removed useless computations at the end of procedure "leapfrog".

Merged common block "matrfil" into module "parafilt".

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

  ViewVC Help
Powered by ViewVC 1.1.21