ESMF_Calendar.F90

References to this file elsewhere.
1 !
2 ! Earth System Modeling Framework
3 ! Copyright 2002-2003, University Corporation for Atmospheric Research,
4 ! Massachusetts Institute of Technology, Geophysical Fluid Dynamics
5 ! Laboratory, University of Michigan, National Centers for Environmental
6 ! Prediction, Los Alamos National Laboratory, Argonne National Laboratory,
7 ! NASA Goddard Space Flight Center.
8 ! Licensed under the University of Illinois-NCSA license.
9 !
10 !==============================================================================
11 !
12 !     ESMF Calendar Module
13       module ESMF_CalendarMod
14 !
15 !==============================================================================
16 !
17 ! This file contains the Calendar class definition and all Calendar class
18 ! methods.
19 !
20 !------------------------------------------------------------------------------
21 ! INCLUDES
22 #include <ESMF_TimeMgr.inc>
23 
24 !==============================================================================
25 !BOPI
26 ! !MODULE: ESMF_CalendarMod
27 !
28 ! !DESCRIPTION:
29 ! Part of Time Manager F90 API wrapper of C++ implemenation
30 !
31 ! Defines F90 wrapper entry points for corresponding
32 ! C++ class { \tt ESMC\_Calendar} implementation
33 !
34 ! See {\tt ../include/ESMC\_Calendar.h} for complete description
35 !
36 !------------------------------------------------------------------------------
37 ! !USES:
38       ! inherit from ESMF base class
39       use ESMF_BaseMod
40 
41       ! inherit from base time class
42       use ESMF_BaseTimeMod
43 
44       implicit none
45 !
46 !------------------------------------------------------------------------------
47 ! !PRIVATE TYPES:
48       private
49 !------------------------------------------------------------------------------
50 
51 
52 
53       INTEGER, PARAMETER :: MONTHS_PER_YEAR = 12
54       INTEGER, PARAMETER :: mday(MONTHS_PER_YEAR)   &
55                           = (/31,28,31,30,31,30,31,31,30,31,30,31/)
56       INTEGER, PARAMETER :: mdayleap(MONTHS_PER_YEAR) &
57                           = (/31,29,31,30,31,30,31,31,30,31,30,31/)
58       INTEGER, DIMENSION(365) :: daym
59       INTEGER, DIMENSION(366) :: daymleap
60       INTEGER :: mdaycum(0:MONTHS_PER_YEAR)
61       INTEGER :: mdayleapcum(0:MONTHS_PER_YEAR)
62       TYPE(ESMF_BaseTime), TARGET :: monthbdys(0:MONTHS_PER_YEAR)
63       TYPE(ESMF_BaseTime), TARGET :: monthbdysleap(0:MONTHS_PER_YEAR)
64 
65 
66 !------------------------------------------------------------------------------
67 !     ! ESMF_CalendarType
68 !
69 !     ! F90 "enum" type to match C++ ESMC_CalendarType enum
70 
71       type ESMF_CalendarType
72       private
73         integer :: caltype
74       end type
75 
76       type(ESMF_CalendarType), parameter :: &
77                                ESMF_CAL_GREGORIAN =  ESMF_CalendarType(1), &
78                                ESMF_CAL_JULIAN =     ESMF_CalendarType(2), &
79                            ! like Gregorian, except Feb always has 28 days
80                                ESMF_CAL_NOLEAP =     ESMF_CalendarType(3), & 
81                            ! 12 months, 30 days each
82                                ESMF_CAL_360DAY =     ESMF_CalendarType(4), & 
83                            ! user defined
84                                ESMF_CAL_GENERIC =    ESMF_CalendarType(5), &
85                            ! track base time seconds only
86                                ESMF_CAL_NOCALENDAR = ESMF_CalendarType(6)
87 
88 !------------------------------------------------------------------------------
89 !     ! ESMF_Calendar
90 !
91 !     ! F90 class type to match C++ Calendar class in size only;
92 !     !  all dereferencing within class is performed by C++ implementation
93 !
94 !------------------------------------------------------------------------------
95 !
96 !     ! ESMF_DaysPerYear
97 !
98       type ESMF_DaysPerYear
99       private
100         integer :: D        ! whole days per year
101 ! Fractional days-per-year are not yet used in this implementation.  
102 !        integer :: Dn       ! fractional days per year numerator
103 !        integer :: Dd       ! fractional days per year denominator
104       end type              ! e.g. for Venus, D=0, Dn=926, Dd=1000
105 !
106 !------------------------------------------------------------------------------
107 !     ! ESMF_Calendar
108 !
109 !
110       type ESMF_Calendar
111       private
112         type(ESMF_CalendarType) :: Type
113 ! TBH:  When NO_DT_COMPONENT_INIT is set, code that uses F95 compile-time 
114 ! TBH:  initialization of components of derived types is not included.  
115 ! TBH:  Some older compilers, like PGI 5.x do not support this F95 feature.  
116 #ifdef NO_DT_COMPONENT_INIT
117         logical :: Set
118 #else
119         logical :: Set = .false.
120 #endif
121         integer, dimension(MONTHS_PER_YEAR) :: DaysPerMonth
122         integer :: SecondsPerDay
123         integer :: SecondsPerYear
124         type(ESMF_DaysPerYear) :: DaysPerYear
125       end type
126 
127 !------------------------------------------------------------------------------
128 ! !PUBLIC DATA:
129    TYPE(ESMF_Calendar), public, save, pointer :: defaultCal   ! Default Calendar
130 
131 
132 !
133 !------------------------------------------------------------------------------
134 ! !PUBLIC TYPES:
135       public MONTHS_PER_YEAR
136       public mday
137       public mdayleap
138       public monthbdys
139       public monthbdysleap
140       public daym
141       public daymleap
142       public mdaycum
143       public mdayleapcum
144       public ESMF_CalendarType
145       public ESMF_CAL_GREGORIAN, ESMF_CAL_NOLEAP, &
146              ESMF_CAL_360DAY, ESMF_CAL_NOCALENDAR
147 !      public ESMF_CAL_JULIAN
148 !      public ESMF_CAL_GENERIC
149       public ESMF_Calendar
150 
151 !------------------------------------------------------------------------------
152 !
153 ! !PUBLIC MEMBER FUNCTIONS:
154       public ESMF_CalendarCreate
155 
156 ! Required inherited and overridden ESMF_Base class methods
157 
158       public ESMF_CalendarInitialized ! Only in this implementation, intended
159                                       ! to be private within ESMF methods
160 !EOPI
161 
162 !==============================================================================
163 
164       contains
165 
166 
167 !==============================================================================
168 !BOP
169 ! !IROUTINE: ESMF_CalendarCreate - Create a new ESMF Calendar of built-in type
170 
171 ! !INTERFACE:
172       ! Private name; call using ESMF_CalendarCreate()
173       function ESMF_CalendarCreate(name, calendartype, rc)
174 
175 ! !RETURN VALUE:
176       type(ESMF_Calendar) :: ESMF_CalendarCreate
177 
178 ! !ARGUMENTS:
179       character (len=*),       intent(in),  optional :: name
180       type(ESMF_CalendarType), intent(in)            :: calendartype
181       integer,                 intent(out), optional :: rc
182 
183 ! !DESCRIPTION:
184 !     Creates and sets a {\tt calendar} to the given built-in
185 !     {\tt ESMF\_CalendarType}. 
186 !
187 !     This is a private method; invoke via the public overloaded entry point
188 !     {\tt ESMF\_CalendarCreate()}.
189 !
190 !     The arguments are:
191 !     \begin{description}
192 !     \item[{[name]}]
193 !          The name for the newly created calendar.  If not specified, a
194 !          default unique name will be generated: "CalendarNNN" where NNN
195 !          is a unique sequence number from 001 to 999.
196 !     \item[calendartype]
197 !          The built-in {\tt ESMF\_CalendarType}.  Valid values are:
198 !            {\tt ESMF\_CAL\_360DAY}, {\tt ESMF\_CAL\_GREGORIAN},
199 !            {\tt ESMF\_CAL\_JULIANDAY}, {\tt ESMF\_CAL\_NOCALENDAR}, and
200 !            {\tt ESMF\_CAL\_NOLEAP}.
201 !          See the "Time Manager Reference" document for a description of
202 !          each calendar type.
203 !     \item[{[rc]}]
204 !          Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
205 !     \end{description}
206 !    
207 !EOP
208 ! !REQUIREMENTS:
209 !     TMGn.n.n
210       type(ESMF_DaysPerYear) :: dayspy
211 
212       if ( present(rc) ) rc = ESMF_FAILURE
213 ! Calendar type is hard-coded.  Use ESMF library if more flexibility is 
214 ! needed.  
215 #ifdef NO_LEAP_CALENDAR
216       if ( calendartype%caltype  /= ESMF_CAL_NOLEAP%caltype ) then
217          write(6,*) 'Not a valid calendar type for this implementation'
218          write(6,*) 'This implementation only allows ESMF_CAL_NOLEAP'
219          write(6,*) 'calender type set to     = ', calendartype%caltype
220          write(6,*) 'NO_LEAP calendar type is = ', ESMF_CAL_NOLEAP%caltype
221          return
222       end if
223       ESMF_CalendarCreate%Type = ESMF_CAL_NOLEAP
224 #else
225       if ( calendartype%caltype  /= ESMF_CAL_GREGORIAN%caltype ) then
226          write(6,*) 'Not a valid calendar type for this implementation'
227          write(6,*) 'This implementation only allows ESMF_CAL_GREGORIAN'
228          write(6,*) 'calender type set to     = ', calendartype%caltype
229          write(6,*) 'GREGORIAN calendar type is = ', ESMF_CAL_GREGORIAN%caltype
230          return
231       end if
232       ESMF_CalendarCreate%Type = ESMF_CAL_GREGORIAN
233 #endif
234 ! This is a bug on some systems -- need initial value set by compiler at 
235 ! startup.  
236 ! However, note that some older compilers do not support compile-time 
237 ! initialization of data members of Fortran derived data types.  For example, 
238 ! PGI 5.x compilers do not support this F95 feature.  See 
239 ! NO_DT_COMPONENT_INIT.  
240       ESMF_CalendarCreate%Set = .true.
241       ESMF_CalendarCreate%SecondsPerDay = SECONDS_PER_DAY
242 ! DaysPerYear and SecondsPerYear are incorrect for Gregorian calendars...  
243       dayspy%D = size(daym)
244 !TBH:  TODO:  Replace DaysPerYear and SecondsPerYear with methods 
245 !TBH:  TODO:  since they only make sense for the NO_LEAP calendar!  
246       ESMF_CalendarCreate%DaysPerYear = dayspy
247       ESMF_CalendarCreate%SecondsPerYear = ESMF_CalendarCreate%SecondsPerDay &
248                                        * dayspy%D
249 !TBH:  TODO:  use mdayleap for leap-year calendar
250       ESMF_CalendarCreate%DaysPerMonth(:) = mday(:)
251 
252       if ( present(rc) ) rc = ESMF_SUCCESS
253 
254       end function ESMF_CalendarCreate
255 
256 
257 !==============================================================================
258 !BOP
259 ! !IROUTINE: ESMF_CalendarInitialized - check if calendar was created
260 
261 ! !INTERFACE:
262       function ESMF_CalendarInitialized(calendar)
263 
264 ! !RETURN VALUE:
265       logical ESMF_CalendarInitialized
266 
267 ! !ARGUMENTS:
268       type(ESMF_Calendar), intent(in)            :: calendar
269 
270 ! !DESCRIPTION:
271 !EOP
272 ! !REQUIREMENTS:
273 !     TMGn.n.n
274 ! Note that return value from this function will be bogus for older compilers 
275 ! that do not support compile-time initialization of data members of Fortran 
276 ! derived data types.  For example, PGI 5.x compilers do not support this F95 
277 ! feature.  At the moment, the call to this fuction is #ifdefd out when the 
278 ! leap-year calendar is used so this is not an issue for WRF (see 
279 ! NO_DT_COMPONENT_INIT).  
280         ESMF_CalendarInitialized = calendar%set
281 
282      end function ESMF_CalendarInitialized
283 
284       end module ESMF_CalendarMod