psmile_io_utils.F90

Go to the documentation of this file.
00001 !-----------------------------------------------------------------------
00002 ! Copyright 2006-2010, SGI Germany, Munich, Germany.
00003 ! All rights reserved. Use is subject to OASIS4 license terms.
00004 !-----------------------------------------------------------------------
00005 !BOP
00006 ! !MODULE:
00007 Module psmile_io_utils
00008 ! !INTERFACE:
00009     Interface psmile_io_fileunit
00010           module procedure psmile_io_fileunit
00011         End Interface 
00012     Interface combine_with_date
00013           module procedure combine_with_date
00014         End Interface
00015     Interface extract_date
00016           module procedure extract_date
00017         End Interface
00018     Interface psmile_io_get_initial_date
00019           module procedure psmile_io_get_initial_date 
00020         End Interface
00021     Interface psmile_io_get_jobstart_date
00022           module procedure psmile_io_get_jobstart_date 
00023         End Interface
00024     Interface psmile_io_get_jobend_date
00025           module procedure psmile_io_get_jobend_date 
00026         End Interface
00027         Interface psmile_io_check_basename
00028           module procedure  psmile_io_check_basename 
00029         End Interface
00030 !        Interface indexi
00031 !          module procedure indexi
00032 !        End Interface
00033 ! !DESCRIPTION:
00034 !
00035 ! psmile_io_fileunit returns automatically an unused FORTRAN IO unit
00036 ! at the time when this routine is called.
00037 !
00038 ! combine_with_date combines a file anme <name>.nc with the
00039 ! extensions _in or _out followed with the suffix .<date in ISO format>.nc
00040 !
00041 ! extract_date returns the date from a string 
00042 ! 'SeCond siNce 2003-05-13 15:21:52'  as a PRISM_Time_Struct and optionally 
00043 ! as an integer array of 6 elements.
00044 !
00045 ! psmile_io_check_basename checks if a given file name contains a certain 
00046 ! suffix. If a suffix is present the filename is no basename and the
00047 ! result is .false.
00048 ! 
00049 ! psmile_io_get_jobstart_date returns the Gregorian date of the job start
00050 ! and optionally on an integer array
00051 !
00052 ! psmile_io_get_jobend_date returns the Gregorian date of the job end
00053 ! and optionally on an integer array
00054 !
00055 ! psmile_io_get_initial_date returns the Gregorian date of the experiment
00056 ! and optionally on an integer array
00057 !
00058 ! indexi performs a sort by ranking 
00059 !
00060 ! !REVISION HISTORY:
00061 ! 
00062 !   Date      Programmer    Description
00063 ! ----------  -----------   -----------
00064 ! 31.10.2003  vogelsang     File unit search
00065 ! 09.12.2003  vogelsang     added psmile_io_get_jobstart_date and
00066 !                            psmile_io_get_initial_date
00067 ! 27.08.2004  vogelsang     Added the procedure psmile_io_get_jobend_date
00068 !
00069 !EOP
00070 ! ---------------------------------------------------------------------
00071 contains
00072   subroutine psmile_io_fileunit(id_varid,id_unit,ierror)
00073   use psmile
00074   implicit none
00075   include 'prism.inc'
00076   integer,intent(in)    :: id_varid
00077   integer,intent(out)   :: id_unit
00078   integer,intent(out)   :: ierror
00079 
00080   logical :: l_open
00081   integer :: i,ierrp(2)
00082 
00083    Character(len=len_cvs_string), save :: mycvs_io_utils = 
00084    '$Id: psmile_io_utils.F90 2325 2010-04-21 15:00:07Z valcke $'
00085 #ifdef __PSMILE_WITH_IO
00086         l_open=.true.
00087         do i=7, PSMILE_IO_MAX_UNIT
00088            if(.not.any(i.eq.IO_res_units(1:PSMILE_IO_MAX_RESERVED_UNITS))) &
00089              inquire(unit=i,opened=l_open)
00090            if(.not.l_open) exit
00091         end do
00092 
00093         if(i== PSMILE_IO_MAX_UNIT+1)then
00094             ierror=PRISM_Error_Internal
00095             call psmile_error ( ierror, 'Cound not find free I/O unit!', &
00096                              ierrp, 0, __FILE__, __LINE__ )
00097 
00098         else
00099             id_unit = i
00100         endif
00101 #endif
00102 
00103         return
00104    end subroutine psmile_io_fileunit
00105 !
00106       subroutine combine_with_date(cd_in,cd_mode,id_initial_date,cd_on)
00107 !-------------------------------------------------------------
00108 !     use mod_kinds_model
00109       character(len=*),intent(in)::cd_in
00110       character(len=*),intent(in)::cd_mode
00111       character(len=*),intent(out)::cd_on
00112       integer,intent(in)::id_initial_date(:)
00113 !Local
00114       integer,parameter::il_nsuffixes=2
00115       integer::leni,leno,lens,lenb,il_i
00116       character(len=8)::suffixes(il_nsuffixes),suffix
00117       character(len=len(cd_in))::cl_basename
00118       character(len=4)::cl_year
00119       character(len=2)::cl_date(1:size(id_initial_date)-1)
00120      
00121       suffixes(1)='.nc'
00122       suffixes(2)='.grib'
00123      
00124       leni=len(trim(cd_in))
00125       leno=len(cd_on)
00126 
00127       cl_basename=''
00128      
00129       do il_i=1,il_nsuffixes
00130      
00131         suffix=suffixes(il_i)
00132         lens=len(trim(suffix))
00133 
00134         if(leni.gt.0.and.leni.lt.lens) then
00135           cl_basename(1:leni)=cd_in(1:leni)
00136           lenb=leni
00137           suffix='.nc'
00138         else if(cd_in(leni-lens+1:leni).eq.suffix(1:lens)) then
00139           cl_basename(1:leni-lens)=cd_in(1:leni-lens)
00140           lenb=leni-lens
00141           EXIT
00142         else
00143           cl_basename(1:leni)=cd_in(1:leni)
00144           lenb=leni
00145           suffix='.nc'
00146         endif
00147      
00148       enddo
00149      
00150      
00151       write(cl_year,'(i4.4)')id_initial_date(1)
00152 
00153       do il_i=2,size(id_initial_date)
00154 
00155         write(cl_date(il_i-1),'(i2.2)')id_initial_date(il_i)
00156 
00157       enddo
00158      
00159       if(trim(cd_mode) .eq. 'since' ) then
00160       cd_on=trim(cl_basename(1:lenb))//' '//trim(cd_mode)//' ' &
00161                                      //cl_year//'-'//cl_date(1)//'-' &
00162                                      //cl_date(2)//' ' &
00163                                      //cl_date(3)//':' &
00164                                      //cl_date(4)//':' &
00165                                      //cl_date(5)
00166       else
00167       cd_on=trim(cl_basename(1:lenb))//'_'//trim(cd_mode)//'.' &
00168                                      //cl_year//'-'//cl_date(1)//'-' &
00169                                      //cl_date(2)//'T' &
00170                                      //cl_date(3)//'_' &
00171                                      //cl_date(4)//'_' &
00172                                      //cl_date(5)//suffix
00173       endif
00174      
00175       return
00176       end subroutine combine_with_date
00177 !
00178       subroutine extract_date(time_unit,curdate,id_date)
00179       use PRISM_Constants
00180       use PSMILE
00181       implicit none
00182 !
00183 !     Arguments
00184 !
00185       character(len=*),intent(in)::time_unit
00186       Type(PRISM_Time_Struct),intent(inout):: curdate
00187       integer,dimension(6),intent(out),optional::id_date
00188 !
00189 !     Local variables
00190 !      
00191       integer::i,j,iloc,ierrp(2),ierror
00192       character(len=max_name)::tmp_unit
00193       character(len=1)::tmp_char
00194       
00195       
00196 !
00197 !Pack input string and convert to small letters
00198 !
00199       
00200       iloc=1
00201       do i=1,len(trim(time_unit))
00202       if(time_unit(i:i) .ne. ' ') then
00203       j=ichar(time_unit(i:i))
00204       if(j.ge.65 .and. j.le.90) then
00205       tmp_char=char(j+32)
00206       else
00207       tmp_char=char(j)
00208       endif
00209       tmp_unit(iloc:iloc)=tmp_char
00210       iloc=iloc+1
00211       endif
00212       enddo
00213 !
00214       if(len(trim(tmp_unit))-4.lt.1) then
00215          ierror = PRISM_Error_Internal
00216          call psmile_error ( ierror, 'Invalid unit of time axis!', &
00217                              ierrp, 0, __FILE__, __LINE__ )
00218       endif
00219       
00220 !
00221 ! Search for the string 'since'
00222 !
00223       do i=1,len(trim(tmp_unit))-4
00224       if(tmp_unit(i:i+4).eq.'since') exit
00225       enddo
00226 
00227       if(i.eq.len(trim(tmp_unit))-4) then
00228          ierror = PRISM_Error_Internal
00229          call psmile_error ( ierror, 'Time axis has no time origin!', &
00230                              ierrp, 0, __FILE__, __LINE__ )
00231       endif
00232       
00233 !
00234 ! The date starts here
00235 !
00236       i=i+5
00237       
00238       read(tmp_unit(i:i+3),'(i4)')curdate%year
00239       
00240 !
00241 ! Shift to the next position skipping separator
00242 !
00243       i=i+5
00244       
00245       read(tmp_unit(i:i+1),'(i2)')curdate%month
00246       
00247 !
00248 ! Shift to the next position skipping separator
00249 !
00250       i=i+3
00251       
00252       read(tmp_unit(i:i+3),'(i2)')curdate%day
00253       
00254 !
00255 ! Shift to the next position .
00256 !
00257       i=i+2
00258       
00259 !
00260 ! Separator between day and hour ?
00261 !
00262       if(ichar(tmp_unit(i:i)).lt.48 .or. ichar(tmp_unit(i:i)).gt.57) i=i+1
00263 !
00264       read(tmp_unit(i:i+1),'(i2)')curdate%hour
00265 !
00266 ! Shift to the next position skipping separator
00267 !
00268       i=i+3
00269       read(tmp_unit(i:i+1),'(i2)')curdate%minute
00270 !
00271 ! Shift to the next position skipping separator
00272 !
00273       i=i+3
00274       read(tmp_unit(i:i+1),'(i2)') j
00275       curdate%second=dble(j)
00276       
00277       if(present(id_date)) then
00278                 id_date(1)=curdate%year
00279                 id_date(2)=curdate%month
00280                 id_date(3)=curdate%day
00281                 id_date(4)=curdate%hour
00282                 id_date(5)=curdate%minute
00283                 id_date(6)=curdate%second
00284       endif
00285       
00286       end subroutine extract_date
00287 
00288 
00289       subroutine psmile_io_get_jobstart_date(id_jobstart_date,id_date,ierror)
00290       USE PRISM, only : PRISM_Jobstart_date
00291       USE PRISM_Constants
00292       USE PSMILe
00293       USE prism_calendar
00294       implicit none
00295 
00296       integer,intent(out) :: ierror
00297       Type(PRISM_Time_Struct),intent(out) :: id_jobstart_date
00298       integer,intent(out),optional:: id_date(:)
00299 !Local
00300 !RV Warning: Workarounad
00301 !      Type(PRISM_Time_Struct) :: prism_jobstart_date
00302 
00303       ierror=0
00304 !RV, Workaround
00305 !      prism_jobstart_date%year=0
00306 !      prism_jobstart_date%month=0
00307 !      prism_jobstart_date%day=0
00308 !      prism_jobstart_date%hour=0
00309 !      prism_jobstart_date%minute=0
00310 !      prism_jobstart_date%second=0
00311       id_jobstart_date= PRISM_jobstart_date
00312 #ifdef VERBOSE
00313       print*,trim(ch_id),' : psmile_io_get_jobstart_date: date',id_jobstart_date
00314 #endif
00315       if(present(id_date))then
00316           id_date(1)=id_jobstart_date%year
00317           id_date(2)=id_jobstart_date%month
00318           id_date(3)=id_jobstart_date%day
00319           id_date(4)=id_jobstart_date%hour
00320           id_date(5)=id_jobstart_date%minute
00321           id_date(6)=id_jobstart_date%second
00322       endif
00323 #ifdef VERBOSE
00324       print*,trim(ch_id),' : psmile_io_get_jobstart_date: end'
00325       call psmile_flushstd
00326 #endif
00327       return
00328       end subroutine psmile_io_get_jobstart_date
00329 
00330       subroutine psmile_io_get_jobend_date(id_jobend_date,id_date,ierror)
00331       USE PRISM, only : PRISM_jobend_date
00332       USE PRISM_Constants
00333       USE PSMILe
00334       USE prism_calendar
00335       implicit none
00336 
00337       integer,intent(out) :: ierror
00338       Type(PRISM_Time_Struct),intent(out) :: id_jobend_date
00339       integer,intent(out),optional:: id_date(:)
00340 !Local
00341 !RV Warning: Workarounad
00342 !      Type(PRISM_Time_Struct) :: prism_jobend_date
00343 
00344       ierror=0
00345 !RV, Workaround
00346 !      prism_jobend_date%year=0
00347 !      prism_jobend_date%month=0
00348 !      prism_jobend_date%day=0
00349 !      prism_jobend_date%hour=0
00350 !      prism_jobend_date%minute=0
00351 !      prism_jobend_date%second=0
00352       id_jobend_date= PRISM_jobend_date
00353 #ifdef VERBOSE
00354       print*,trim(ch_id),' : psmile_io_get_jobend_date: date',id_jobend_date
00355       call psmile_flushstd
00356 #endif
00357       if(present(id_date))then
00358           id_date(1)=id_jobend_date%year
00359           id_date(2)=id_jobend_date%month
00360           id_date(3)=id_jobend_date%day
00361           id_date(4)=id_jobend_date%hour
00362           id_date(5)=id_jobend_date%minute
00363           id_date(6)=id_jobend_date%second
00364       endif
00365 #ifdef VERBOSE
00366       print*,trim(ch_id),' : psmile_io_get_jobend_date: end'
00367       call psmile_flushstd
00368 #endif
00369       return
00370       end subroutine psmile_io_get_jobend_date
00371 
00372       subroutine psmile_io_get_initial_date(id_initial_date,id_date,ierror)
00373       USE PRISM_Constants
00374       USE PSMILe
00375       USE prism_calendar
00376       implicit none
00377 
00378       integer,intent(out) :: ierror
00379       Type(PRISM_Time_Struct),intent(out) :: id_initial_date
00380       integer,intent(out),optional:: id_date(:)
00381 
00382       ierror=0
00383 !      id_initial_date= PRISM_initial_date
00384       call psmile_get_initial_date(id_initial_date,ierror)
00385       if(present(id_date))then
00386           id_date(1)=id_initial_date%year
00387           id_date(2)=id_initial_date%month
00388           id_date(3)=id_initial_date%day
00389           id_date(4)=id_initial_date%hour
00390           id_date(5)=id_initial_date%minute
00391           id_date(6)=id_initial_date%second
00392       endif
00393 #ifdef VERBOSE
00394       print*,trim(ch_id),' : psmile_io_get_jobstart_date: end'
00395       call psmile_flushstd
00396 #endif
00397       return
00398       end subroutine psmile_io_get_initial_date
00399 
00400       subroutine psmile_io_check_basename(cd_filename,cd_suffix &
00401                                          ,ld_base,id_error)
00402       implicit none
00403       character(len=*),intent(in)         :: cd_filename
00404       character(len=*),intent(in)         :: cd_suffix
00405       logical,intent(out)                 :: ld_base
00406       integer,intent(out)                 :: id_error
00407 
00408 !Local variables
00409       integer                             :: il_flsuffl,il_flnamel
00410 
00411       id_error=0
00412 
00413       ld_base=.TRUE.
00414       il_flnamel=len(trim(cd_filename))
00415       il_flsuffl=len(trim(cd_suffix))
00416 
00417       if(il_flnamel.lt.il_flsuffl) return
00418 
00419       if(cd_filename(il_flnamel-il_flsuffl+1:il_flnamel).eq.trim(cd_suffix)) &
00420         ld_base=.false.
00421 
00422       end subroutine psmile_io_check_basename
00423 
00424       
00425        subroutine indexi(n,arr,indx)
00426 !---------------------------------------------------------------------
00427 ! Generates a list indx which sorts arr in ascending order.
00428 ! This is called sorting by indexing.
00429 ! Code taken from 'Numerical Recipes'
00430 !---------------------------------------------------------------------
00431       INTEGER,intent(in):: n
00432       INTEGER,intent(out)::indx(*)
00433       integer,intent(in):: arr(*)
00434 !Local
00435       integer,PARAMETER:: M=7,NSTACK=128
00436       INTEGER:: i,indxt,ir,itemp,j,jstack,k,l,istack(NSTACK)
00437       integer:: a
00438 
00439       do 11 j=1,n
00440         indx(j)=j
00441 11    continue
00442       jstack=0
00443       l=1
00444       ir=n
00445 1     if(ir-l.lt.M)then
00446         do 13 j=l+1,ir
00447           indxt=indx(j)
00448           a=arr(indxt)
00449           do 12 i=j-1,1,-1
00450             if(arr(indx(i)).le.a)goto 2
00451             indx(i+1)=indx(i)
00452 12        continue
00453           i=0
00454 2         indx(i+1)=indxt
00455 13      continue
00456         if(jstack.eq.0)return
00457         ir=istack(jstack)
00458         l=istack(jstack-1)
00459         jstack=jstack-2
00460       else
00461         k=(l+ir)/2
00462         itemp=indx(k)
00463         indx(k)=indx(l+1)
00464         indx(l+1)=itemp
00465         if(arr(indx(l+1)).gt.arr(indx(ir)))then
00466           itemp=indx(l+1)
00467           indx(l+1)=indx(ir)
00468           indx(ir)=itemp
00469         endif
00470         if(arr(indx(l)).gt.arr(indx(ir)))then
00471           itemp=indx(l)
00472           indx(l)=indx(ir)
00473           indx(ir)=itemp
00474         endif
00475         if(arr(indx(l+1)).gt.arr(indx(l)))then
00476           itemp=indx(l+1)
00477           indx(l+1)=indx(l)
00478           indx(l)=itemp
00479         endif
00480         i=l+1
00481         j=ir
00482         indxt=indx(l)
00483         a=arr(indxt)
00484 3       continue
00485           i=i+1
00486         if(arr(indx(i)).lt.a)goto 3
00487 4       continue
00488           j=j-1
00489         if(arr(indx(j)).gt.a)goto 4
00490         if(j.lt.i)goto 5
00491         itemp=indx(i)
00492         indx(i)=indx(j)
00493         indx(j)=itemp
00494         goto 3
00495 5       indx(l)=indx(j)
00496         indx(j)=indxt
00497         jstack=jstack+2
00498         if(jstack.gt.NSTACK)pause 'NSTACK too small in indexx'
00499         if(ir-i+1.ge.j-l)then
00500           istack(jstack)=ir
00501           istack(jstack-1)=i
00502           ir=j-1
00503         else
00504           istack(jstack)=j-1
00505           istack(jstack-1)=l
00506           l=i
00507         endif
00508       endif
00509       goto 1
00510       END subroutine indexi
00511 
00512 
00513 End Module psmile_io_utils
00514 

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1