1 |
C $Header: $ |
2 |
C $Name: $ |
3 |
|
4 |
#include "PACKAGES_CONFIG.h" |
5 |
#include "CPP_OPTIONS.h" |
6 |
subroutine set_alarm (tag,date,time,freq) |
7 |
C*********************************************************************** |
8 |
C Purpose |
9 |
C ------- |
10 |
C Utility to Set Internal Alarms |
11 |
C |
12 |
C Argument Description |
13 |
C -------------------- |
14 |
C tag ....... Character String Tagging Alarm Process |
15 |
C date ...... Begining Date for Alarm |
16 |
C time ...... Begining Time for Alarm |
17 |
C freq ...... Repeating Frequency Interval for Alarm |
18 |
C |
19 |
C*********************************************************************** |
20 |
|
21 |
implicit none |
22 |
character*(*) tag |
23 |
integer freq,date,time |
24 |
|
25 |
#ifdef ALLOW_USE_MPI |
26 |
#include "SIZE.h" |
27 |
#include "EEPARAMS.h" |
28 |
#include "EESUPPORT.h" |
29 |
#endif |
30 |
|
31 |
#include "chronos.h" |
32 |
|
33 |
#ifdef ALLOW_USE_MPI |
34 |
c MPI Utilities |
35 |
c ------------- |
36 |
#include "mpif.h" |
37 |
integer mpi_comm_model,ierror |
38 |
#endif |
39 |
|
40 |
integer myid |
41 |
logical first,set |
42 |
data first /.true./ |
43 |
|
44 |
integer n |
45 |
#ifdef ALLOW_USE_MPI |
46 |
call mpi_comm_rank ( mpi_comm_model,myid,ierror ) |
47 |
#else |
48 |
myid = 1 |
49 |
#endif |
50 |
|
51 |
if(first) then |
52 |
ntags = 1 |
53 |
tags(1) = tag |
54 |
freqs(1) = freq |
55 |
dates(1) = date |
56 |
times(1) = time |
57 |
if( myid.eq.1 ) write(6,100) date,time,freq,tags(1) |
58 |
else |
59 |
|
60 |
set = .false. |
61 |
do n=1,ntags |
62 |
if(tag.eq.tags(n)) then |
63 |
if( myid.eq.1 ) then |
64 |
print *, 'Warning! Alarm has already been set for Tag: ',tag |
65 |
print *, 'Changing Alarm Information:' |
66 |
print *, 'Frequency: ',freqs(n),' (Old) ',freq,' (New)' |
67 |
print *, ' Date0: ',dates(n),' (Old) ',date,' (New)' |
68 |
print *, ' Time0: ',times(n),' (Old) ',time,' (New)' |
69 |
endif |
70 |
freqs(n) = freq |
71 |
dates(n) = date |
72 |
times(n) = time |
73 |
set = .true. |
74 |
endif |
75 |
enddo |
76 |
if(.not.set) then |
77 |
ntags = ntags+1 |
78 |
if(ntags.gt.maxtag ) then |
79 |
if( myid.eq.1 ) then |
80 |
print *, 'Too many Alarms are Set!!' |
81 |
print *, 'Maximum Number of Alarms = ',maxtag |
82 |
endif |
83 |
call my_finalize |
84 |
call my_exit (101) |
85 |
endif |
86 |
tags(ntags) = tag |
87 |
freqs(ntags) = freq |
88 |
dates(ntags) = date |
89 |
times(ntags) = time |
90 |
if( myid.eq.1 ) write(6,100) date,time,freq,tags(ntags) |
91 |
endif |
92 |
endif |
93 |
|
94 |
first = .false. |
95 |
100 format(1x,'Setting Alarm for: ',i8,2x,i6.6,', with frequency: ', |
96 |
. i8,', and Tag: ',a80) |
97 |
return |
98 |
end |
99 |
|
100 |
subroutine get_alarm (tag,date,time,freq,tleft) |
101 |
C*********************************************************************** |
102 |
C Purpose |
103 |
C ------- |
104 |
C Utility to Get Internal Alarm Information |
105 |
C |
106 |
C Input |
107 |
C ----- |
108 |
C tag ....... Character String Tagging Alarm Process |
109 |
C |
110 |
C Output |
111 |
C ------ |
112 |
C date ...... Begining Date for Alarm |
113 |
C time ...... Begining Time for Alarm |
114 |
C freq ...... Frequency Interval for Alarm |
115 |
C tleft ..... Time Remaining (seconds) before Alarm is TRUE |
116 |
C |
117 |
C*********************************************************************** |
118 |
|
119 |
implicit none |
120 |
character*(*) tag |
121 |
integer freq,date,time,tleft |
122 |
|
123 |
#ifdef ALLOW_USE_MPI |
124 |
#include "SIZE.h" |
125 |
#include "EEPARAMS.h" |
126 |
#include "EESUPPORT.h" |
127 |
#endif |
128 |
|
129 |
#include "chronos.h" |
130 |
|
131 |
#ifdef ALLOW_USE_MPI |
132 |
c MPI Utilities |
133 |
c ------------- |
134 |
#include "mpif.h" |
135 |
integer mpi_comm_model,ierror |
136 |
#endif |
137 |
|
138 |
logical set,alarm |
139 |
external alarm |
140 |
integer myid,n,nalarm,nsecf |
141 |
|
142 |
#ifdef ALLOW_USE_MPI |
143 |
call mpi_comm_rank ( mpi_comm_model,myid,ierror ) |
144 |
#else |
145 |
myid = 1 |
146 |
#endif |
147 |
|
148 |
set = .false. |
149 |
do n=1,ntags |
150 |
if(tag.eq.tags(n)) then |
151 |
freq = freqs(n) |
152 |
date = dates(n) |
153 |
time = times(n) |
154 |
|
155 |
if( alarm(tag) ) then |
156 |
tleft = 0 |
157 |
else |
158 |
call get_time (nymd,nhms) |
159 |
tleft = nsecf(freq) - nalarm(freq,nymd,nhms,date,time ) |
160 |
endif |
161 |
|
162 |
set = .true. |
163 |
endif |
164 |
enddo |
165 |
|
166 |
if(.not.set) then |
167 |
if( myid.eq.1 ) print *, 'Alarm has not been set for Tag: ',tag |
168 |
freq = 0 |
169 |
date = 0 |
170 |
time = 0 |
171 |
tleft = 0 |
172 |
endif |
173 |
|
174 |
return |
175 |
end |
176 |
|
177 |
function alarm (tag) |
178 |
implicit none |
179 |
character*(*) tag |
180 |
integer date,time |
181 |
logical alarm |
182 |
#include "chronos.h" |
183 |
|
184 |
integer n,modalarm,nalarm,freq,date0,time0 |
185 |
modalarm(freq,date0,time0) = nalarm (freq,date,time,date0,time0 ) |
186 |
|
187 |
call get_time (date,time) |
188 |
|
189 |
alarm = .false. |
190 |
do n=1,ntags |
191 |
if( tags(n).eq.tag ) then |
192 |
if( freqs(n).eq.0 ) then |
193 |
alarm = (dates(n).eq.date) .and. (times(n).eq.time) |
194 |
else |
195 |
alarm = ( date.gt.dates(n) .or. |
196 |
. (date.eq.dates(n) .and. time.ge.times(n)) ) .and. |
197 |
. modalarm( freqs(n),dates(n),times(n) ).eq.0 |
198 |
endif |
199 |
endif |
200 |
enddo |
201 |
|
202 |
return |
203 |
end |
204 |
|
205 |
subroutine set_time (date,time) |
206 |
implicit none |
207 |
integer date,time |
208 |
|
209 |
#ifdef ALLOW_USE_MPI |
210 |
#include "SIZE.h" |
211 |
#include "EEPARAMS.h" |
212 |
#include "EESUPPORT.h" |
213 |
#endif |
214 |
|
215 |
#include "chronos.h" |
216 |
|
217 |
#ifdef ALLOW_USE_MPI |
218 |
c MPI Utilities |
219 |
c ------------- |
220 |
#include "mpif.h" |
221 |
integer mpi_comm_model,ierror |
222 |
#endif |
223 |
integer myid |
224 |
|
225 |
#ifdef ALLOW_USE_MPI |
226 |
call mpi_comm_rank ( mpi_comm_model,myid,ierror ) |
227 |
#else |
228 |
myid = 1 |
229 |
#endif |
230 |
if( myid.eq.1 ) then |
231 |
print *, 'Setting Clock' |
232 |
print *, 'Date: ',date |
233 |
print *, 'Time: ',time |
234 |
endif |
235 |
|
236 |
nymd = date |
237 |
nhms = time |
238 |
return |
239 |
end |
240 |
|
241 |
subroutine get_time (date,time) |
242 |
implicit none |
243 |
integer date,time |
244 |
|
245 |
#include "chronos.h" |
246 |
|
247 |
date = nymd |
248 |
time = nhms |
249 |
return |
250 |
end |
251 |
|
252 |
function nsecf (nhms) |
253 |
C*********************************************************************** |
254 |
C Purpose |
255 |
C Converts NHMS format to Total Seconds |
256 |
C |
257 |
C*********************************************************************** |
258 |
implicit none |
259 |
integer nhms, nsecf |
260 |
nsecf = nhms/10000*3600 + mod(nhms,10000)/100*60 + mod(nhms,100) |
261 |
return |
262 |
end |
263 |
|
264 |
function nhmsf (nsec) |
265 |
C*********************************************************************** |
266 |
C Purpose |
267 |
C Converts Total Seconds to NHMS format |
268 |
C |
269 |
C*********************************************************************** |
270 |
implicit none |
271 |
integer nhmsf, nsec |
272 |
nhmsf = nsec/3600*10000 + mod(nsec,3600)/60*100 + mod(nsec,60) |
273 |
return |
274 |
end |
275 |
|
276 |
function nsecf2 (nhhmmss,nmmdd,nymd) |
277 |
C*********************************************************************** |
278 |
C Purpose |
279 |
C Computes the Total Number of seconds from NYMD using NHHMMSS & NMMDD |
280 |
C |
281 |
C Arguments Description |
282 |
C NHHMMSS IntervaL Frequency (HHMMSS) |
283 |
C NMMDD Interval Frequency (MMDD) |
284 |
C NYMD Current Date (YYMMDD) |
285 |
C |
286 |
C NOTE: |
287 |
C IF (NMMDD.ne.0), THEN HOUR FREQUENCY HH MUST BE < 24 |
288 |
C |
289 |
C*********************************************************************** |
290 |
implicit none |
291 |
|
292 |
integer nsecf2,nhhmmss,nmmdd,nymd |
293 |
|
294 |
INTEGER NSDAY, NCYCLE |
295 |
PARAMETER ( NSDAY = 86400 ) |
296 |
PARAMETER ( NCYCLE = 1461*24*3600 ) |
297 |
|
298 |
INTEGER YEAR, MONTH, DAY |
299 |
|
300 |
INTEGER MNDY(12,4) |
301 |
DATA MNDY /0,31,60,91,121,152,182,213,244,274,305,335,366, |
302 |
. 397,34*0 / |
303 |
|
304 |
integer nsecf,i,nsegm,nsegd,iday,iday2,nday |
305 |
|
306 |
C*********************************************************************** |
307 |
C* COMPUTE # OF SECONDS FROM NHHMMSS * |
308 |
C*********************************************************************** |
309 |
|
310 |
nsecf2 = nsecf( nhhmmss ) |
311 |
|
312 |
if( nmmdd.eq.0 ) return |
313 |
|
314 |
C*********************************************************************** |
315 |
C* COMPUTE # OF DAYS IN A 4-YEAR CYCLE * |
316 |
C*********************************************************************** |
317 |
|
318 |
DO I=15,48 |
319 |
MNDY(I,1) = MNDY(I-12,1) + 365 |
320 |
ENDDO |
321 |
|
322 |
C*********************************************************************** |
323 |
C* COMPUTE # OF SECONDS FROM NMMDD * |
324 |
C*********************************************************************** |
325 |
|
326 |
nsegm = nmmdd/100 |
327 |
nsegd = mod(nmmdd,100) |
328 |
|
329 |
YEAR = NYMD / 10000 |
330 |
MONTH = MOD(NYMD,10000) / 100 |
331 |
DAY = MOD(NYMD,100) |
332 |
|
333 |
IDAY = MNDY( MONTH ,MOD(YEAR ,4)+1 ) |
334 |
month = month + nsegm |
335 |
If( month.gt.12 ) then |
336 |
month = month - 12 |
337 |
year = year + 1 |
338 |
endif |
339 |
IDAY2 = MNDY( MONTH ,MOD(YEAR ,4)+1 ) |
340 |
|
341 |
nday = iday2-iday |
342 |
if(nday.lt.0) nday = nday + 1461 |
343 |
nday = nday + nsegd |
344 |
|
345 |
nsecf2 = nsecf2 + nday*nsday |
346 |
|
347 |
return |
348 |
end |
349 |
|
350 |
subroutine fixdate (nymd) |
351 |
implicit none |
352 |
integer nymd |
353 |
|
354 |
c Modify 6-digit YYMMDD for dates between 1950-2050 |
355 |
c ------------------------------------------------- |
356 |
if (nymd .lt. 500101) then |
357 |
nymd = 20000000 + nymd |
358 |
else if (nymd .le. 991231) then |
359 |
nymd = 19000000 + nymd |
360 |
endif |
361 |
|
362 |
return |
363 |
end |
364 |
|
365 |
subroutine interp_time ( nymd ,nhms , |
366 |
. nymd1,nhms1, nymd2,nhms2, fac1,fac2 ) |
367 |
C*********************************************************************** |
368 |
C |
369 |
C PURPOSE: |
370 |
C ======== |
371 |
C Compute interpolation factors, fac1 & fac2, to be used in the |
372 |
C calculation of the instantanious boundary conditions, ie: |
373 |
C |
374 |
C q(i,j) = fac1*q1(i,j) + fac2*q2(i,j) |
375 |
C where: |
376 |
C q(i,j) => Boundary Data valid at (nymd , nhms ) |
377 |
C q1(i,j) => Boundary Data centered at (nymd1 , nhms1) |
378 |
C q2(i,j) => Boundary Data centered at (nymd2 , nhms2) |
379 |
C |
380 |
C INPUT: |
381 |
C ====== |
382 |
C nymd : Date (yymmdd) of Current Timestep |
383 |
C nhms : Time (hhmmss) of Current Timestep |
384 |
C nymd1 : Date (yymmdd) of Boundary Data 1 |
385 |
C nhms1 : Time (hhmmss) of Boundary Data 1 |
386 |
C nymd2 : Date (yymmdd) of Boundary Data 2 |
387 |
C nhms2 : Time (hhmmss) of Boundary Data 2 |
388 |
C |
389 |
C OUTPUT: |
390 |
C ======= |
391 |
C fac1 : Interpolation factor for Boundary Data 1 |
392 |
C fac2 : Interpolation factor for Boundary Data 2 |
393 |
C |
394 |
C |
395 |
C*********************************************************************** |
396 |
implicit none |
397 |
|
398 |
integer nhms,nymd,nhms1,nymd1,nhms2,nymd2 |
399 |
_RL fac1,fac2 |
400 |
|
401 |
INTEGER YEAR , MONTH , DAY , SEC |
402 |
INTEGER YEAR1, MONTH1, DAY1, SEC1 |
403 |
INTEGER YEAR2, MONTH2, DAY2, SEC2 |
404 |
|
405 |
_RL time, time1, time2 |
406 |
|
407 |
INTEGER DAYSCY |
408 |
PARAMETER (DAYSCY = 365*4+1) |
409 |
|
410 |
INTEGER MNDY(12,4) |
411 |
|
412 |
LOGICAL FIRST |
413 |
DATA FIRST/.TRUE./ |
414 |
|
415 |
DATA MNDY /0,31,60,91,121,152,182,213,244,274,305,335,366, |
416 |
. 397,34*0 / |
417 |
|
418 |
integer i,nsecf |
419 |
|
420 |
C*********************************************************************** |
421 |
C* SET TIME BOUNDARIES * |
422 |
C*********************************************************************** |
423 |
|
424 |
YEAR = NYMD / 10000 |
425 |
MONTH = MOD(NYMD,10000) / 100 |
426 |
DAY = MOD(NYMD,100) |
427 |
SEC = NSECF(NHMS) |
428 |
|
429 |
YEAR1 = NYMD1 / 10000 |
430 |
MONTH1 = MOD(NYMD1,10000) / 100 |
431 |
DAY1 = MOD(NYMD1,100) |
432 |
SEC1 = NSECF(NHMS1) |
433 |
|
434 |
YEAR2 = NYMD2 / 10000 |
435 |
MONTH2 = MOD(NYMD2,10000) / 100 |
436 |
DAY2 = MOD(NYMD2,100) |
437 |
SEC2 = NSECF(NHMS2) |
438 |
|
439 |
C*********************************************************************** |
440 |
C* COMPUTE DAYS IN 4-YEAR CYCLE * |
441 |
C*********************************************************************** |
442 |
|
443 |
IF(FIRST) THEN |
444 |
DO I=15,48 |
445 |
MNDY(I,1) = MNDY(I-12,1) + 365 |
446 |
ENDDO |
447 |
FIRST=.FALSE. |
448 |
ENDIF |
449 |
|
450 |
C*********************************************************************** |
451 |
C* COMPUTE INTERPOLATION FACTORS * |
452 |
C*********************************************************************** |
453 |
|
454 |
time = DAY + MNDY(MONTH ,MOD(YEAR ,4)+1) + float(sec )/86400. |
455 |
time1 = DAY1 + MNDY(MONTH1,MOD(YEAR1,4)+1) + float(sec1)/86400. |
456 |
time2 = DAY2 + MNDY(MONTH2,MOD(YEAR2,4)+1) + float(sec2)/86400. |
457 |
|
458 |
if( time .lt.time1 ) time = time + dayscy |
459 |
if( time2.lt.time1 ) time2 = time2 + dayscy |
460 |
|
461 |
fac1 = (time2-time)/(time2-time1) |
462 |
fac2 = (time-time1)/(time2-time1) |
463 |
|
464 |
RETURN |
465 |
END |
466 |
|
467 |
subroutine tick (nymd,nhms,ndt) |
468 |
C*********************************************************************** |
469 |
C Purpose |
470 |
C Tick the Date (nymd) and Time (nhms) by NDT (seconds) |
471 |
C |
472 |
C*********************************************************************** |
473 |
implicit none |
474 |
|
475 |
integer nymd,nhms,ndt |
476 |
|
477 |
integer nsec,nsecf,incymd,nhmsf |
478 |
|
479 |
IF(NDT.NE.0) THEN |
480 |
NSEC = NSECF(NHMS) + NDT |
481 |
|
482 |
IF (NSEC.GT.86400) THEN |
483 |
DO WHILE (NSEC.GT.86400) |
484 |
NSEC = NSEC - 86400 |
485 |
NYMD = INCYMD (NYMD,1) |
486 |
ENDDO |
487 |
ENDIF |
488 |
|
489 |
IF (NSEC.EQ.86400) THEN |
490 |
NSEC = 0 |
491 |
NYMD = INCYMD (NYMD,1) |
492 |
ENDIF |
493 |
|
494 |
IF (NSEC.LT.00000) THEN |
495 |
DO WHILE (NSEC.LT.0) |
496 |
NSEC = 86400 + NSEC |
497 |
NYMD = INCYMD (NYMD,-1) |
498 |
ENDDO |
499 |
ENDIF |
500 |
|
501 |
NHMS = NHMSF (NSEC) |
502 |
ENDIF |
503 |
|
504 |
RETURN |
505 |
END |
506 |
|
507 |
subroutine tic_time (mymd,mhms,ndt) |
508 |
C*********************************************************************** |
509 |
C PURPOSE |
510 |
C Tick the Clock by NDT (seconds) |
511 |
C |
512 |
C*********************************************************************** |
513 |
implicit none |
514 |
#include "chronos.h" |
515 |
|
516 |
integer mymd,mhms,ndt |
517 |
|
518 |
integer nsec,nsecf,incymd,nhmsf |
519 |
|
520 |
IF(NDT.NE.0) THEN |
521 |
NSEC = NSECF(NHMS) + NDT |
522 |
|
523 |
IF (NSEC.GT.86400) THEN |
524 |
DO WHILE (NSEC.GT.86400) |
525 |
NSEC = NSEC - 86400 |
526 |
NYMD = INCYMD (NYMD,1) |
527 |
ENDDO |
528 |
ENDIF |
529 |
|
530 |
IF (NSEC.EQ.86400) THEN |
531 |
NSEC = 0 |
532 |
NYMD = INCYMD (NYMD,1) |
533 |
ENDIF |
534 |
|
535 |
IF (NSEC.LT.00000) THEN |
536 |
DO WHILE (NSEC.LT.0) |
537 |
NSEC = 86400 + NSEC |
538 |
NYMD = INCYMD (NYMD,-1) |
539 |
ENDDO |
540 |
ENDIF |
541 |
|
542 |
NHMS = NHMSF (NSEC) |
543 |
ENDIF |
544 |
|
545 |
c Pass Back Current Updated Time |
546 |
c ------------------------------ |
547 |
mymd = nymd |
548 |
mhms = nhms |
549 |
|
550 |
RETURN |
551 |
END |
552 |
|
553 |
FUNCTION NALARM (MHMS,NYMD,NHMS,NYMD0,NHMS0) |
554 |
C*********************************************************************** |
555 |
C PURPOSE |
556 |
C COMPUTES MODULO-FRACTION BETWEEN MHHS AND TOTAL TIME |
557 |
C USAGE |
558 |
C ARGUMENTS DESCRIPTION |
559 |
C MHMS INTERVAL FREQUENCY (HHMMSS) |
560 |
C NYMD CURRENT YYMMDD |
561 |
C NHMS CURRENT HHMMSS |
562 |
C NYMD0 BEGINNING YYMMDD |
563 |
C NHMS0 BEGINNING HHMMSS |
564 |
C |
565 |
C*********************************************************************** |
566 |
implicit none |
567 |
|
568 |
integer nalarm,MHMS,NYMD,NHMS,NYMD0,NHMS0 |
569 |
|
570 |
integer nsday, ncycle |
571 |
PARAMETER ( NSDAY = 86400 ) |
572 |
PARAMETER ( NCYCLE = 1461*24*3600 ) |
573 |
|
574 |
INTEGER YEAR, MONTH, DAY, SEC, YEAR0, MONTH0, DAY0, SEC0 |
575 |
|
576 |
integer MNDY(12,4) |
577 |
DATA MNDY /0,31,60,91,121,152,182,213,244,274,305,335,366, |
578 |
. 397,34*0 / |
579 |
|
580 |
integer i,nsecf,iday,iday0,nsec,nsec0,ntime |
581 |
|
582 |
C*********************************************************************** |
583 |
C* COMPUTE # OF DAYS IN A 4-YEAR CYCLE * |
584 |
C*********************************************************************** |
585 |
|
586 |
DO I=15,48 |
587 |
MNDY(I,1) = MNDY(I-12,1) + 365 |
588 |
ENDDO |
589 |
|
590 |
C*********************************************************************** |
591 |
C* SET CURRENT AND BEGINNING TIMES * |
592 |
C*********************************************************************** |
593 |
|
594 |
YEAR = NYMD / 10000 |
595 |
MONTH = MOD(NYMD,10000) / 100 |
596 |
DAY = MOD(NYMD,100) |
597 |
SEC = NSECF(NHMS) |
598 |
|
599 |
YEAR0 = NYMD0 / 10000 |
600 |
MONTH0 = MOD(NYMD0,10000) / 100 |
601 |
DAY0 = MOD(NYMD0,100) |
602 |
SEC0 = NSECF(NHMS0) |
603 |
|
604 |
C*********************************************************************** |
605 |
C* COMPUTE POSITIONS IN CYCLE FOR CURRENT AND BEGINNING TIMES * |
606 |
C*********************************************************************** |
607 |
|
608 |
IDAY = (DAY -1) + MNDY( MONTH ,MOD(YEAR ,4)+1 ) |
609 |
IDAY0 = (DAY0-1) + MNDY( MONTH0,MOD(YEAR0,4)+1 ) |
610 |
|
611 |
NSEC = IDAY *NSDAY + SEC |
612 |
NSEC0 = IDAY0*NSDAY + SEC0 |
613 |
|
614 |
NTIME = NSEC-NSEC0 |
615 |
IF (NTIME.LT.0 ) NTIME = NTIME + NCYCLE |
616 |
NALARM = NTIME |
617 |
IF ( MHMS.NE.0 ) NALARM = MOD( NALARM,NSECF(MHMS) ) |
618 |
|
619 |
RETURN |
620 |
END |
621 |
|
622 |
FUNCTION INCYMD (NYMD,M) |
623 |
C*********************************************************************** |
624 |
C PURPOSE |
625 |
C INCYMD: NYMD CHANGED BY ONE DAY |
626 |
C MODYMD: NYMD CONVERTED TO JULIAN DATE |
627 |
C DESCRIPTION OF PARAMETERS |
628 |
C NYMD CURRENT DATE IN YYMMDD FORMAT |
629 |
C M +/- 1 (DAY ADJUSTMENT) |
630 |
C |
631 |
C*********************************************************************** |
632 |
implicit none |
633 |
integer incymd,nymd,m |
634 |
|
635 |
integer ny,nm,nd,ny00,modymd |
636 |
|
637 |
INTEGER NDPM(12) |
638 |
DATA NDPM /31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/ |
639 |
LOGICAL LEAP |
640 |
DATA NY00 /1900 / |
641 |
LEAP(NY) = MOD(NY,4).EQ.0 .AND. (NY.NE.0 .OR. MOD(NY00,400).EQ.0) |
642 |
|
643 |
C*********************************************************************** |
644 |
C |
645 |
NY = NYMD / 10000 |
646 |
NM = MOD(NYMD,10000) / 100 |
647 |
ND = MOD(NYMD,100) + M |
648 |
|
649 |
IF (ND.EQ.0) THEN |
650 |
NM = NM - 1 |
651 |
IF (NM.EQ.0) THEN |
652 |
NM = 12 |
653 |
NY = NY - 1 |
654 |
ENDIF |
655 |
ND = NDPM(NM) |
656 |
IF (NM.EQ.2 .AND. LEAP(NY)) ND = 29 |
657 |
ENDIF |
658 |
|
659 |
IF (ND.EQ.29 .AND. NM.EQ.2 .AND. LEAP(NY)) GO TO 20 |
660 |
|
661 |
IF (ND.GT.NDPM(NM)) THEN |
662 |
ND = 1 |
663 |
NM = NM + 1 |
664 |
IF (NM.GT.12) THEN |
665 |
NM = 1 |
666 |
NY = NY + 1 |
667 |
ENDIF |
668 |
ENDIF |
669 |
|
670 |
20 CONTINUE |
671 |
INCYMD = NY*10000 + NM*100 + ND |
672 |
|
673 |
RETURN |
674 |
|
675 |
C*********************************************************************** |
676 |
C E N T R Y M O D Y M D |
677 |
C*********************************************************************** |
678 |
|
679 |
ENTRY MODYMD (NYMD) |
680 |
|
681 |
NY = NYMD / 10000 |
682 |
NM = MOD(NYMD,10000) / 100 |
683 |
ND = MOD(NYMD,100) |
684 |
|
685 |
40 CONTINUE |
686 |
IF (NM.LE.1) GO TO 60 |
687 |
NM = NM - 1 |
688 |
ND = ND + NDPM(NM) |
689 |
IF (NM.EQ.2 .AND. LEAP(NY)) ND = ND + 1 |
690 |
GO TO 40 |
691 |
|
692 |
60 CONTINUE |
693 |
MODYMD = ND |
694 |
|
695 |
RETURN |
696 |
END |
697 |
|
698 |
SUBROUTINE ASTRO ( NYMD,NHMS,ALAT,ALON,IRUN,COSZ,RA ) |
699 |
C*********************************************************************** |
700 |
C |
701 |
C INPUT: |
702 |
C ====== |
703 |
C NYMD : CURRENT YYMMDD |
704 |
C NHMS : CURRENT HHMMSS |
705 |
C ALAT(IRUN):LATITUDES IN DEGREES. |
706 |
C ALON(IRUN):LONGITUDES IN DEGREES. (0 = GREENWICH, + = EAST). |
707 |
C IRUN : # OF POINTS TO CALCULATE |
708 |
C |
709 |
C OUTPUT: |
710 |
C ======= |
711 |
C COSZ(IRUN) : COSINE OF ZENITH ANGLE. |
712 |
C RA : EARTH-SUN DISTANCE IN UNITS OF |
713 |
C THE ORBITS SEMI-MAJOR AXIS. |
714 |
C |
715 |
C NOTE: |
716 |
C ===== |
717 |
C THE INSOLATION AT THE TOP OF THE ATMOSPHERE IS: |
718 |
C |
719 |
C S(I) = (SOLAR CONSTANT)*(1/RA**2)*COSZ(I), |
720 |
C |
721 |
C WHERE: |
722 |
C RA AND COSZ(I) ARE THE TWO OUTPUTS OF THIS SUBROUTINE. |
723 |
C |
724 |
C*********************************************************************** |
725 |
|
726 |
implicit none |
727 |
|
728 |
c Input Variables |
729 |
c --------------- |
730 |
integer nymd, nhms, irun |
731 |
_RL cosz(irun), alat(irun), alon(irun), ra |
732 |
|
733 |
c Local Variables |
734 |
c --------------- |
735 |
integer year, day, sec, month, iday, idayp1 |
736 |
integer dayscy |
737 |
integer i,nsecf,k,km,kp |
738 |
|
739 |
_RL hc |
740 |
_RL pi, zero, one, two, six, dg2rd, yrlen, eqnx, ob, ecc, per |
741 |
_RL daylen, fac, thm, thp, thnow, zs, zc, sj, cj |
742 |
|
743 |
parameter ( pi = 3.1415926535898) |
744 |
parameter ( zero = 0.0 ) |
745 |
parameter ( one = 1.0 ) |
746 |
parameter ( two = 2.0 ) |
747 |
parameter ( six = 6.0 ) |
748 |
parameter ( dg2rd = pi/180. ) |
749 |
|
750 |
parameter ( yrlen = 365.25 ) |
751 |
parameter ( dayscy = 365*4+1 ) |
752 |
parameter ( eqnx = 80.9028) |
753 |
parameter ( ob = 23.45*dg2rd ) |
754 |
parameter ( ecc = 0.0167 ) |
755 |
parameter ( per = 102.0*dg2rd) |
756 |
parameter ( daylen = 86400.) |
757 |
|
758 |
_RL TH(DAYSCY),T0,T1,T2,T3,T4,FUN,Y,MNDY(12,4) |
759 |
|
760 |
LOGICAL FIRST |
761 |
DATA FIRST/.TRUE./ |
762 |
SAVE |
763 |
|
764 |
DATA MNDY /0,31,60,91,121,152,182,213,244,274,305,335,366, |
765 |
. 397,34*0 / |
766 |
|
767 |
FUN(Y) = (TWO*PI/((ONE-ECC**2)**1.5))*(ONE/YRLEN) |
768 |
. * (ONE - ECC*COS(Y-PER)) ** 2 |
769 |
|
770 |
C*********************************************************************** |
771 |
C* SET CURRENT TIME * |
772 |
C*********************************************************************** |
773 |
|
774 |
YEAR = NYMD / 10000 |
775 |
MONTH = MOD(NYMD,10000) / 100 |
776 |
DAY = MOD(NYMD,100) |
777 |
SEC = NSECF(NHMS) |
778 |
|
779 |
C*********************************************************************** |
780 |
C* COMPUTE DAY-ANGLES FOR 4-YEAR CYCLE * |
781 |
C*********************************************************************** |
782 |
|
783 |
IF(FIRST) THEN |
784 |
DO 100 I=15,48 |
785 |
MNDY(I,1) = MNDY(I-12,1) + 365 |
786 |
100 CONTINUE |
787 |
|
788 |
KM = INT(EQNX) + 1 |
789 |
FAC = KM-EQNX |
790 |
T0 = ZERO |
791 |
T1 = FUN(T0 )*FAC |
792 |
T2 = FUN(ZERO+T1/TWO)*FAC |
793 |
T3 = FUN(ZERO+T2/TWO)*FAC |
794 |
T4 = FUN(ZERO+T3 )*FAC |
795 |
TH(KM) = (T1 + TWO*(T2 + T3) + T4) / SIX |
796 |
|
797 |
DO 200 K=2,DAYSCY |
798 |
T1 = FUN(TH(KM) ) |
799 |
T2 = FUN(TH(KM)+T1/TWO) |
800 |
T3 = FUN(TH(KM)+T2/TWO) |
801 |
T4 = FUN(TH(KM)+T3 ) |
802 |
KP = MOD(KM,DAYSCY) + 1 |
803 |
TH(KP) = TH(KM) + (T1 + TWO*(T2 + T3) + T4) / SIX |
804 |
KM = KP |
805 |
200 CONTINUE |
806 |
|
807 |
FIRST=.FALSE. |
808 |
ENDIF |
809 |
|
810 |
C*********************************************************************** |
811 |
C* COMPUTE EARTH-SUN DISTANCE TO CURRENT SECOND * |
812 |
C*********************************************************************** |
813 |
|
814 |
IDAY = DAY + MNDY(MONTH,MOD(YEAR,4)+1) |
815 |
IDAYP1 = MOD( IDAY,DAYSCY) + 1 |
816 |
THM = MOD( TH(IDAY) ,TWO*PI) |
817 |
THP = MOD( TH(IDAYP1),TWO*PI) |
818 |
|
819 |
IF(THP.LT.THM) THP = THP + TWO*PI |
820 |
FAC = FLOAT(SEC)/DAYLEN |
821 |
THNOW = THM*(ONE-FAC) + THP*FAC |
822 |
|
823 |
ZS = SIN(THNOW) * SIN(OB) |
824 |
ZC = SQRT(ONE-ZS*ZS) |
825 |
RA = (1.-ECC*ECC) / ( ONE-ECC*COS(THNOW-PER) ) |
826 |
|
827 |
C*********************************************************************** |
828 |
C* COMPUTE COSINE OF THE ZENITH ANGLE * |
829 |
C*********************************************************************** |
830 |
|
831 |
FAC = FAC*TWO*PI + PI |
832 |
DO I = 1,IRUN |
833 |
|
834 |
HC = COS( FAC+ALON(I)*DG2RD ) |
835 |
SJ = SIN(ALAT(I)*DG2RD) |
836 |
CJ = SQRT(ONE-SJ*SJ) |
837 |
|
838 |
COSZ(I) = SJ*ZS + CJ*ZC*HC |
839 |
IF( COSZ(I).LT.ZERO ) COSZ(I) = ZERO |
840 |
ENDDO |
841 |
|
842 |
RETURN |
843 |
END |
844 |
|
845 |
subroutine time_bound(nymd,nhms,nymd1,nhms1,nymd2,nhms2,imnm,imnp) |
846 |
C*********************************************************************** |
847 |
C PURPOSE |
848 |
C Compute Date and Time boundaries. |
849 |
C |
850 |
C ARGUMENTS DESCRIPTION |
851 |
C nymd .... Current Date |
852 |
C nhms .... Current Time |
853 |
C nymd1 ... Previous Date Boundary |
854 |
C nhms1 ... Previous Time Boundary |
855 |
C nymd2 ... Subsequent Date Boundary |
856 |
C nhms2 ... Subsequent Time Boundary |
857 |
C |
858 |
C imnm .... Previous Time Index for Interpolation |
859 |
C imnp .... Subsequent Time Index for Interpolation |
860 |
C |
861 |
C*********************************************************************** |
862 |
|
863 |
implicit none |
864 |
integer nymd,nhms, nymd1,nhms1, nymd2,nhms2 |
865 |
|
866 |
c Local Variables |
867 |
c --------------- |
868 |
integer month,day,nyear,midmon1,midmon,midmon2 |
869 |
integer imnm,imnp |
870 |
INTEGER DAYS(14), daysm, days0, daysp |
871 |
DATA DAYS /31,31,28,31,30,31,30,31,31,30,31,30,31,31/ |
872 |
|
873 |
integer nmonf,ndayf,n |
874 |
NMONF(N) = MOD(N,10000)/100 |
875 |
NDAYF(N) = MOD(N,100) |
876 |
|
877 |
C********************************************************************* |
878 |
C**** Find Proper Month and Time Boundaries for Climatological Data ** |
879 |
C********************************************************************* |
880 |
|
881 |
MONTH = NMONF(NYMD) |
882 |
DAY = NDAYF(NYMD) |
883 |
|
884 |
daysm = days(month ) |
885 |
days0 = days(month+1) |
886 |
daysp = days(month+2) |
887 |
|
888 |
c Check for Leap Year |
889 |
c ------------------- |
890 |
nyear = nymd/10000 |
891 |
if( 4*(nyear/4).eq.nyear ) then |
892 |
if( month.eq.3 ) daysm = daysm+1 |
893 |
if( month.eq.2 ) days0 = days0+1 |
894 |
if( month.eq.1 ) daysp = daysp+1 |
895 |
endif |
896 |
|
897 |
MIDMON1 = daysm/2 + 1 |
898 |
MIDMON = days0/2 + 1 |
899 |
MIDMON2 = daysp/2 + 1 |
900 |
|
901 |
|
902 |
IF(DAY.LT.MIDMON) THEN |
903 |
imnm = month |
904 |
imnp = month + 1 |
905 |
nymd2 = (nymd/10000)*10000 + month*100 + midmon |
906 |
nhms2 = 000000 |
907 |
nymd1 = nymd2 |
908 |
nhms1 = nhms2 |
909 |
call tick ( nymd1,nhms1, -midmon *86400 ) |
910 |
call tick ( nymd1,nhms1,-(daysm-midmon1)*86400 ) |
911 |
ELSE |
912 |
IMNM = MONTH + 1 |
913 |
IMNP = MONTH + 2 |
914 |
nymd1 = (nymd/10000)*10000 + month*100 + midmon |
915 |
nhms1 = 000000 |
916 |
nymd2 = nymd1 |
917 |
nhms2 = nhms1 |
918 |
call tick ( nymd2,nhms2,(days0-midmon)*86400 ) |
919 |
call tick ( nymd2,nhms2, midmon2*86400 ) |
920 |
ENDIF |
921 |
|
922 |
c ------------------------------------------------------------- |
923 |
c Note: At this point, imnm & imnp range between 01-14, where |
924 |
c 01 -> Previous years December |
925 |
c 02-13 -> Current years January-December |
926 |
c 14 -> Next years January |
927 |
c ------------------------------------------------------------- |
928 |
|
929 |
imnm = imnm-1 |
930 |
imnp = imnp-1 |
931 |
|
932 |
if( imnm.eq.0 ) imnm = 12 |
933 |
if( imnp.eq.0 ) imnp = 12 |
934 |
if( imnm.eq.13 ) imnm = 1 |
935 |
if( imnp.eq.13 ) imnp = 1 |
936 |
|
937 |
return |
938 |
end |