!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| module glc_io !BOP ! !MODULE: glc_io ! !DESCRIPTION: ! Contains routines for specialized glc IO ! ! !REVISION HISTORY: ! ! !USES: use glc_time_management, only: iyear, imonth, iday, ihour, iminute, isecond, & runtype, cesm_date_stamp, elapsed_days, elapsed_days0 use glc_communicate, only: my_task, master_task use glimmer_ncdf, only: add_output, delete_output use glimmer_ncio, only: glimmer_nc_checkwrite, & glimmer_nc_createfile use glimmer_global, only: fname_length use glc_constants use glc_kinds_mod use esmf, only: ESMF_Clock use seq_timemgr_mod, only: seq_timemgr_EClockGetData use shr_sys_mod use shr_kind_mod, only: CL=>SHR_KIND_CL, IN=>SHR_KIND_IN use shr_file_mod, only: shr_file_getunit, shr_file_freeunit use netcdf implicit none private save ! !PUBLIC MEMBER FUNCTIONS: public :: glc_io_read_restart_time, & glc_io_write_history, & glc_io_write_restart !---------------------------------------------------------------------- ! ! module variables ! !---------------------------------------------------------------------- character(CL), public :: & history_vars ! Name of the CISM variables to be output in cesm ! history files !EOP !BOC !EOC !*********************************************************************** !*********************************************************************** contains !*********************************************************************** !BOP ! !IROUTINE: glc_io_read_restart_time ! !INTERFACE: subroutine glc_io_read_restart_time(nhour_glint, filename) use glc_files, only : ptr_filename implicit none integer(IN), intent(inout) :: nhour_glint character(fname_length), intent(inout) :: filename ! local variables character(fname_length) :: filename0 integer(IN) :: cesmYMD ! cesm model date integer(IN) :: cesmTOD ! cesm model sec integer(IN) :: glcYMD ! glc model date integer(IN) :: glcTOD ! glc model sec integer(IN) :: rst_elapsed_days ! integer(IN) :: ptr_unit ! unit for pointer file integer(IN) :: rst_unit ! unit for restart file integer(IN) :: status ! !----------------------------------------------------------------------- ! get restart filename from rpointer file ptr_unit = shr_file_getUnit() if (my_task == master_task) then open(ptr_unit,file=ptr_filename) read(ptr_unit,'(a)') filename0 filename = trim(filename0) close(ptr_unit) write(stdout,*) & 'glc_io_read_restart_time: using dumpfile for restart = ', filename call shr_sys_flush(stdout) endif !! call broadcast_scalar(filename, master_task) call shr_file_freeunit(ptr_unit) ! read time from the restart file, since glimmer needs this to initialize rst_unit = shr_file_getUnit() status = nf90_open(filename,0,rst_unit) call nc_errorhandle(__FILE__,__LINE__,status) status = nf90_get_att(rst_unit, NF90_GLOBAL, 'cesmYMD', cesmYMD) call nc_errorhandle(__FILE__,__LINE__,status) status = nf90_get_att(rst_unit, NF90_GLOBAL, 'cesmTOD', cesmTOD) call nc_errorhandle(__FILE__,__LINE__,status) status = nf90_get_att(rst_unit, NF90_GLOBAL, 'glcYMD', glcYMD) call nc_errorhandle(__FILE__,__LINE__,status) status = nf90_get_att(rst_unit, NF90_GLOBAL, 'glcTOD', glcTOD) call nc_errorhandle(__FILE__,__LINE__,status) status = nf90_get_att(rst_unit, NF90_GLOBAL, 'elapsed_days', rst_elapsed_days) call nc_errorhandle(__FILE__,__LINE__,status) status = nf90_close(rst_unit) call nc_errorhandle(__FILE__,__LINE__,status) ! calculate nhour_glint for return nhour_glint = rst_elapsed_days * 24 end subroutine glc_io_read_restart_time !*********************************************************************** !BOP ! !IROUTINE: glc_io_write_history ! !INTERFACE: subroutine glc_io_write_history(instance, EClock) use glint_type use glide_io use glint_io use glide_nc_custom, only: glide_nc_filldvars implicit none type(glint_instance), intent(inout) :: instance type(ESMF_Clock), intent(in) :: EClock ! local variables type(glimmer_nc_output), pointer :: oc => null() character(CL) :: filename integer(IN) :: cesmYMD ! cesm model date integer(IN) :: cesmTOD ! cesm model sec integer(IN) :: cesmYR ! cesm model year integer(IN) :: cesmMON ! cesm model month integer(IN) :: cesmDAY ! cesm model day integer(IN) :: glcYMD ! cism model date integer(IN) :: glcTOD ! cism model sec integer(IN) :: rst_elapsed_days ! integer(IN) :: ptr_unit ! unit for pointer file integer(IN) :: status ! !----------------------------------------------------------------------- ! figure out history filename call seq_timemgr_EClockGetData(EClock, curr_ymd=cesmYMD, curr_tod=cesmTOD, & curr_yr=cesmYR, curr_mon=cesmMON, curr_day=cesmDAY) filename = glc_filename(cesmYR, cesmMON, cesmDAY, cesmTOD, 'history') if (my_task == master_task) then write(stdout,*) & 'glc_io_write_history: calling dumpfile for history filename= ', filename call shr_sys_flush(stdout) endif allocate(oc) oc%freq = 1 oc%append = .false. oc%default_xtype = NF90_DOUBLE oc%nc%filename = '' oc%nc%filename = trim(filename) !jw oc%nc%vars = ' acab artm thk usurf uvel vvel uflx vflx temp ' oc%nc%vars = trim(history_vars) oc%nc%hotstart = .false. oc%nc%vars_copy = oc%nc%vars !jw TO DO: fill out the rest of the metadata !jw oc%metadata%title = !jw oc%metadata%institution = !jw oc%metadata%source = !jw oc%metadata%history = !jw oc%metadata%references = !jw oc%metadata%comment = ! create the output unit call glimmer_nc_createfile(oc, instance%model) call glide_io_create(oc, instance%model) call glint_io_create(oc, instance%model) ! write time to the file glcYMD = iyear*10000 + imonth*100 + iday glcTOD = ihour*3600 + iminute*60 + isecond status = nf90_put_att(oc%nc%id, NF90_GLOBAL, 'cesmYMD', cesmYMD) call nc_errorhandle(__FILE__,__LINE__,status) status = nf90_put_att(oc%nc%id, NF90_GLOBAL, 'cesmTOD', cesmTOD) call nc_errorhandle(__FILE__,__LINE__,status) status = nf90_put_att(oc%nc%id, NF90_GLOBAL, 'glcYMD', glcYMD) call nc_errorhandle(__FILE__,__LINE__,status) status = nf90_put_att(oc%nc%id, NF90_GLOBAL, 'glcTOD', glcTOD) call nc_errorhandle(__FILE__,__LINE__,status) rst_elapsed_days = elapsed_days - elapsed_days0 status = nf90_put_att(oc%nc%id, NF90_GLOBAL, 'elapsed_days', rst_elapsed_days) call nc_errorhandle(__FILE__,__LINE__,status) call glide_nc_filldvars(oc, instance%model) call glimmer_nc_checkwrite(oc, instance%model, forcewrite=.true., & time=instance%glide_time) call glide_io_write(oc, instance%model) call glint_io_write(oc, instance) status = nf90_close(oc%nc%id) call nc_errorhandle(__FILE__,__LINE__,status) oc => null() !jw TO DO: figure out why deallocate statement crashes the code !jw deallocate(oc) end subroutine glc_io_write_history !*********************************************************************** !BOP ! !IROUTINE: glc_io_write_restart ! !INTERFACE: subroutine glc_io_write_restart(instance, EClock) use glc_files, only : ptr_filename use glint_type use glide_io use glint_io use glide_nc_custom, only: glide_nc_filldvars implicit none type(glint_instance), intent(inout) :: instance type(ESMF_Clock), intent(in) :: EClock ! local variables type(glimmer_nc_output), pointer :: oc => null() character(CL) :: filename integer(IN) :: cesmYMD ! cesm model date integer(IN) :: cesmTOD ! cesm model sec integer(IN) :: cesmYR ! cesm model year integer(IN) :: cesmMON ! cesm model month integer(IN) :: cesmDAY ! cesm model day integer(IN) :: glcYMD ! cism model date integer(IN) :: glcTOD ! cism model sec integer(IN) :: rst_elapsed_days ! integer(IN) :: ptr_unit ! unit for pointer file integer(IN) :: status ! !----------------------------------------------------------------------- ! figure out restart filename call seq_timemgr_EClockGetData(EClock, curr_ymd=cesmYMD, curr_tod=cesmTOD, & curr_yr=cesmYR, curr_mon=cesmMON, curr_day=cesmDAY) filename = glc_filename(cesmYR, cesmMON, cesmDAY, cesmTOD, 'restart') if (my_task == master_task) then write(stdout,*) & 'glc_io_write_restart: calling dumpfile for restart filename= ', filename call shr_sys_flush(stdout) endif allocate(oc) oc%freq = 1 oc%append = .false. oc%default_xtype = NF90_DOUBLE oc%nc%filename = '' oc%nc%filename = trim(filename) oc%nc%vars = ' hot ' oc%nc%hotstart = .true. oc%nc%vars_copy = oc%nc%vars !jw TO DO: fill out the rest of the metadata !jw oc%metadata%title = !jw oc%metadata%institution = !jw oc%metadata%source = !jw oc%metadata%history = !jw oc%metadata%references = !jw oc%metadata%comment = ! create the output unit call glimmer_nc_createfile(oc, instance%model) call glide_io_create(oc, instance%model) call glint_io_create(oc, instance%model) ! write time to the file glcYMD = iyear*10000 + imonth*100 + iday glcTOD = ihour*3600 + iminute*60 + isecond status = nf90_put_att(oc%nc%id, NF90_GLOBAL, 'cesmYMD', cesmYMD) call nc_errorhandle(__FILE__,__LINE__,status) status = nf90_put_att(oc%nc%id, NF90_GLOBAL, 'cesmTOD', cesmTOD) call nc_errorhandle(__FILE__,__LINE__,status) status = nf90_put_att(oc%nc%id, NF90_GLOBAL, 'glcYMD', glcYMD) call nc_errorhandle(__FILE__,__LINE__,status) status = nf90_put_att(oc%nc%id, NF90_GLOBAL, 'glcTOD', glcTOD) call nc_errorhandle(__FILE__,__LINE__,status) rst_elapsed_days = elapsed_days - elapsed_days0 status = nf90_put_att(oc%nc%id, NF90_GLOBAL, 'elapsed_days', rst_elapsed_days) call nc_errorhandle(__FILE__,__LINE__,status) call glide_nc_filldvars(oc, instance%model) call glimmer_nc_checkwrite(oc, instance%model, forcewrite=.true., & time=instance%glide_time) call glide_io_write(oc, instance%model) call glint_io_write(oc, instance) status = nf90_close(oc%nc%id) call nc_errorhandle(__FILE__,__LINE__,status) oc => null() !jw TO DO: figure out why deallocate statement crashes the code !jw deallocate(oc) ! write pointer to restart file ptr_unit = shr_file_getUnit() if (my_task == master_task) then open(ptr_unit,file=ptr_filename) write(ptr_unit,'(a)') filename close(ptr_unit) endif call shr_file_freeunit(ptr_unit) end subroutine glc_io_write_restart !*********************************************************************** ! BOP ! ! !ROUTINE: glc_filename ! ! !INTERFACE: character(CL) function glc_filename( yr_spec, mon_spec, day_spec, sec_spec, file_type ) ! ! !DESCRIPTION: Create a filename from a filename specifier. Interpret filename specifier ! string with: ! %c for case ! %i for instance suffix ! %y for year ! %m for month ! %d for day ! %s for second ! %% for the "%" character ! If the filename specifier has spaces " ", they will be trimmed out ! of the resulting filename. ! ! !USES: use glc_time_management, only: runid use glc_ensemble , only: get_inst_suffix ! ! !INPUT/OUTPUT PARAMETERS: integer, intent(in) :: yr_spec ! Simulation year integer, intent(in) :: mon_spec ! Simulation month integer, intent(in) :: day_spec ! Simulation day integer, intent(in) :: sec_spec ! Seconds into current simulation day character(7), intent(in) :: file_type ! file type, either history or restart ! ! EOP ! integer :: i, n ! Loop variables integer :: year ! Simulation year integer :: month ! Simulation month integer :: day ! Simulation day integer :: ncsec ! Seconds into current simulation day character(CL) :: string ! Temporary character string character(CL) :: format ! Format character string character(CL) :: filename_spec ! cism filename specifier !--------------------------------------------------------------------------- ! Determine what the file tpye is and set the filename specifier accordingly !--------------------------------------------------------------------------- filename_spec = ' ' if (file_type.eq.'history') then filename_spec = '%c.cism%i.h.%y-%m-%d-%s' else if (file_type.eq.'restart') then filename_spec = '%c.cism%i.r.%y-%m-%d-%s' else call shr_sys_abort ('glc_filename: file_type specifier is invalid') endif !----------------------------------------------------------------- ! Determine year, month, day and sec to put in filename !----------------------------------------------------------------- if ( len_trim(filename_spec) == 0 )then call shr_sys_abort ('glc_filename: filename specifier is empty') end if if ( index(trim(filename_spec)," ") /= 0 )then call shr_sys_abort ('glc_filename: filename specifier can not contain a space:'//trim(filename_spec)) end if year = yr_spec month = mon_spec day = day_spec ncsec = sec_spec ! Go through each character in the filename specifier and interpret if special string i = 1 glc_filename = '' string = '' do while ( i <= len_trim(filename_spec) ) if ( filename_spec(i:i) == "%" )then i = i + 1 select case( filename_spec(i:i) ) case( 'c' ) ! runid string = trim(runid) case( 'i' ) ! instance suffix call get_inst_suffix(string) case( 'y' ) ! year if ( year > 99999 ) then format = '(i6.6)' else if ( year > 9999 ) then format = '(i5.5)' else format = '(i4.4)' end if write(string,format) year case( 'm' ) ! month write(string,'(i2.2)') month case( 'd' ) ! day write(string,'(i2.2)') day case( 's' ) ! second write(string,'(i5.5)') ncsec case( '%' ) ! percent character string = "%" case default call shr_sys_abort ('glc_filename: Invalid expansion character: '//filename_spec(i:i)) end select else n = index( filename_spec(i:), "%" ) if ( n == 0 ) n = len_trim( filename_spec(i:) ) + 1 if ( n == 0 ) exit string = filename_spec(i:n+i-2) i = n + i - 2 end if if ( len_trim(glc_filename) == 0 )then glc_filename = trim(string) else if ( (len_trim(glc_filename)+len_trim(string)) >= CL )then call shr_sys_abort ('glc_filename Resultant filename too long') end if glc_filename = trim(glc_filename) // trim(string) end if i = i + 1 end do if ( len_trim(glc_filename) == 0 )then call shr_sys_abort ('glc_filename: Resulting filename is empty') end if ! add ".nc" to tail end glc_filename = trim(glc_filename) // '.nc' end function glc_filename end module glc_io