c $Header: /u/gcmpack/MITgcm/pkg/exf/exf_getffieldrec.F,v 1.14 2005/05/31 18:03:51 adcroft Exp $ #include "EXF_OPTIONS.h" subroutine EXF_GETFFIELDREC( I fldstartdate, fldperiod, I fldstartdate1, fldstartdate2, I usefldyearlyfields, O fac, O first, O changed, O count0, O count1, O yp, O yf, I mytime, I myiter, I mythid & ) c ================================================================== c SUBROUTINE exf_GetFFieldRec c ================================================================== c c o Get flags, counters, and the linear interpolation factor for a c given field. c c started: Christian Eckert eckert@mit.edu 30-Jun-1999 c c changed: Christian Eckert eckert@mit.edu 14-Jan-2000 c - Restructured the code in order to create a package c for the MITgcmUV. c c Christian Eckert eckert@mit.edu 12-Feb-2000 c - Changed Routine names (package prefix: exf_) c c Curtis Heisey cheisey@mit.edu 19-Dec-2002 c - added "repeatPeriod" for cycling of forcing datasets c c menemenlis@jpl.nasa.gov c 27-Dec-2002 bug fix for verification/global_with_exf c 8-Oct-2003 speed-up computations for long integration interval c c ================================================================== c SUBROUTINE exf_GetFFieldRec c ================================================================== implicit none c == global variables == c cal: modelstart, modelstep #include "EEPARAMS.h" #include "cal.h" #include "exf_param.h" c == routine arguments == _RL fldstartdate _RL fldperiod integer fldstartdate1 integer fldstartdate2 logical usefldyearlyfields _RL fac logical first logical changed integer count0 integer count1 _RL mytime integer myiter integer mythid c == local variables == integer mydate(4) integer previousdate(4) integer nextperiod(4) integer difftime(4) integer fldcount _RL fldsecs _RL fldsectot _RL fldsecs0 _RL fldsecs1 _RL prevfldsecs integer prevfldcount integer iprint integer date_array(4) integer startinyear(4) integer yi,yf,yp,yn integer mi,mf,mp,mn integer di,df,dp,dn integer si,sf,sp,sn integer li,lf,lp,ln integer wi,wf,wp,wn integer nextiter _RL nexttime #ifdef EXF_VERBOSE character*(max_len_mbuf) msgbuf #endif c == end of interface == c Determine offset in seconds from beginning of input data c to current date. c This is very slow for a long integration interval. c call cal_GetDate( myiter, mytime, mydate, mythid ) c call cal_TimePassed( fldstartdate, mydate, difftime, mythid ) c call cal_ToSeconds( difftime, fldsecs, mythid ) fldsecs = mytime - fldstartdate c Variables needed to set switches for reading new records. first = ((mytime - modelstart) .lt. 0.5*modelstep) if ( .not. first ) then c This is very slow for a long integration interval. c call cal_GetDate(myiter-1,mytime-modelstep,previousdate,mythid) c call cal_TimePassed(fldstartdate,previousdate,difftime,mythid ) c call cal_ToSeconds( difftime, prevfldsecs, mythid ) prevfldsecs = fldsecs - modelstep else prevfldsecs = 0 endif c Determine the flux records just before and after mycurrentdate. if (repeatPeriod.eq.0.) then if ( fldsecs .lt. 0 ) then print *, 'flux data not available for this date' STOP 'ABNORMAL END: S/R EXF_GETFFIELDREC' endif count0 = int((fldsecs+0.5)/fldperiod) + 1 count1 = count0 + 1 prevfldcount= int((prevfldsecs+0.5)/fldperiod) + 1 fldsecs = fldsecs - int((fldsecs+0.5)/fldperiod)*fldperiod elseif (repeatPeriod.gt.0.) then c If using repeating data (e.g. monthly means) then make c fldsecs cycle around. do while ( fldsecs .lt. 0 ) fldsecs = fldsecs + repeatPeriod enddo fldsecs0 = mod(fldsecs,repeatPeriod) count0 = int((fldsecs0+0.5)/fldperiod) + 1 fldsecs1 = mod(fldsecs+fldperiod,repeatPeriod) count1 = int((fldsecs1+0.5)/fldperiod) + 1 do while ( prevfldsecs .lt. 0 ) prevfldsecs = prevfldsecs + repeatPeriod enddo prevfldsecs = mod(prevfldsecs,repeatPeriod) prevfldcount= int((prevfldsecs+0.5)/fldperiod) + 1 fldsecs = fldsecs0-int((fldsecs0+0.5)/fldperiod)*fldperiod else print *, 'repeatPeriod must be positive' STOP 'ABNORMAL END: S/R EXF_GETFFIELDREC' endif c Weight belonging to irec for linear interpolation purposes. fac = 1. - fldsecs/fldperiod c Set switches for reading new records. if ( first) then changed = .false. else if (count0 .ne. prevfldcount) then changed = .true. else changed = .false. endif endif c --------------------------------------------------------------------- c --------------------------------------------------------------------- if (usefldyearlyfields) then if (repeatPeriod.NE.0.) then print *, 'Use of usefldyearlyfields AND repeatPeriod', & 'not implemented' STOP 'ABNORMAL END: S/R EXF_GETFFIELDREC' endif cph( cph-exf-print iprint = yp cph) c overwrite count0/1 indices by those w.r.t. yearly files c fac, first, changed remain valid call CAL_FULLDATE( fldstartdate1, fldstartdate2, & date_array, mythid ) call CAL_CONVDATE( date_array,yi,mi,di,si,li,wi,mythid ) call CAL_GETDATE( myiter, mytime, mydate, mythid ) call CAL_CONVDATE( mydate,yf,mf,df,sf,lf,wf,mythid ) if ( yf .EQ. yi ) then startinyear(1) = date_array(1) else if ( mf.EQ.1 .AND. df.EQ.1 .AND. & mydate(2) .LT. date_array(2) ) then if ( (yf-1) .EQ. yi ) then startinyear(1) = date_array(1) else startinyear(1) = (yf-1)*10000 + 100 + 1 endif else startinyear(1) = yf*10000 + 100 + 1 yi = yf if ( mf.EQ.1 .AND. df.EQ.1 .AND. & mydate(2) .EQ. date_array(2) ) then first = .TRUE. endif endif startinyear(2) = date_array(2) startinyear(3) = date_array(3) startinyear(4) = date_array(4) cph-exf-print if (iprint.EQ.3000) then cph-exf-print print *, 'ph-exf startin ', startinyear(1), startinyear(2) cph-exf-print print *, 'ph-exf mydate ', mydate(1), mydate(2) cph-exf-print endif call CAL_TIMEPASSED( startinyear, mydate, difftime, mythid ) call CAL_TOSECONDS( difftime, fldsectot, mythid ) fldsecs = int(fldsectot/fldperiod)*fldperiod fldcount = int(fldsecs/fldperiod) + 1 if ( first) then changed = .false. yp = yf else call CAL_GETDATE( myiter-1, mytime-modelstep, & previousdate, mythid ) call CAL_CONVDATE( previousdate,yp,mp,dp,sp,lp,wp,mythid ) if ( yp .NE. yf ) then startinyear(1) = yp*10000 + 100 + 1 startinyear(2) = date_array(2) startinyear(3) = previousdate(3) startinyear(4) = date_array(4) endif call CAL_TIMEPASSED( startinyear, previousdate, difftime, & mythid ) call CAL_TOSECONDS( difftime, prevfldsecs, mythid ) prevfldsecs = int(prevfldsecs/fldperiod)*fldperiod prevfldcount = int(prevfldsecs/fldperiod) + 1 if (fldcount .ne. prevfldcount) then changed = .true. else changed = .false. endif endif count0 = fldcount count1 = fldcount + 1 nexttime = mytime - (fldsectot-fldsecs) + fldperiod nextiter = INT(nexttime/modelstep +0.0001) cph-exf-print if (iprint.EQ.3000) then cph-exf-print print *, 'ph-exf fldsec ', fldsectot, fldsecs cph-exf-print print *, 'ph-exf next ', nexttime, nexttime-mytime, cph-exf-print & INT((nexttime-mytime)/modelstep) cph-exf-print endif call CAL_GETDATE( & nextiter, nexttime, nextperiod, mythid) call CAL_CONVDATE( nextperiod,yn,mn,dn,sn,ln,wn,mythid ) cph-exf-print if (iprint.EQ.3000) print *, 'ph-exf nextperiod ', cph-exf-print & nextiter, nextperiod(1), nextperiod(2) if ( yn.GT.yi ) then count1 = 1 yf = yn endif endif cph-exf-print if (iprint.EQ.3000) then cph-exf-print print *, 'ph-exf-rec yp, yf, yn ', cph-exf-print & yp, yf, yn cph-exf-print print *, 'ph-exf-rec myiter, c0, c1 ', cph-exf-print & myiter, count0, count1, changed cph-exf-print endif c --------------------------------------------------------------------- c --------------------------------------------------------------------- #ifdef EXF_VERBOSE c Do some printing for the protocol. _BEGIN_MASTER( mythid ) write(msgbuf,'(a)') ' exf_GetFFieldsRec:' call PRINT_MESSAGE( msgbuf, standardmessageunit, & SQUEEZE_RIGHT , mythid) write(msgbuf,'(a,2x,l2,2x,l2,2x,D15.8)') & ' exf_GetFFieldsRec: first, changed, fac:', & first, changed, fac call PRINT_MESSAGE( msgbuf, standardmessageunit, & SQUEEZE_RIGHT , mythid) write(msgbuf,'(a,3(1x,i6))') & ' exf_GetFFieldsRec: myiter, count0, count1:', & myiter, count0, count1 call PRINT_MESSAGE( msgbuf, standardmessageunit, & SQUEEZE_RIGHT , mythid) write(msgbuf,'(a)') ' exf_GetFFieldsRec:' call PRINT_MESSAGE( msgbuf, standardmessageunit, & SQUEEZE_RIGHT , mythid) _END_MASTER( mythid ) #endif end