From 2dc03c1ca1acd8a61a5ac89448cc96897cf092c7 Mon Sep 17 00:00:00 2001 From: bensonr <6594772+bensonr@users.noreply.github.com> Date: Wed, 25 Aug 2021 09:19:23 -0400 Subject: [PATCH] Updates to use FMS 2021.03 (#374) * io/FV3GFS_io.F90 updated to use fms2_io * atmos_model.F90 and ccpp/data/GFS_typefs.F90 updates to input_nml_file handling * atmos_cubed_sphere submodule updated --- CMakeLists.txt | 2 + atmos_cubed_sphere | 2 +- atmos_model.F90 | 2 + ccpp/data/GFS_typedefs.F90 | 14 +- io/FV3GFS_io.F90 | 688 +++++++++++++++++++++++++------------ 5 files changed, 484 insertions(+), 224 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ea4109cd5..4766a17d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,8 @@ list(APPEND _fv3dycore_defs_private SPMD GFS_TYPES USE_GFSL63 MOIST_CAPPA + INTERNAL_FILE_NML + ENABLE_QUAD_PRECISION USE_COND) if(MULTI_GASES) diff --git a/atmos_cubed_sphere b/atmos_cubed_sphere index 3a0d35ad3..bdb078ade 160000 --- a/atmos_cubed_sphere +++ b/atmos_cubed_sphere @@ -1 +1 @@ -Subproject commit 3a0d35ad3efca351d5b1efccfad58eecf8147f2c +Subproject commit bdb078ade1e9f81755513d6dbb51b3f40fccaa41 diff --git a/atmos_model.F90 b/atmos_model.F90 index 0730a886a..0425b5a03 100644 --- a/atmos_model.F90 +++ b/atmos_model.F90 @@ -650,6 +650,8 @@ subroutine atmos_model_init (Atmos, Time_init, Time, Time_step) Init_parm%hydrostatic = Atm(mygrid)%flagstruct%hydrostatic #ifdef INTERNAL_FILE_NML + ! allocate required to work around GNU compiler bug 100886 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100886 + allocate(Init_parm%input_nml_file, mold=input_nml_file) Init_parm%input_nml_file => input_nml_file Init_parm%fn_nml='using internal file' #else diff --git a/ccpp/data/GFS_typedefs.F90 b/ccpp/data/GFS_typedefs.F90 index 9bb68da10..17ca800cd 100644 --- a/ccpp/data/GFS_typedefs.F90 +++ b/ccpp/data/GFS_typedefs.F90 @@ -148,9 +148,9 @@ module GFS_typedefs character(len=32), pointer :: tracer_names(:) !< tracers names to dereference tracer id integer, pointer :: tracer_types(:) !< tracers types: 0=generic, 1=chem,prog, 2=chem,diag character(len=64) :: fn_nml !< namelist filename - character(len=256), pointer :: input_nml_file(:) !< character string containing full namelist - !< for use with internal file reads - end type GFS_init_type + character(len=:), pointer, dimension(:) :: input_nml_file => null() !< character string containing full namelist + !< for use with internal file reads + end type GFS_init_type !---------------------------------------------------------------- @@ -586,8 +586,8 @@ module GFS_typedefs integer :: nthreads !< OpenMP threads available for physics integer :: nlunit !< unit for namelist character(len=64) :: fn_nml !< namelist filename for surface data cycling - character(len=256), pointer :: input_nml_file(:) !< character string containing full namelist - !< for use with internal file reads + character(len=:), pointer, dimension(:) :: input_nml_file => null() !< character string containing full namelist + !< for use with internal file reads integer :: input_nml_file_length !< length (number of lines) in namelist for internal reads integer :: logunit real(kind=kind_phys) :: fhzero !< hours between clearing of diagnostic buckets @@ -3086,7 +3086,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & integer, intent(in) :: nwat character(len=32), intent(in) :: tracer_names(:) integer, intent(in) :: tracer_types(:) - character(len=256), intent(in), pointer :: input_nml_file(:) + character(len=:), intent(in), dimension(:), pointer :: input_nml_file integer, intent(in) :: blksz(:) real(kind=kind_phys), dimension(:), intent(in) :: ak real(kind=kind_phys), dimension(:), intent(in) :: bk @@ -3723,6 +3723,8 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & !--- read in the namelist #ifdef INTERNAL_FILE_NML + ! allocate required to work around GNU compiler bug 100886 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100886 + allocate(Model%input_nml_file, mold=input_nml_file) Model%input_nml_file => input_nml_file read(Model%input_nml_file, nml=gfs_physics_nml) ! Set length (number of lines) in namelist for internal reads diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index adc3c9b03..ce6420fa4 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -3,7 +3,7 @@ module FV3GFS_io_mod !----------------------------------------------------------------------- ! gfs_physics_driver_mod defines the GFS physics routines used by ! the GFDL FMS system to obtain tendencies and boundary fluxes due -! to the physical parameterizations and processes that drive +! to the physical parameterizations and processes that drive ! atmospheric time tendencies for use by other components, namely ! the atmospheric dynamical core. ! @@ -17,10 +17,13 @@ module FV3GFS_io_mod use block_control_mod, only: block_control_type use mpp_mod, only: mpp_error, mpp_pe, mpp_root_pe, & mpp_chksum, NOTE, FATAL - use fms_mod, only: file_exist, stdout - use fms_io_mod, only: restart_file_type, free_restart_type, & - register_restart_field, & - restore_state, save_restart + use fms_mod, only: stdout + use fms2_io_mod, only: FmsNetcdfDomainFile_t, unlimited, & + open_file, close_file, & + register_axis, register_restart_field, & + register_variable_attribute, register_field, & + read_restart, write_restart, write_data, & + get_global_io_domain_indices, variable_exists use mpp_domains_mod, only: domain1d, domain2d, domainUG use time_manager_mod, only: time_type use diag_manager_mod, only: register_diag_field, send_data @@ -42,7 +45,7 @@ module FV3GFS_io_mod !----------------------------------------------------------------------- implicit none private - + !--- public interfaces --- public FV3GFS_restart_read, FV3GFS_restart_write public FV3GFS_GFS_checksum @@ -58,10 +61,10 @@ module FV3GFS_io_mod character(len=32) :: fn_srf = 'sfc_data.nc' character(len=32) :: fn_phy = 'phy_data.nc' - !--- GFDL FMS netcdf restart data types - type(restart_file_type) :: Oro_restart, Sfc_restart, Phy_restart - type(restart_file_type) :: Oro_ls_restart, Oro_ss_restart - + !--- GFDL FMS netcdf restart data types defined in fms2_io + type(FmsNetcdfDomainFile_t) :: Oro_restart, Sfc_restart, Phy_restart + type(FmsNetcdfDomainFile_t) :: Oro_ls_restart, Oro_ss_restart + !--- GFDL FMS restart containers character(len=32), allocatable, dimension(:) :: oro_name2, sfc_name2, sfc_name3 real(kind=kind_phys), allocatable, target, dimension(:,:,:) :: oro_var2, sfc_var2, phy_var2, sfc_var3ice @@ -96,7 +99,7 @@ module FV3GFS_io_mod real, parameter:: drythresh = 1.e-4_r8, zero = 0.0_r8, one = 1.0_r8 real, parameter:: min_lake_orog = 200.0_r8 real(kind=kind_phys), parameter :: timin = 173.0_r8 ! minimum temperature allowed for snow/ice - + !--- miscellaneous other variables logical :: use_wrtgridcomp_output = .FALSE. logical :: module_is_initialized = .FALSE. @@ -119,8 +122,8 @@ subroutine FV3GFS_restart_read (GFS_Data, GFS_Restart, Atm_block, Model, fv_doma type(GFS_control_type), intent(inout) :: Model type(domain2d), intent(in) :: fv_domain logical, intent(in) :: warm_start - - !--- read in surface data from chgres + + !--- read in surface data from chgres call sfc_prop_restart_read (GFS_Data%Sfcprop, Atm_block, Model, fv_domain, warm_start) !--- read in physics restart data @@ -138,10 +141,10 @@ subroutine FV3GFS_restart_write (GFS_Data, GFS_Restart, Atm_block, Model, fv_dom type(GFS_control_type), intent(in) :: Model type(domain2d), intent(in) :: fv_domain character(len=32), optional, intent(in) :: timestamp - - !--- write surface data from chgres + + !--- write surface data from chgres call sfc_prop_restart_write (GFS_Data%Sfcprop, Atm_block, Model, fv_domain, timestamp) - + !--- write physics restart data call phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timestamp) @@ -490,7 +493,7 @@ end subroutine FV3GFS_GFS_checksum ! calls: register_restart_field, restart_state, free_restart ! ! opens: oro_data.tile?.nc, sfc_data.tile?.nc -! +! !---------------------------------------------------------------------- subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_start) !--- interface variable definitions @@ -515,7 +518,13 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta integer :: vegtyp logical :: mand real(kind=kind_phys) :: rsnow, tem, tem1 - + !--- directory of the input files + character(5) :: indir='INPUT' + character(37) :: infile + !--- fms2_io file open logic + logical :: amiopen + logical :: is_lsoil + nvar_o2 = 19 nvar_oro_ls_ss = 10 nvar_s2o = 18 @@ -551,8 +560,14 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta npz = Atm_block%npz nx = (iec - isc + 1) ny = (jec - jsc + 1) - + !--- OROGRAPHY FILE + + !--- open file + infile=trim(indir)//'/'//trim(fn_oro) + amiopen=open_file(Oro_restart, trim(infile), 'read', domain=fv_domain, is_restart=.true., dont_add_res_to_filename=.true.) + if (.not.amiopen) call mpp_error( FATAL, 'Error with opening file '//trim(infile) ) + if (.not. allocated(oro_name2)) then !--- allocate the various containers needed for orography data allocate(oro_name2(nvar_o2)) @@ -579,23 +594,29 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta !--- variables below here are optional oro_name2(18) = 'lake_frac' ! lake fraction [0:1] oro_name2(19) = 'lake_depth' ! lake depth(m) + + !--- register axis + call register_axis( Oro_restart, "lon", 'X' ) + call register_axis( Oro_restart, "lat", 'Y' ) !--- register the 2D fields do num = 1,nvar_o2 - var2_p => oro_var2(:,:,num) - if (trim(oro_name2(num)) == 'lake_frac' .or. trim(oro_name2(num)) == 'lake_depth') then - id_restart = register_restart_field(Oro_restart, fn_oro, oro_name2(num), var2_p, domain=fv_domain, mandatory=.false.) - else - id_restart = register_restart_field(Oro_restart, fn_oro, oro_name2(num), var2_p, domain=fv_domain) - endif + var2_p => oro_var2(:,:,num) + if (trim(oro_name2(num)) == 'lake_frac' .or. trim(oro_name2(num)) == 'lake_depth') then + call register_restart_field(Oro_restart, oro_name2(num), var2_p, dimensions=(/'lat','lon'/), is_optional=.true.) + else + call register_restart_field(Oro_restart, oro_name2(num), var2_p, dimensions=(/'lat','lon'/)) + endif enddo nullify(var2_p) - endif + endif + + !--- read the orography restart/data + call mpp_error(NOTE,'reading topographic/orographic information from INPUT/oro_data.tile*.nc') + call read_restart(Oro_restart) + call close_file(Oro_restart) - !--- read the orography restart/data - call mpp_error(NOTE,'reading topographic/orographic information from INPUT/oro_data.tile*.nc') - call restore_state(Oro_restart) - !--- copy data into GFS containers + !--- copy data into GFS containers !$omp parallel do default(shared) private(i, j, nb, ix) do nb = 1, Atm_block%nblks @@ -635,7 +656,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta enddo enddo - + nvar_s2m = 44 if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then nvar_s2m = nvar_s2m + 4 @@ -647,11 +668,21 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta !--- deallocate containers and free restart container deallocate(oro_name2, oro_var2) - call free_restart_type(Oro_restart) - !--- Modify/read-in additional orographic static fields for GSL drag suite + !--- Modify/read-in additional orographic static fields for GSL drag suite if (Model%gwd_opt==3 .or. Model%gwd_opt==33 .or. & Model%gwd_opt==2 .or. Model%gwd_opt==22 ) then + + !--- open restart file + infile=trim(indir)//'/'//trim(fn_oro_ls) + amiopen=open_file(Oro_ls_restart, trim(infile), 'read', domain=fv_domain, is_restart=.true., dont_add_res_to_filename=.true.) + if( .not.amiopen ) call mpp_error( FATAL, 'Error with opening file '//trim(infile) ) + + !--- open restart file + infile=trim(indir)//'/'//trim(fn_oro_ss) + amiopen=open_file(Oro_ss_restart, trim(infile), 'read', domain=fv_domain, is_restart=.true., dont_add_res_to_filename=.true.) + if( .not.amiopen ) call mpp_error( FATAL, 'Error with opening file '//trim(infile) ) + if (.not. allocated(oro_ls_ss_name)) then !--- allocate the various containers needed for orography data allocate(oro_ls_ss_name(nvar_oro_ls_ss)) @@ -668,28 +699,34 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta oro_ls_ss_name(8) = 'ol2' oro_ls_ss_name(9) = 'ol3' oro_ls_ss_name(10) = 'ol4' - !--- register the 2D fields + + call register_axis(Oro_ls_restart, "lon", 'X') + call register_axis(Oro_ls_restart, "lat", 'Y') + call register_axis(Oro_ss_restart, "lon", 'X') + call register_axis(Oro_ss_restart, "lat", 'Y') + do num = 1,nvar_oro_ls_ss var2_p => oro_ls_var(:,:,num) - id_restart = register_restart_field(Oro_ls_restart, fn_oro_ls, & - oro_ls_ss_name(num), var2_p, domain=fv_domain) + call register_restart_field(Oro_ls_restart, oro_ls_ss_name(num), var2_p, dimensions=(/'lon','lat'/)) enddo nullify(var2_p) do num = 1,nvar_oro_ls_ss var2_p => oro_ss_var(:,:,num) - id_restart = register_restart_field(Oro_ss_restart, fn_oro_ss, & - oro_ls_ss_name(num), var2_p, domain=fv_domain) + call register_restart_field(Oro_ss_restart, oro_ls_ss_name(num), var2_p, dimensions=(/'lon','lat'/)) enddo nullify(var2_p) - endif + end if !--- read new GSL created orography restart/data call mpp_error(NOTE,'reading topographic/orographic information from & - &INPUT/oro_data_ls.tile*.nc') - call restore_state(Oro_ls_restart) + &INPUT/oro_data_ls.tile*.nc') + call read_restart(Oro_ls_restart) + call close_file(Oro_ls_restart) call mpp_error(NOTE,'reading topographic/orographic information from & - &INPUT/oro_data_ss.tile*.nc') - call restore_state(Oro_ss_restart) + &INPUT/oro_data_ss.tile*.nc') + call read_restart(Oro_ss_restart) + call close_file(Oro_ss_restart) + do nb = 1, Atm_block%nblks !--- 2D variables @@ -727,11 +764,15 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta enddo enddo - call free_restart_type(Oro_ls_restart) - call free_restart_type(Oro_ss_restart) - endif + end if + + !--- SURFACE FILE + + !--- open file + infile=trim(indir)//'/'//trim(fn_srf) + amiopen=open_file(Sfc_restart, trim(infile), "read", domain=fv_domain, is_restart=.true., dont_add_res_to_filename=.true.) + if( .not.amiopen ) call mpp_error(FATAL, 'Error opening file'//trim(infile)) - !--- SURFACE FILE if (.not. allocated(sfc_name2)) then !--- allocate the various containers needed for restarts allocate(sfc_name2(nvar_s2m+nvar_s2o+nvar_s2mp+nvar_s2r)) @@ -894,6 +935,36 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta sfc_name2(nvar_s2m+19) = 'lai' endif + is_lsoil=.false. + if ( .not. warm_start ) then + if( variable_exists(Sfc_restart,"lsoil") ) then + is_lsoil=.true. + call register_axis(Sfc_restart, 'lon', 'X') + call register_axis(Sfc_restart, 'lat', 'Y') + call register_axis(Sfc_restart, 'lsoil', dimension_length=Model%lsoil) + else + call register_axis(Sfc_restart, 'xaxis_1', 'X') + call register_axis(Sfc_restart, 'yaxis_1', 'Y') + call register_axis(Sfc_restart, 'zaxis_1', dimension_length=4) + call register_axis(Sfc_restart, 'Time', 1) + end if + else + call register_axis(Sfc_restart, 'xaxis_1', 'X') + call register_axis(Sfc_restart, 'yaxis_1', 'Y') + call register_axis(Sfc_restart, 'zaxis_1', dimension_length=Model%kice) + + if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. Model%lsm == Model%lsm_noah_wrfv4) then + call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil) + else if(Model%lsm == Model%lsm_ruc) then + call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil_lsm) + end if + if(Model%lsm == Model%lsm_noahmp) then + call register_axis(Sfc_restart, 'zaxis_3', dimension_length=3) + call register_axis(Sfc_restart, 'zaxis_4', dimension_length=7) + end if + call register_axis(Sfc_restart, 'Time', unlimited) + end if + !--- register the 2D fields do num = 1,nvar_s2m var2_p => sfc_var2(:,:,num) @@ -901,47 +972,69 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta .or. trim(sfc_name2(num)) == 'zorli' .or. trim(sfc_name2(num)) == 'zorlwav' & .or. trim(sfc_name2(num)) == 'snodl' .or. trim(sfc_name2(num)) == 'weasdl' & .or. trim(sfc_name2(num)) == 'tsfc' .or. trim(sfc_name2(num)) == 'zorlw' & - .or. trim(sfc_name2(num)) == 'albdirvis_lnd' .or. trim(sfc_name2(num)) == 'albdirnir_lnd' & - .or. trim(sfc_name2(num)) == 'albdifvis_lnd' .or. trim(sfc_name2(num)) == 'albdifnir_lnd' & - .or. trim(sfc_name2(num)) == 'albdirvis_ice' .or. trim(sfc_name2(num)) == 'albdifvis_ice' & - .or. trim(sfc_name2(num)) == 'albdirnir_ice' .or. trim(sfc_name2(num)) == 'albdifnir_ice' & - .or. trim(sfc_name2(num)) == 'emis_lnd' ) then - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name2(num), var2_p, domain=fv_domain, mandatory=.false.) + .or. trim(sfc_name2(num)) == 'albdirvis_lnd' .or. trim(sfc_name2(num)) == 'albdirnir_lnd' & + .or. trim(sfc_name2(num)) == 'albdifvis_lnd' .or. trim(sfc_name2(num)) == 'albdifnir_lnd' & + .or. trim(sfc_name2(num)) == 'albdirvis_ice' .or. trim(sfc_name2(num)) == 'albdirnir_ice' & + .or. trim(sfc_name2(num)) == 'albdifvis_ice' .or. trim(sfc_name2(num)) == 'albdifnir_ice' & + .or. trim(sfc_name2(num)) == 'emis_lnd' ) then + if(is_lsoil) then + call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'lat','lon'/), is_optional=.true.) + else + call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'Time ','yaxis_1','xaxis_1'/),& + &is_optional=.true.) + end if else - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name2(num), var2_p, domain=fv_domain) + if(is_lsoil) then + call register_restart_field(Sfc_restart,sfc_name2(num),var2_p, dimensions=(/'lat','lon'/)) + else + call register_restart_field(Sfc_restart,sfc_name2(num),var2_p, dimensions=(/'Time ','yaxis_1','xaxis_1'/)) + end if endif - enddo - + enddo if (Model%nstf_name(1) > 0) then - mand = .false. - if (Model%nstf_name(2) == 0) mand = .true. - do num = nvar_s2m+1,nvar_s2m+nvar_s2o - var2_p => sfc_var2(:,:,num) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name2(num), var2_p, domain=fv_domain, mandatory=mand) - enddo + mand = .false. + if (Model%nstf_name(2) == 0) mand = .true. + do num = nvar_s2m+1,nvar_s2m+nvar_s2o + var2_p => sfc_var2(:,:,num) + if(is_lsoil) then + call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'lat','lon'/), is_optional=.not.mand) + else + call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'Time ','yaxis_1','xaxis_1'/), & + &is_optional=.not.mand) + endif + enddo endif if (Model%lsm == Model%lsm_ruc) then ! nvar_s2mp = 0 - do num = nvar_s2m+nvar_s2o+1, nvar_s2m+nvar_s2o+nvar_s2r - var2_p => sfc_var2(:,:,num) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name2(num), var2_p, domain=fv_domain) - enddo + do num = nvar_s2m+nvar_s2o+1, nvar_s2m+nvar_s2o+nvar_s2r + var2_p => sfc_var2(:,:,num) + if(is_lsoil) then + call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'lat','lon'/) ) + else + call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'Time ','yaxis_1','xaxis_1'/) ) + end if + enddo endif ! mp/ruc + ! Noah MP register only necessary only lsm = 2, not necessary has values if (nvar_s2mp > 0) then - mand = .false. - do num = nvar_s2m+nvar_s2o+1,nvar_s2m+nvar_s2o+nvar_s2mp - var2_p => sfc_var2(:,:,num) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name2(num), var2_p, domain=fv_domain, mandatory=mand) - enddo + mand = .false. + do num = nvar_s2m+nvar_s2o+1,nvar_s2m+nvar_s2o+nvar_s2mp + var2_p => sfc_var2(:,:,num) + if(is_lsoil) then + call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'lat','lon'/), is_optional=.not.mand) + else + call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'Time ','yaxis_1','xaxis_1'/), & + &is_optional=.not.mand) + end if + enddo endif ! noahmp - nullify(var2_p) - endif ! if not allocated + endif ! if not allocated + - if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. Model%lsm == Model%lsm_noah_wrfv4 .or. (.not.warm_start)) then !--- names of the 3D variables to save sfc_name3(1) = 'stc' @@ -966,29 +1059,43 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta !--- register the 3D fields sfc_name3(0) = 'tiice' var3_p => sfc_var3ice(:,:,:) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name3(0), var3_p, domain=fv_domain, mandatory=.false.) - + call register_restart_field(Sfc_restart, sfc_name3(0), var3_p, dimensions=(/'xaxis_1', 'yaxis_1', 'zaxis_1', 'Time '/),& + &is_optional=.true.) + do num = 1,nvar_s3 - var3_p => sfc_var3(:,:,:,num) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name3(num), var3_p, domain=fv_domain) + var3_p => sfc_var3(:,:,:,num) + if ( warm_start ) then + call register_restart_field(Sfc_restart, sfc_name3(num), var3_p, dimensions=(/'xaxis_1', 'yaxis_1', 'lsoil ', 'Time '/),& + &is_optional=.true.) + else + if(is_lsoil) then + call register_restart_field(Sfc_restart, sfc_name3(num), var3_p, dimensions=(/'lat ', 'lon ', 'lsoil'/), is_optional=.true.) + else + call register_restart_field(Sfc_restart, sfc_name3(num), var3_p, dimensions=(/'xaxis_1','yaxis_1','zaxis_1','Time '/),& + &is_optional=.true.) + end if + end if enddo + if (Model%lsm == Model%lsm_noahmp) then - mand = .false. - do num = nvar_s3+1,nvar_s3+3 - var3_p1 => sfc_var3sn(:,:,:,num) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name3(num), var3_p1, domain=fv_domain,mandatory=mand) - enddo + mand = .false. + do num = nvar_s3+1,nvar_s3+3 + var3_p1 => sfc_var3sn(:,:,:,num) + call register_restart_field(Sfc_restart, sfc_name3(num), var3_p1, dimensions=(/'xaxis_1', 'yaxis_1','zaxis_2', 'Time '/),& + &is_optional=.not.mand) + enddo - var3_p2 => sfc_var3eq(:,:,:,7) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name3(7), var3_p2, domain=fv_domain,mandatory=mand) + var3_p2 => sfc_var3eq(:,:,:,7) + call register_restart_field(Sfc_restart, sfc_name3(7), var3_p2, dimensions=(/'xaxis_1', 'yaxis_1', 'zaxis_3', 'Time '/),& + &is_optional=.not.mand) - var3_p3 => sfc_var3zn(:,:,:,8) - id_restart = register_restart_fIeld(Sfc_restart, fn_srf, sfc_name3(8), var3_p3, domain=fv_domain,mandatory=mand) - - nullify(var3_p1) - nullify(var3_p2) - nullify(var3_p3) + var3_p3 => sfc_var3zn(:,:,:,8) + call register_restart_field(Sfc_restart, sfc_name3(8), var3_p3, dimensions=(/'xaxis_1', 'yaxis_1', 'zaxis_4', 'Time '/),& + &is_optional=.not.mand) + nullify(var3_p1) + nullify(var3_p2) + nullify(var3_p3) endif !mp nullify(var3_p) @@ -1002,7 +1109,8 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta !--- read the surface restart/data call mpp_error(NOTE,'reading surface properties data from INPUT/sfc_data.tile*.nc') - call restore_state(Sfc_restart) + call read_restart(Sfc_restart) + call close_file(Sfc_restart) ! write(0,*)' stype read in min,max=',minval(sfc_var2(:,:,35)),maxval(sfc_var2(:,:,35)),' sfc_name2=',sfc_name2(35) ! write(0,*)' stype read in min,max=',minval(sfc_var2(:,:,18)),maxval(sfc_var2(:,:,18)) @@ -1296,7 +1404,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta Sfcprop(nb)%snicexy(ix,lsoil) = sfc_var3sn(i,j,lsoil,4) Sfcprop(nb)%snliqxy(ix,lsoil) = sfc_var3sn(i,j,lsoil,5) Sfcprop(nb)%tsnoxy(ix,lsoil) = sfc_var3sn(i,j,lsoil,6) - enddo + enddo do lsoil = 1, 4 Sfcprop(nb)%smoiseq(ix,lsoil) = sfc_var3eq(i,j,lsoil,7) @@ -1304,7 +1412,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta do lsoil = -2, 4 Sfcprop(nb)%zsnsoxy(ix,lsoil) = sfc_var3zn(i,j,lsoil,8) - enddo + enddo endif else if (Model%lsm == Model%lsm_ruc) then @@ -1512,6 +1620,14 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p1 => NULL() real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p2 => NULL() real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p3 => NULL() + !--- directory of the input files + character(7) :: indir='RESTART' + character(72) :: infile + !--- fms2_io file open logic + logical :: amiopen + !--- variables used for fms2_io register axis + integer :: is, ie + integer, allocatable, dimension(:) :: buffer nvar2m = 44 if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then @@ -1557,11 +1673,83 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta deallocate(sfc_name3) deallocate(sfc_var2) deallocate(sfc_var3) - call free_restart_type(Sfc_restart) - end if + end if end if end if + !--- set filename + infile=trim(indir)//'/'//trim(fn_srf) + if( present(timestamp) ) infile=trim(indir)//'/'//trim(timestamp)//'.'//trim(fn_srf) + + !--- register axis + amiopen=open_file(Sfc_restart, trim(infile), 'overwrite', domain=fv_domain, is_restart=.true., dont_add_res_to_filename=.true.) + if( amiopen ) then + call register_axis(Sfc_restart, 'xaxis_1', 'X') + call register_field(Sfc_restart, 'xaxis_1', 'double', (/'xaxis_1'/)) + call register_variable_attribute(Sfc_restart, 'xaxis_1', 'cartesian_axis', 'X', str_len=1) + call get_global_io_domain_indices(Sfc_restart, 'xaxis_1', is, ie, indices=buffer) + call write_data(Sfc_restart, "xaxis_1", buffer) + deallocate(buffer) + + call register_axis(Sfc_restart, 'yaxis_1', 'Y') + call register_field(Sfc_restart, 'yaxis_1', 'double', (/'yaxis_1'/)) + call register_variable_attribute(Sfc_restart, 'yaxis_1', 'cartesian_axis', 'Y', str_len=1) + call get_global_io_domain_indices(Sfc_restart, 'yaxis_1', is, ie, indices=buffer) + call write_data(Sfc_restart, "yaxis_1", buffer) + deallocate(buffer) + + call register_axis(Sfc_restart, 'zaxis_1', dimension_length=Model%kice) + call register_field(Sfc_restart, 'zaxis_1', 'double', (/'zaxis_1'/)) + call register_variable_attribute(Sfc_restart, 'zaxis_1', 'cartesian_axis', 'Z', str_len=1) + allocate( buffer(Model%kice) ) + do i=1, Model%kice + buffer(i) = i + end do + call write_data(Sfc_restart, 'zaxis_1', buffer) + deallocate(buffer) + + if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. Model%lsm == Model%lsm_noah_wrfv4) then + call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil) + call register_field(Sfc_restart, 'zaxis_2', 'double', (/'zaxis_2'/)) + call register_variable_attribute(Sfc_restart, 'zaxis_2', 'cartesian_axis', 'Z', str_len=1) + allocate( buffer(Model%lsoil) ) + do i=1, Model%lsoil + buffer(i)=i + end do + call write_data(Sfc_restart, 'zaxis_2', buffer) + deallocate(buffer) + endif + + if(Model%lsm == Model%lsm_noahmp) then + call register_axis(Sfc_restart, 'zaxis_3', dimension_length=3) + call register_field(Sfc_restart, 'zaxis_3', 'double', (/'zaxis_3'/)) + call register_variable_attribute(Sfc_restart, 'zaxis_3', 'cartesian_axis', 'Z', str_len=1) + allocate(buffer(3)) + do i=1, 3 + buffer(i) = i + end do + call write_data(Sfc_restart, 'zaxis_3', buffer) + deallocate(buffer) + + call register_axis(Sfc_restart, 'zaxis_4', dimension_length=7) + call register_field(Sfc_restart, 'zaxis_4', 'double', (/'zaxis_4'/)) + call register_variable_attribute(Sfc_restart, 'zaxis_4', 'cartesian_axis' ,'Z', str_len=1) + allocate(buffer(7)) + do i=1, 7 + buffer(i)=i + end do + call write_data(Sfc_restart, 'zaxis_4', buffer) + deallocate(buffer) + end if + call register_axis(Sfc_restart, 'Time', unlimited) + call register_field(Sfc_restart, 'Time', 'double', (/'Time'/)) + call register_variable_attribute(Sfc_restart, 'Time', 'cartesian_axis', 'T', str_len=1) + call write_data( Sfc_restart, 'Time', 1) + else + call mpp_error(FATAL, 'Error in opening file'//trim(infile) ) + end if + + if (.not. allocated(sfc_name2)) then !--- allocate the various containers needed for restarts allocate(sfc_name2(nvar2m+nvar2o+nvar2mp+nvar2r)) @@ -1716,100 +1904,112 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta sfc_name2(nvar2m+46) = 'deeprechxy' sfc_name2(nvar2m+47) = 'rechxy' endif + end if + + !--- register the 2D fields + do num = 1,nvar2m + var2_p => sfc_var2(:,:,num) + if (trim(sfc_name2(num)) == 'sncovr' .or. trim(sfc_name2(num)) == 'tsfcl' .or.trim(sfc_name2(num)) == 'zorll' & + .or. trim(sfc_name2(num)) == 'zorli' .or.trim(sfc_name2(num)) == 'zorlwav' & + .or. trim(sfc_name2(num)) == 'snodl' .or. trim(sfc_name2(num)) == 'weasdl' & + .or. trim(sfc_name2(num)) == 'tsfc' .or. trim(sfc_name2(num)) == 'zorlw' & + .or. trim(sfc_name2(num)) == 'albdirvis_lnd' .or. trim(sfc_name2(num)) == 'albdirnir_lnd' & + .or. trim(sfc_name2(num)) == 'albdifvis_lnd' .or. trim(sfc_name2(num)) == 'albdifnir_lnd' & + .or. trim(sfc_name2(num)) == 'albdirvis_ice' .or. trim(sfc_name2(num)) == 'albdirnir_ice' & + .or. trim(sfc_name2(num)) == 'albdifvis_ice' .or. trim(sfc_name2(num)) == 'albdifnir_ice' & + .or. trim(sfc_name2(num)) == 'emis_lnd' ) then + call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'xaxis_1','yaxis_1','Time '/), is_optional=.true.) + else + call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/) ) + endif + enddo + if (Model%nstf_name(1) > 0) then + mand = .false. + if (Model%nstf_name(2) ==0) mand = .true. + do num = nvar2m+1,nvar2m+nvar2o + var2_p => sfc_var2(:,:,num) + call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/),& + &is_optional=.not.mand) + enddo + endif - !--- register the 2D fields - do num = 1,nvar2m - var2_p => sfc_var2(:,:,num) - if (trim(sfc_name2(num)) == 'sncovr' .or. trim(sfc_name2(num)) == 'tsfcl' .or.trim(sfc_name2(num)) == 'zorll' & - .or. trim(sfc_name2(num)) == 'zorli' .or.trim(sfc_name2(num)) == 'zorlwav' & - .or. trim(sfc_name2(num)) == 'snodl' .or. trim(sfc_name2(num)) == 'weasdl' & - .or. trim(sfc_name2(num)) == 'tsfc' .or. trim(sfc_name2(num)) == 'zorlw' & - .or. trim(sfc_name2(num)) == 'albdirvis_lnd' .or. trim(sfc_name2(num)) == 'albdirnir_lnd' & - .or. trim(sfc_name2(num)) == 'albdifvis_lnd' .or. trim(sfc_name2(num)) == 'albdifnir_lnd' & - .or. trim(sfc_name2(num)) == 'albdirvis_ice' .or. trim(sfc_name2(num)) == 'albdifvis_ice' & - .or. trim(sfc_name2(num)) == 'albdirnir_ice' .or. trim(sfc_name2(num)) == 'albdifnir_ice' & -! .or. trim(sfc_name2(num)) == 'sfalb_ice' & - .or. trim(sfc_name2(num)) == 'emis_lnd' ) then - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name2(num), var2_p, domain=fv_domain, mandatory=.false.) - else - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name2(num), var2_p, domain=fv_domain) - endif + if (Model%lsm == Model%lsm_ruc) then ! nvar2mp =0 + do num = nvar2m+nvar2o+1, nvar2m+nvar2o+nvar2r + var2_p => sfc_var2(:,:,num) + call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/)) enddo - if (Model%nstf_name(1) > 0) then - mand = .false. - if (Model%nstf_name(2) ==0) mand = .true. - do num = nvar2m+1,nvar2m+nvar2o - var2_p => sfc_var2(:,:,num) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name2(num), var2_p, domain=fv_domain, mandatory=mand) - enddo - endif + else if (Model%lsm == Model%lsm_noahmp) then ! nvar2r =0 + mand = .true. ! actually should be true since it is after cold start + do num = nvar2m+nvar2o+1,nvar2m+nvar2o+nvar2mp + var2_p => sfc_var2(:,:,num) + call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/),& + &is_optional=.not.mand) + enddo + endif + nullify(var2_p) - if (Model%lsm == Model%lsm_ruc) then ! nvar2mp =0 - do num = nvar2m+nvar2o+1, nvar2m+nvar2o+nvar2r - var2_p => sfc_var2(:,:,num) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name2(num), var2_p, domain=fv_domain) - enddo - else if (Model%lsm == Model%lsm_noahmp) then ! nvar2r =0 - mand = .true. ! actually should be true since it is after cold start - do num = nvar2m+nvar2o+1,nvar2m+nvar2o+nvar2mp - var2_p => sfc_var2(:,:,num) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name2(num), var2_p, domain=fv_domain, mandatory=mand) - enddo + if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. Model%lsm == Model%lsm_noah_wrfv4) then + !--- names of the 3D variables to save + sfc_name3(1) = 'stc' + sfc_name3(2) = 'smc' + sfc_name3(3) = 'slc' + if (Model%lsm == Model%lsm_noahmp) then + sfc_name3(4) = 'snicexy' + sfc_name3(5) = 'snliqxy' + sfc_name3(6) = 'tsnoxy' + sfc_name3(7) = 'smoiseq' + sfc_name3(8) = 'zsnsoxy' endif - nullify(var2_p) - - if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. Model%lsm == Model%lsm_noah_wrfv4) then - !--- names of the 3D variables to save - sfc_name3(1) = 'stc' - sfc_name3(2) = 'smc' - sfc_name3(3) = 'slc' - if (Model%lsm == Model%lsm_noahmp) then - sfc_name3(4) = 'snicexy' - sfc_name3(5) = 'snliqxy' - sfc_name3(6) = 'tsnoxy' - sfc_name3(7) = 'smoiseq' - sfc_name3(8) = 'zsnsoxy' - endif - else if (Model%lsm == Model%lsm_ruc) then - !--- names of the 3D variables to save - sfc_name3(1) = 'tslb' - sfc_name3(2) = 'smois' - sfc_name3(3) = 'sh2o' - sfc_name3(4) = 'smfr' - sfc_name3(5) = 'flfr' - end if + else if (Model%lsm == Model%lsm_ruc) then + !--- names of the 3D variables to save + sfc_name3(1) = 'tslb' + sfc_name3(2) = 'smois' + sfc_name3(3) = 'sh2o' + sfc_name3(4) = 'smfr' + sfc_name3(5) = 'flfr' + end if - !--- register the 3D fields -! if (Model%frac_grid) then - sfc_name3(0) = 'tiice' - var3_p => sfc_var3ice(:,:,:) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name3(0), var3_p, domain=fv_domain) -! endif + !--- register the 3D fields + ! if (Model%frac_grid) then + sfc_name3(0) = 'tiice' + var3_p => sfc_var3ice(:,:,:) + call register_restart_field(Sfc_restart, sfc_name3(0), var3_p, dimensions=(/'xaxis_1', 'yaxis_1', 'zaxis_1', 'Time '/)) + ! endif + if(Model%lsm == Model%lsm_ruc) then do num = 1,nvar3 - var3_p => sfc_var3(:,:,:,num) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name3(num), var3_p, domain=fv_domain) + var3_p => sfc_var3(:,:,:,num) + call register_restart_field(Sfc_restart, sfc_name3(num), var3_p, dimensions=(/'xaxis_1', 'yaxis_1', 'zaxis_1', 'Time '/)) enddo nullify(var3_p) + else + do num = 1,nvar3 + var3_p => sfc_var3(:,:,:,num) + call register_restart_field(Sfc_restart, sfc_name3(num), var3_p, dimensions=(/'xaxis_1', 'yaxis_1', 'zaxis_2', 'Time '/)) + enddo + nullify(var3_p) + endif - if (Model%lsm == Model%lsm_noahmp) then - mand = .true. - do num = nvar3+1,nvar3+3 - var3_p1 => sfc_var3sn(:,:,:,num) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name3(num), var3_p1, domain=fv_domain,mandatory=mand) - enddo - - var3_p2 => sfc_var3eq(:,:,:,7) - id_restart = register_restart_field(Sfc_restart, fn_srf, sfc_name3(7), var3_p2, domain=fv_domain,mandatory=mand) - - var3_p3 => sfc_var3zn(:,:,:,8) - id_restart = register_restart_fIeld(Sfc_restart, fn_srf, sfc_name3(8), var3_p3, domain=fv_domain,mandatory=mand) + if (Model%lsm == Model%lsm_noahmp) then + mand = .true. + do num = nvar3+1,nvar3+3 + var3_p1 => sfc_var3sn(:,:,:,num) + call register_restart_field(Sfc_restart, sfc_name3(num), var3_p1, dimensions=(/'xaxis_1', 'yaxis_1', 'zaxis_3', 'Time '/),& + &is_optional=.not.mand) + enddo - nullify(var3_p1) - nullify(var3_p2) - nullify(var3_p3) - endif ! lsm = lsm_noahmp - endif + var3_p2 => sfc_var3eq(:,:,:,7) + call register_restart_field(Sfc_restart, sfc_name3(7), var3_p2, dimensions=(/'xaxis_1', 'yaxis_1', 'zaxis_2', 'Time '/),& + &is_optional=.not.mand) + + var3_p3 => sfc_var3zn(:,:,:,8) + call register_restart_field(Sfc_restart, sfc_name3(8), var3_p3, dimensions=(/'xaxis_1', 'yaxis_1', 'zaxis_4', 'Time '/),& + &is_optional=.not.mand) + + nullify(var3_p1) + nullify(var3_p2) + nullify(var3_p3) + endif ! lsm = lsm_noahmp !$omp parallel do default(shared) private(i, j, nb, ix, lsoil) @@ -1993,7 +2193,8 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta enddo enddo - call save_restart(Sfc_restart, timestamp) + call write_restart(Sfc_restart) + call close_file(Sfc_restart) end subroutine sfc_prop_restart_write @@ -2009,7 +2210,7 @@ end subroutine sfc_prop_restart_write ! calls: register_restart_field, restart_state, free_restart ! ! opens: phys_data.tile?.nc -! +! !---------------------------------------------------------------------- subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain) !--- interface variable definitions @@ -2025,7 +2226,9 @@ subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain) character(len=64) :: fname real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() - + !--- directory of the input files + character(5) :: indir='INPUT' + logical :: amiopen isc = Atm_block%isc iec = Atm_block%iec @@ -2039,7 +2242,20 @@ subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain) nvar3d = GFS_Restart%num3d fdiag = GFS_Restart%fdiag ldiag = GFS_Restart%ldiag - + + !--- open restart file and register axes + fname = trim(indir)//'/'//trim(fn_phy) + amiopen=open_file(Phy_restart, trim(fname), 'read', domain=fv_domain, is_restart=.true., dont_add_res_to_filename=.true.) + if( amiopen ) then + call register_axis(Phy_restart, 'xaxis_1', 'X') + call register_axis(Phy_restart, 'yaxis_1', 'Y') + call register_axis(Phy_restart, 'zaxis_1', npz) + call register_axis(Phy_restart, 'Time', unlimited) + else + call mpp_error(NOTE,'No physics restarts - cold starting physical parameterizations') + return + endif + !--- register the restart fields if (.not. allocated(phy_var2)) then allocate (phy_var2(nx,ny,nvar2d)) @@ -2049,28 +2265,22 @@ subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain) do num = 1,nvar2d var2_p => phy_var2(:,:,num) - id_restart = register_restart_field (Phy_restart, fn_phy, trim(GFS_Restart%name2d(num)), & - var2_p, domain=fv_domain, mandatory=.false.) + call register_restart_field(Phy_restart, trim(GFS_Restart%name2d(num)), var2_p, dimensions=(/'xaxis_1','yaxis_1','Time '/),& + &is_optional=.true.) enddo do num = 1,nvar3d var3_p => phy_var3(:,:,:,num) - id_restart = register_restart_field (Phy_restart, fn_phy, trim(GFS_restart%name3d(num)), & - var3_p, domain=fv_domain, mandatory=.false.) + call register_restart_field(Phy_restart, trim(GFS_restart%name3d(num)), var3_p, dimensions=(/'xaxis_1','yaxis_1','zaxis_1','Time '/), is_optional=.true.) enddo nullify(var2_p) nullify(var3_p) endif - fname = 'INPUT/'//trim(fn_phy) - if (file_exist(fname)) then - !--- read the surface restart/data - call mpp_error(NOTE,'reading physics restart data from INPUT/phy_data.tile*.nc') - call restore_state(Phy_restart) - else - call mpp_error(NOTE,'No physics restarts - cold starting physical parameterizations') - return - endif - + !--- read the surface restart/data + call mpp_error(NOTE,'reading physics restart data from INPUT/phy_data.tile*.nc') + call read_restart(Phy_restart) + call close_file(Phy_restart) + !--- place the data into the block GFS containers !--- phy_var* variables !$omp parallel do default(shared) private(i, j, nb, ix) @@ -2093,7 +2303,7 @@ subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain) j = Atm_block%index(nb)%jj(ix) - jsc + 1 GFS_Restart%data(nb,num)%var2p(ix) = zero enddo - enddo + enddo enddo endif do num = 1,nvar3d @@ -2136,7 +2346,12 @@ subroutine phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timesta integer :: nvar2d, nvar3d real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() - + !--- used for axis data for fms2_io + integer :: is, ie + integer, allocatable, dimension(:) :: buffer + character(7) :: indir='RESTART' + character(72) :: infile + logical :: amiopen isc = Atm_block%isc iec = Atm_block%iec @@ -2148,32 +2363,70 @@ subroutine phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timesta nvar2d = GFS_Restart%num2d nvar3d = GFS_Restart%num3d - !--- register the restart fields + !--- set file name + infile=trim(indir)//'/'//trim(fn_phy) + if( present(timestamp) ) infile=trim(indir)//'/'//trim(timestamp)//'.'//trim(fn_phy) + !--- register axis + amiopen=open_file(Phy_restart, trim(infile), 'overwrite', domain=fv_domain, is_restart=.true., dont_add_res_to_filename=.true.) + if( amiopen ) then + call register_axis(Phy_restart, 'xaxis_1', 'X') + call register_field(Phy_restart, 'xaxis_1', 'double', (/'xaxis_1'/)) + call register_variable_attribute(Phy_restart, 'xaxis_1', 'cartesian_axis', 'X', str_len=1) + call get_global_io_domain_indices(Phy_restart, 'xaxis_1', is, ie, indices=buffer) + call write_data(Phy_restart, "xaxis_1", buffer) + deallocate(buffer) + + call register_axis(Phy_restart, 'yaxis_1', 'Y') + call register_field(Phy_restart, 'yaxis_1', 'double', (/'yaxis_1'/)) + call register_variable_attribute(Phy_restart, 'yaxis_1', 'cartesian_axis', 'Y', str_len=1) + call get_global_io_domain_indices(Phy_restart, 'yaxis_1', is, ie, indices=buffer) + call write_data(Phy_restart, "yaxis_1", buffer) + deallocate(buffer) + + call register_axis(Phy_restart, 'zaxis_1', npz) + call register_field(Phy_restart, 'zaxis_1', 'double', (/'zaxis_1'/)) + call register_variable_attribute(Phy_restart, 'zaxis_1', 'cartesian_axis', 'Z', str_len=1) + allocate( buffer(npz) ) + do i=1, npz + buffer(i)=i + end do + call write_data(Phy_restart, "zaxis_1", buffer) + deallocate(buffer) + + call register_axis(Phy_restart, 'Time', unlimited) + call register_field(Phy_restart, 'Time', 'double', (/'Time'/)) + call register_variable_attribute(Phy_restart, 'Time', 'cartesian_axis', 'T', str_len=1) + call write_data(Phy_restart, "Time", 1) + else + call mpp_error(FATAL, 'Error opening file '//trim(infile)) + end if + + !--- register the restart fields if (.not. allocated(phy_var2)) then allocate (phy_var2(nx,ny,nvar2d)) allocate (phy_var3(nx,ny,npz,nvar3d)) phy_var2 = zero phy_var3 = zero - - do num = 1,nvar2d - var2_p => phy_var2(:,:,num) - id_restart = register_restart_field (Phy_restart, fn_phy, trim(GFS_Restart%name2d(num)), & - var2_p, domain=fv_domain, mandatory=.false.) - enddo - do num = 1,nvar3d - var3_p => phy_var3(:,:,:,num) - id_restart = register_restart_field (Phy_restart, fn_phy, trim(GFS_restart%name3d(num)), & - var3_p, domain=fv_domain, mandatory=.false.) - enddo - nullify(var2_p) - nullify(var3_p) endif + do num = 1,nvar2d + var2_p => phy_var2(:,:,num) + call register_restart_field(Phy_restart, trim(GFS_Restart%name2d(num)), var2_p, dimensions=(/'xaxis_1','yaxis_1','Time '/),& + &is_optional=.true.) + enddo + do num = 1,nvar3d + var3_p => phy_var3(:,:,:,num) + call register_restart_field(Phy_restart, trim(GFS_Restart%name3d(num)), var3_p, dimensions=(/'xaxis_1','yaxis_1','zaxis_1','Time '/),& + &is_optional=.true.) + enddo + nullify(var2_p) + nullify(var3_p) + !--- 2D variables !$omp parallel do default(shared) private(i, j, num, nb, ix) do num = 1,nvar2d do nb = 1,Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) + do ix = 1, Atm_block%blksz(nb) i = Atm_block%index(nb)%ii(ix) - isc + 1 j = Atm_block%index(nb)%jj(ix) - jsc + 1 phy_var2(i,j,num) = GFS_Restart%data(nb,num)%var2p(ix) @@ -2185,7 +2438,7 @@ subroutine phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timesta do num = 1,nvar3d do nb = 1,Atm_block%nblks do k=1,npz - do ix = 1, Atm_block%blksz(nb) + do ix = 1, Atm_block%blksz(nb) i = Atm_block%index(nb)%ii(ix) - isc + 1 j = Atm_block%index(nb)%jj(ix) - jsc + 1 phy_var3(i,j,k,num) = GFS_Restart%data(nb,num)%var3p(ix,k) @@ -2194,7 +2447,8 @@ subroutine phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timesta enddo enddo - call save_restart(Phy_restart, timestamp) + call write_restart(Phy_restart) + call close_file(Phy_restart) end subroutine phys_restart_write @@ -2321,7 +2575,7 @@ end subroutine fv3gfs_diag_register !------------------------------------------------------------------------- !--- gfs_diag_output --- !------------------------------------------------------------------------- -! routine to transfer the diagnostic data to the gfdl fms diagnostic +! routine to transfer the diagnostic data to the gfdl fms diagnostic ! manager for eventual output to the history files. ! ! calls: send_data