From 0b4db900bf1111de27e5ed0145c6a2a406e6102e Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Fri, 5 May 2023 15:32:41 +0000 Subject: [PATCH 01/27] move utility routines, data structures, and name generation out of FV3GFS_io.F90 --- CMakeLists.txt | 2 + io/FV3GFS_common_io.F90 | 279 +++++++++ io/FV3GFS_io.F90 | 1212 ++++++++++++++------------------------- io/FV3GFS_sfc_io.F90 | 276 +++++++++ 4 files changed, 987 insertions(+), 782 deletions(-) create mode 100644 io/FV3GFS_common_io.F90 create mode 100644 io/FV3GFS_sfc_io.F90 diff --git a/CMakeLists.txt b/CMakeLists.txt index 226aea148..236da3b17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,8 @@ add_library(fv3atm cpl/module_cplfields.F90 cpl/module_cap_cpl.F90 io/clm_lake_io.F90 + io/FV3GFS_common_io.F90 + io/FV3GFS_sfc_io.F90 io/FV3GFS_io.F90 io/FV3GFS_restart_io.F90 io/module_write_netcdf.F90 diff --git a/io/FV3GFS_common_io.F90 b/io/FV3GFS_common_io.F90 new file mode 100644 index 000000000..61c6bf817 --- /dev/null +++ b/io/FV3GFS_common_io.F90 @@ -0,0 +1,279 @@ +module FV3GFS_common_io + use GFS_typedefs, only: kind_phys + + implicit none + private + + public :: copy_from_GFS_Data, copy_to_GFS_Data + public :: copy_from_GFS_Data_2d_phys2phys, copy_from_GFS_Data_3d_phys2phys, & + copy_from_GFS_Data_2d_int2phys, copy_from_GFS_Data_3d_int2phys, & + copy_from_GFS_Data_2d_stack_phys2phys, copy_to_GFS_Data_3d_slice_phys2phys, & + copy_to_GFS_Data_2d_phys2phys, copy_to_GFS_Data_3d_phys2phys, & + copy_to_GFS_Data_2d_int2phys, copy_to_GFS_Data_3d_int2phys + + public :: create_2d_field_and_add_to_bundle + public :: create_3d_field_and_add_to_bundle + public :: add_zaxis_to_field + + interface copy_from_GFS_Data + module procedure copy_from_GFS_Data_2d_phys2phys, & + copy_from_GFS_Data_3d_phys2phys, & + copy_from_GFS_Data_2d_int2phys, & + copy_from_GFS_Data_3d_int2phys, & + copy_from_GFS_Data_2d_stack_phys2phys + end interface + + interface copy_to_GFS_Data + module procedure copy_to_GFS_Data_2d_phys2phys, & + copy_to_GFS_Data_3d_phys2phys, & + copy_to_GFS_Data_2d_int2phys, & + copy_to_GFS_Data_3d_int2phys, & + copy_to_GFS_Data_3d_slice_phys2phys + end interface copy_to_GFS_Data + +contains + + pure subroutine copy_from_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(in) :: var_block(:) + real(kind=kind_phys), intent(out) :: var2d(:,:,:) + integer ix + + nt=nt+1 + do ix=1,size(var_block) + var2d(ii1(ix),jj1(ix),nt) = var_block(ix) + enddo + end subroutine copy_from_GFS_Data_2d_phys2phys + + pure subroutine copy_from_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(in) :: var_block(:,:) + real(kind=kind_phys), intent(out) :: var3d(:,:,:,:) + integer ix, k + + nt=nt+1 + do k=lbound(var_block,2),ubound(var_block,2) + do ix=1,size(var_block,1) + var3d(ii1(ix),jj1(ix),k,nt) = var_block(ix,k) + enddo + enddo + end subroutine copy_from_GFS_Data_3d_phys2phys + + pure subroutine copy_from_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc, var_block(:) + integer, intent(inout) :: nt + real(kind=kind_phys), intent(out) :: var2d(:,:,:) + integer ix + + nt=nt+1 + do ix=1,size(var_block) + var2d(ii1(ix),jj1(ix),nt) = var_block(ix) + enddo + end subroutine copy_from_GFS_Data_2d_int2phys + + pure subroutine copy_from_GFS_Data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + ! For copying phy_f2d and phy_fctd + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(in) :: var_block(:,:) + real(kind=kind_phys), intent(out) :: var3d(:,:,:) + integer ix, k + + nt=nt+1 + do k=lbound(var_block,2),ubound(var_block,2) + do ix=1,size(var_block,1) + var3d(ii1(ix),jj1(ix),nt) = var_block(ix,k) + enddo + enddo + end subroutine copy_from_GFS_Data_2d_stack_phys2phys + + pure subroutine copy_from_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), var_block(:,:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(out) :: var3d(:,:,:,:) + integer ix, k + + nt=nt+1 + do k=lbound(var_block,2),ubound(var_block,2) + do ix=1,size(var_block,1) + var3d(ii1(ix),jj1(ix),k,nt) = real(var_block(ix,k),kind_phys) + enddo + enddo + end subroutine copy_from_GFS_Data_3d_int2phys + + pure subroutine copy_to_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(out) :: var_block(:) + real(kind=kind_phys), intent(in) :: var2d(:,:,:) + integer ix + + nt=nt+1 + do ix=1,size(var_block) + var_block(ix) = var2d(ii1(ix),jj1(ix),nt) + enddo + end subroutine copy_to_GFS_Data_2d_phys2phys + + pure subroutine copy_to_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(out) :: var_block(:,:) + real(kind=kind_phys), intent(in) :: var3d(:,:,:,:) + integer ix, k + + nt=nt+1 + do k=lbound(var_block,2),ubound(var_block,2) + do ix=1,size(var_block,1) + var_block(ix,k) = var3d(ii1(ix),jj1(ix),k,nt) + enddo + enddo + end subroutine copy_to_GFS_Data_3d_phys2phys + + pure subroutine copy_to_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc, k1, k2 + integer, intent(inout) :: nt + real(kind=kind_phys), intent(out) :: var_block(:,:) + real(kind=kind_phys), intent(in) :: var3d(:,:,:,:) + integer ix, k + + nt=nt+1 + do k=k1,k2 + do ix=1,size(var_block,1) + var_block(ix,k) = var3d(ii1(ix),jj1(ix),k,nt) + enddo + enddo + end subroutine copy_to_GFS_Data_3d_slice_phys2phys + + pure subroutine copy_to_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + integer, intent(out) :: var_block(:) + real(kind=kind_phys), intent(in) :: var2d(:,:,:) + integer ix + + nt=nt+1 + do ix=1,size(var_block) + var_block(ix) = int(var2d(ii1(ix),jj1(ix),nt)) + enddo + end subroutine copy_to_GFS_Data_2d_int2phys + + pure subroutine copy_to_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + integer, intent(out) :: var_block(:,:) + real(kind=kind_phys), intent(in) :: var3d(:,:,:,:) + integer ix + + nt=nt+1 + do ix=1,size(var_block,1) + var_block(ix,:) = int(var3d(ii1(ix),jj1(ix),:,nt)) + enddo + end subroutine copy_to_GFS_Data_3d_int2phys + + subroutine create_2d_field_and_add_to_bundle(temp_r2d, field_name, outputfile, grid, bundle) + + use esmf + + implicit none + + real(kind_phys), dimension(:,:), pointer, intent(in) :: temp_r2d + character(len=*), intent(in) :: field_name + character(len=*), intent(in) :: outputfile + type(ESMF_Grid), intent(in) :: grid + type(ESMF_FieldBundle), intent(inout) :: bundle + + type(ESMF_Field) :: field + + integer :: rc, i + + field = ESMF_FieldCreate(grid, temp_r2d, datacopyflag=ESMF_DATACOPY_REFERENCE, & + name=trim(field_name), indexFlag=ESMF_INDEX_DELOCAL, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU,line=__LINE__, file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", name='output_file', value=trim(outputfile), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_FieldBundleAdd(bundle, (/field/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + end subroutine create_2d_field_and_add_to_bundle + + subroutine create_3d_field_and_add_to_bundle(temp_r3d, field_name, axis_name, num_levels, outputfile, grid, bundle) + + use esmf + + implicit none + + real(kind_phys), dimension(:,:,:), pointer, intent(in) :: temp_r3d + character(len=*), intent(in) :: field_name + character(len=*), intent(in) :: axis_name + integer, intent(in) :: num_levels + character(len=*), intent(in) :: outputfile + type(ESMF_Grid), intent(in) :: grid + type(ESMF_FieldBundle), intent(inout) :: bundle + + type(ESMF_Field) :: field + + integer :: rc, i + + field = ESMF_FieldCreate(grid, temp_r3d, datacopyflag=ESMF_DATACOPY_REFERENCE, & + name=trim(field_name), indexFlag=ESMF_INDEX_DELOCAL, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU,line=__LINE__, file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", name='output_file', value=trim(outputfile), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call add_zaxis_to_field(field, axis_name, num_levels) + + call ESMF_FieldBundleAdd(bundle, (/field/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + end subroutine create_3d_field_and_add_to_bundle + + subroutine add_zaxis_to_field(field, axis_name, num_levels) + + use esmf + + implicit none + + type(ESMF_Field), intent(inout) :: field + character(len=*), intent(in) :: axis_name + integer, intent(in) :: num_levels + + real(kind_phys), allocatable, dimension(:) :: buffer + integer :: rc, i + + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & + name="ESMF:ungridded_dim_labels", valueList=(/trim(axis_name)/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + allocate( buffer(num_levels) ) + do i=1, num_levels + buffer(i)=i + end do + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3-dim", & + name=trim(axis_name), valueList=buffer, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + deallocate(buffer) + + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3-dim", & + name=trim(axis_name)//"cartesian_axis", value="Z", rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + end subroutine add_zaxis_to_field + +end module FV3GFS_common_io diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index 876248d16..26bc985a5 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -41,6 +41,9 @@ module FV3GFS_io_mod use GFS_restart, only: GFS_restart_type use GFS_diagnostics, only: GFS_externaldiag_type + use FV3GFS_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data + use FV3GFS_sfc_io + ! !----------------------------------------------------------------------- implicit none @@ -69,18 +72,16 @@ module FV3GFS_io_mod 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 + character(len=32), allocatable, dimension(:) :: oro_name2 + real(kind=kind_phys), allocatable, target, dimension(:,:,:) :: oro_var2, phy_var2 character(len=32), allocatable, dimension(:) :: oro_ls_ss_name real(kind=kind_phys), allocatable, target, dimension(:,:,:) :: oro_ls_var, oro_ss_var, oro_var3v, oro_var3s - real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: sfc_var3, phy_var3 + real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: phy_var3 character(len=32), allocatable, dimension(:) :: dust12m_name, emi_name, rrfssd_name real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: rrfssd_var real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: dust12m_var real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: emi_var !--- Noah MP restart containers - real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: sfc_var3sn,sfc_var3eq,sfc_var3zn - real(kind=kind_phys) :: zhour ! integer, parameter :: r8 = kind_phys @@ -107,6 +108,8 @@ module FV3GFS_io_mod real, parameter:: min_lake_orog = 200.0_r8 real(kind=kind_phys), parameter :: timin = 173.0_r8 ! minimum temperature allowed for snow/ice + type(Sfc_io_data_type) :: sfc + !--- miscellaneous other variables logical :: use_wrtgridcomp_output = .FALSE. logical :: module_is_initialized = .FALSE. @@ -133,22 +136,6 @@ module FV3GFS_io_mod final :: rrfs_sd_final ! Destructor; calls deallocate_data end type rrfs_sd_data_type - interface copy_from_GFS_Data - module procedure copy_from_GFS_Data_2d_phys2phys, & - copy_from_GFS_Data_3d_phys2phys, & - copy_from_GFS_Data_2d_int2phys, & - copy_from_GFS_Data_3d_int2phys, & - copy_from_GFS_Data_2d_stack_phys2phys - end interface - - interface copy_to_GFS_Data - module procedure copy_to_GFS_Data_2d_phys2phys, & - copy_to_GFS_Data_3d_phys2phys, & - copy_to_GFS_Data_2d_int2phys, & - copy_to_GFS_Data_3d_int2phys, & - copy_to_GFS_Data_3d_slice_phys2phys - end interface copy_to_GFS_Data - CONTAINS !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -561,314 +548,16 @@ end subroutine FV3GFS_GFS_checksum ! !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - pure subroutine copy_from_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(in) :: var_block(:) - real(kind=kind_phys), intent(out) :: var2d(:,:,:) - integer ix - - nt=nt+1 - do ix=1,size(var_block) - var2d(ii1(ix),jj1(ix),nt) = var_block(ix) - enddo - end subroutine copy_from_GFS_Data_2d_phys2phys - - pure subroutine copy_from_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(in) :: var_block(:,:) - real(kind=kind_phys), intent(out) :: var3d(:,:,:,:) - integer ix, k - - nt=nt+1 - do k=lbound(var_block,2),ubound(var_block,2) - do ix=1,size(var_block,1) - var3d(ii1(ix),jj1(ix),k,nt) = var_block(ix,k) - enddo - enddo - end subroutine copy_from_GFS_Data_3d_phys2phys - - pure subroutine copy_from_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc, var_block(:) - integer, intent(inout) :: nt - real(kind=kind_phys), intent(out) :: var2d(:,:,:) - integer ix - - nt=nt+1 - do ix=1,size(var_block) - var2d(ii1(ix),jj1(ix),nt) = var_block(ix) - enddo - end subroutine copy_from_GFS_Data_2d_int2phys - - pure subroutine copy_from_GFS_Data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - ! For copying phy_f2d and phy_fctd - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(in) :: var_block(:,:) - real(kind=kind_phys), intent(out) :: var3d(:,:,:) - integer ix, k - - nt=nt+1 - do k=lbound(var_block,2),ubound(var_block,2) - do ix=1,size(var_block,1) - var3d(ii1(ix),jj1(ix),nt) = var_block(ix,k) - enddo - enddo - end subroutine copy_from_GFS_Data_2d_stack_phys2phys - - pure subroutine copy_from_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), var_block(:,:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(out) :: var3d(:,:,:,:) - integer ix, k - - nt=nt+1 - do k=lbound(var_block,2),ubound(var_block,2) - do ix=1,size(var_block,1) - var3d(ii1(ix),jj1(ix),k,nt) = real(var_block(ix,k),kind_phys) - enddo - enddo - end subroutine copy_from_GFS_Data_3d_int2phys - - pure subroutine copy_to_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(out) :: var_block(:) - real(kind=kind_phys), intent(in) :: var2d(:,:,:) - integer ix - - nt=nt+1 - do ix=1,size(var_block) - var_block(ix) = var2d(ii1(ix),jj1(ix),nt) - enddo - end subroutine copy_to_GFS_Data_2d_phys2phys - - pure subroutine copy_to_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(out) :: var_block(:,:) - real(kind=kind_phys), intent(in) :: var3d(:,:,:,:) - integer ix, k - - nt=nt+1 - do k=lbound(var_block,2),ubound(var_block,2) - do ix=1,size(var_block,1) - var_block(ix,k) = var3d(ii1(ix),jj1(ix),k,nt) - enddo - enddo - end subroutine copy_to_GFS_Data_3d_phys2phys - - pure subroutine copy_to_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc, k1, k2 - integer, intent(inout) :: nt - real(kind=kind_phys), intent(out) :: var_block(:,:) - real(kind=kind_phys), intent(in) :: var3d(:,:,:,:) - integer ix, k - - nt=nt+1 - do k=k1,k2 - do ix=1,size(var_block,1) - var_block(ix,k) = var3d(ii1(ix),jj1(ix),k,nt) - enddo - enddo - end subroutine copy_to_GFS_Data_3d_slice_phys2phys - - pure subroutine copy_to_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - integer, intent(out) :: var_block(:) - real(kind=kind_phys), intent(in) :: var2d(:,:,:) - integer ix - - nt=nt+1 - do ix=1,size(var_block) - var_block(ix) = int(var2d(ii1(ix),jj1(ix),nt)) - enddo - end subroutine copy_to_GFS_Data_2d_int2phys - - pure subroutine copy_to_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - integer, intent(out) :: var_block(:,:) - real(kind=kind_phys), intent(in) :: var3d(:,:,:,:) - integer ix - - nt=nt+1 - do ix=1,size(var_block,1) - var_block(ix,:) = int(var3d(ii1(ix),jj1(ix),:,nt)) - enddo - end subroutine copy_to_GFS_Data_3d_int2phys - - - pure subroutine fill_Sfcprop_names(Model,sfc_name2,sfc_name3,nvar_s2m,warm_start) + subroutine fill_Sfcprop_names(Model,nvar_s2m,warm_start) implicit none type(GFS_control_type), intent(in) :: Model integer, intent(in) :: nvar_s2m - character(len=32),intent(out) :: sfc_name2(:), sfc_name3(:) logical, intent(in) :: warm_start integer :: nt - !--- names of the 2D variables to save - nt=0 - nt=nt+1 ; sfc_name2(nt) = 'slmsk' - nt=nt+1 ; sfc_name2(nt) = 'tsea' !tsfc - nt=nt+1 ; sfc_name2(nt) = 'sheleg' !weasd - nt=nt+1 ; sfc_name2(nt) = 'tg3' - nt=nt+1 ; sfc_name2(nt) = 'zorl' - nt=nt+1 ; sfc_name2(nt) = 'alvsf' - nt=nt+1 ; sfc_name2(nt) = 'alvwf' - nt=nt+1 ; sfc_name2(nt) = 'alnsf' - nt=nt+1 ; sfc_name2(nt) = 'alnwf' - nt=nt+1 ; sfc_name2(nt) = 'facsf' - nt=nt+1 ; sfc_name2(nt) = 'facwf' - nt=nt+1 ; sfc_name2(nt) = 'vfrac' - nt=nt+1 ; sfc_name2(nt) = 'canopy' - nt=nt+1 ; sfc_name2(nt) = 'f10m' - nt=nt+1 ; sfc_name2(nt) = 't2m' - nt=nt+1 ; sfc_name2(nt) = 'q2m' - nt=nt+1 ; sfc_name2(nt) = 'vtype' - nt=nt+1 ; sfc_name2(nt) = 'stype' - nt=nt+1 ; sfc_name2(nt) = 'uustar' - nt=nt+1 ; sfc_name2(nt) = 'ffmm' - nt=nt+1 ; sfc_name2(nt) = 'ffhh' - nt=nt+1 ; sfc_name2(nt) = 'hice' - nt=nt+1 ; sfc_name2(nt) = 'fice' - nt=nt+1 ; sfc_name2(nt) = 'tisfc' - nt=nt+1 ; sfc_name2(nt) = 'tprcp' - nt=nt+1 ; sfc_name2(nt) = 'srflag' - nt=nt+1 ; sfc_name2(nt) = 'snwdph' !snowd - nt=nt+1 ; sfc_name2(nt) = 'shdmin' - nt=nt+1 ; sfc_name2(nt) = 'shdmax' - nt=nt+1 ; sfc_name2(nt) = 'slope' - nt=nt+1 ; sfc_name2(nt) = 'snoalb' - !--- variables below here are optional - nt=nt+1 ; sfc_name2(nt) = 'sncovr' - nt=nt+1 ; sfc_name2(nt) = 'snodl' !snowd on land portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'weasdl'!weasd on land portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'tsfc' !tsfc composite - nt=nt+1 ; sfc_name2(nt) = 'tsfcl' !temp on land portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'zorlw' !zorl on water portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'zorll' !zorl on land portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'zorli' !zorl on ice portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'albdirvis_lnd' - nt=nt+1 ; sfc_name2(nt) = 'albdirnir_lnd' - nt=nt+1 ; sfc_name2(nt) = 'albdifvis_lnd' - nt=nt+1 ; sfc_name2(nt) = 'albdifnir_lnd' - nt=nt+1 ; sfc_name2(nt) = 'emis_lnd' - nt=nt+1 ; sfc_name2(nt) = 'emis_ice' - nt=nt+1 ; sfc_name2(nt) = 'sncovr_ice' - nt=nt+1 ; sfc_name2(nt) = 'snodi' ! snowd on ice portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'weasdi'! weasd on ice portion of a cell - - if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - nt=nt+1 ; sfc_name2(nt) = 'albdirvis_ice' - nt=nt+1 ; sfc_name2(nt) = 'albdifvis_ice' - nt=nt+1 ; sfc_name2(nt) = 'albdirnir_ice' - nt=nt+1 ; sfc_name2(nt) = 'albdifnir_ice' - endif - - if(Model%cplwav) then - nt=nt+1 ; sfc_name2(nvar_s2m) = 'zorlwav' !zorl from wave component - endif - - if (Model%nstf_name(1) > 0) then - !--- NSSTM inputs only needed when (nstf_name(1) > 0) .and. (nstf_name(2)) == 0) - nt=nt+1 ; sfc_name2(nt) = 'tref' - nt=nt+1 ; sfc_name2(nt) = 'z_c' - nt=nt+1 ; sfc_name2(nt) = 'c_0' - nt=nt+1 ; sfc_name2(nt) = 'c_d' - nt=nt+1 ; sfc_name2(nt) = 'w_0' - nt=nt+1 ; sfc_name2(nt) = 'w_d' - nt=nt+1 ; sfc_name2(nt) = 'xt' - nt=nt+1 ; sfc_name2(nt) = 'xs' - nt=nt+1 ; sfc_name2(nt) = 'xu' - nt=nt+1 ; sfc_name2(nt) = 'xv' - nt=nt+1 ; sfc_name2(nt) = 'xz' - nt=nt+1 ; sfc_name2(nt) = 'zm' - nt=nt+1 ; sfc_name2(nt) = 'xtts' - nt=nt+1 ; sfc_name2(nt) = 'xzts' - nt=nt+1 ; sfc_name2(nt) = 'd_conv' - nt=nt+1 ; sfc_name2(nt) = 'ifd' - nt=nt+1 ; sfc_name2(nt) = 'dt_cool' - nt=nt+1 ; sfc_name2(nt) = 'qrain' - endif -! -! Only needed when Noah MP LSM is used - 29 2D -! - if (Model%lsm == Model%lsm_noahmp) then - nt=nt+1 ; sfc_name2(nt) = 'snowxy' - nt=nt+1 ; sfc_name2(nt) = 'tvxy' - nt=nt+1 ; sfc_name2(nt) = 'tgxy' - nt=nt+1 ; sfc_name2(nt) = 'canicexy' - nt=nt+1 ; sfc_name2(nt) = 'canliqxy' - nt=nt+1 ; sfc_name2(nt) = 'eahxy' - nt=nt+1 ; sfc_name2(nt) = 'tahxy' - nt=nt+1 ; sfc_name2(nt) = 'cmxy' - nt=nt+1 ; sfc_name2(nt) = 'chxy' - nt=nt+1 ; sfc_name2(nt) = 'fwetxy' - nt=nt+1 ; sfc_name2(nt) = 'sneqvoxy' - nt=nt+1 ; sfc_name2(nt) = 'alboldxy' - nt=nt+1 ; sfc_name2(nt) = 'qsnowxy' - nt=nt+1 ; sfc_name2(nt) = 'wslakexy' - nt=nt+1 ; sfc_name2(nt) = 'zwtxy' - nt=nt+1 ; sfc_name2(nt) = 'waxy' - nt=nt+1 ; sfc_name2(nt) = 'wtxy' - nt=nt+1 ; sfc_name2(nt) = 'lfmassxy' - nt=nt+1 ; sfc_name2(nt) = 'rtmassxy' - nt=nt+1 ; sfc_name2(nt) = 'stmassxy' - nt=nt+1 ; sfc_name2(nt) = 'woodxy' - nt=nt+1 ; sfc_name2(nt) = 'stblcpxy' - nt=nt+1 ; sfc_name2(nt) = 'fastcpxy' - nt=nt+1 ; sfc_name2(nt) = 'xsaixy' - nt=nt+1 ; sfc_name2(nt) = 'xlaixy' - nt=nt+1 ; sfc_name2(nt) = 'taussxy' - nt=nt+1 ; sfc_name2(nt) = 'smcwtdxy' - nt=nt+1 ; sfc_name2(nt) = 'deeprechxy' - nt=nt+1 ; sfc_name2(nt) = 'rechxy' - else if (Model%lsm == Model%lsm_ruc .and. warm_start) then - nt=nt+1 ; sfc_name2(nt) = 'wetness' - nt=nt+1 ; sfc_name2(nt) = 'clw_surf_land' - nt=nt+1 ; sfc_name2(nt) = 'clw_surf_ice' - nt=nt+1 ; sfc_name2(nt) = 'qwv_surf_land' - nt=nt+1 ; sfc_name2(nt) = 'qwv_surf_ice' - nt=nt+1 ; sfc_name2(nt) = 'tsnow_land' - nt=nt+1 ; sfc_name2(nt) = 'tsnow_ice' - nt=nt+1 ; sfc_name2(nt) = 'snowfall_acc_land' - nt=nt+1 ; sfc_name2(nt) = 'snowfall_acc_ice' - nt=nt+1 ; sfc_name2(nt) = 'sfalb_lnd' - nt=nt+1 ; sfc_name2(nt) = 'sfalb_lnd_bck' - nt=nt+1 ; sfc_name2(nt) = 'sfalb_ice' - if (Model%rdlai) then - nt=nt+1 ; sfc_name2(nt) = 'lai' - endif - else if (Model%lsm == Model%lsm_ruc .and. Model%rdlai) then - nt=nt+1 ; sfc_name2(nt) = 'lai' - endif - - if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then - nt=nt+1 ; sfc_name2(nt) = 'T_snow' - nt=nt+1 ; sfc_name2(nt) = 'T_ice' - nt=nt+1 ; sfc_name2(nt) = 'h_ML' - nt=nt+1 ; sfc_name2(nt) = 't_ML' - nt=nt+1 ; sfc_name2(nt) = 't_mnw' - nt=nt+1 ; sfc_name2(nt) = 'h_talb' - nt=nt+1 ; sfc_name2(nt) = 't_talb' - nt=nt+1 ; sfc_name2(nt) = 't_bot1' - nt=nt+1 ; sfc_name2(nt) = 't_bot2' - nt=nt+1 ; sfc_name2(nt) = 'c_t' - endif - end subroutine fill_sfcprop_names + sfc%nvar2m = nvar_s2m + call sfc%fill_2d_names(Model,warm_start) + end subroutine fill_Sfcprop_names !---------------------------------------------------------------------- ! sfc_prop_restart_read @@ -1382,36 +1071,36 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta 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)) - if (.not. allocated(sfc_name2)) then + if (.not. associated(sfc%name2)) then !--- allocate the various containers needed for restarts - allocate(sfc_name2(nvar_s2m+nvar_s2o+nvar_s2mp+nvar_s2r+nvar_s2l)) - allocate(sfc_name3(0:nvar_s3+nvar_s3mp)) - allocate(sfc_var2(nx,ny,nvar_s2m+nvar_s2o+nvar_s2mp+nvar_s2r+nvar_s2l)) + allocate(sfc%name2(nvar_s2m+nvar_s2o+nvar_s2mp+nvar_s2r+nvar_s2l)) + allocate(sfc%name3(0:nvar_s3+nvar_s3mp)) + allocate(sfc%var2(nx,ny,nvar_s2m+nvar_s2o+nvar_s2mp+nvar_s2r+nvar_s2l)) ! Note that this may cause problems with RUC LSM for coldstart runs from GFS data ! if the initial conditions do contain this variable, because Model%kice is 9 for ! RUC LSM, but tiice in the initial conditions will only have two vertical layers - allocate(sfc_var3ice(nx,ny,Model%kice)) + allocate(sfc%var3ice(nx,ny,Model%kice)) if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. (.not.warm_start)) then - allocate(sfc_var3(nx,ny,Model%lsoil,nvar_s3)) + allocate(sfc%var3(nx,ny,Model%lsoil,nvar_s3)) else if (Model%lsm == Model%lsm_ruc) then - allocate(sfc_var3(nx,ny,Model%lsoil_lsm,nvar_s3)) + allocate(sfc%var3(nx,ny,Model%lsoil_lsm,nvar_s3)) end if - sfc_var2 = -9999.0_r8 - sfc_var3 = -9999.0_r8 - sfc_var3ice= -9999.0_r8 + sfc%var2 = -9999.0_r8 + sfc%var3 = -9999.0_r8 + sfc%var3ice= -9999.0_r8 ! if (Model%lsm == Model%lsm_noahmp) then - allocate(sfc_var3sn(nx,ny,-2:0,4:6)) - allocate(sfc_var3eq(nx,ny,1:4,7:7)) - allocate(sfc_var3zn(nx,ny,-2:4,8:8)) - sfc_var3sn = -9999.0_r8 - sfc_var3eq = -9999.0_r8 - sfc_var3zn = -9999.0_r8 + allocate(sfc%var3sn(nx,ny,-2:0,4:6)) + allocate(sfc%var3eq(nx,ny,1:4,7:7)) + allocate(sfc%var3zn(nx,ny,-2:4,8:8)) + sfc%var3sn = -9999.0_r8 + sfc%var3eq = -9999.0_r8 + sfc%var3zn = -9999.0_r8 end if - call fill_Sfcprop_names(Model,sfc_name2,sfc_name3,nvar_s2m,warm_start) + call fill_Sfcprop_names(Model,nvar_s2m,warm_start) is_lsoil=.false. if ( .not. warm_start ) then @@ -1460,29 +1149,29 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta !--- register the 2D fields do num = 1,nvar_s2m - 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)) == 'snodi' .or. trim(sfc_name2(num)) == 'weasdi' & - .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' .or. trim(sfc_name2(num)) == 'emis_ice' & - .or. trim(sfc_name2(num)) == 'sncovr_ice') then + 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)) == 'snodi' .or. trim(sfc%name2(num)) == 'weasdi' & + .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' .or. trim(sfc%name2(num)) == 'emis_ice' & + .or. trim(sfc%name2(num)) == 'sncovr_ice') then if(is_lsoil) then - call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'lat','lon'/), is_optional=.true.) + 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'/),& + call register_restart_field(Sfc_restart, sfc%name2(num), var2_p, dimensions=(/'Time ','yaxis_1','xaxis_1'/),& &is_optional=.true.) end if else if(is_lsoil) then - call register_restart_field(Sfc_restart,sfc_name2(num),var2_p, dimensions=(/'lat','lon'/)) + 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'/)) + call register_restart_field(Sfc_restart,sfc%name2(num),var2_p, dimensions=(/'Time ','yaxis_1','xaxis_1'/)) end if endif enddo @@ -1491,11 +1180,11 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta mand = .false. if (Model%nstf_name(2) == 0) mand = .true. do num = nvar_s2m+1,nvar_s2m+nvar_s2o - var2_p => sfc_var2(:,:,num) + 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) + 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'/), & + call register_restart_field(Sfc_restart, sfc%name2(num), var2_p, dimensions=(/'Time ','yaxis_1','xaxis_1'/), & &is_optional=.not.mand) endif enddo @@ -1503,11 +1192,11 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta 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) + var2_p => sfc%var2(:,:,num) if(is_lsoil) then - call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'lat','lon'/) ) + 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'/) ) + call register_restart_field(Sfc_restart, sfc%name2(num), var2_p, dimensions=(/'Time ','yaxis_1','xaxis_1'/) ) end if enddo endif ! mp/ruc @@ -1517,11 +1206,11 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta 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) + 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) + 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'/), & + call register_restart_field(Sfc_restart, sfc%name2(num), var2_p, dimensions=(/'Time ','yaxis_1','xaxis_1'/), & &is_optional=.not.mand) end if enddo @@ -1531,11 +1220,11 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then mand = .false. do num = nvar_before_lake+1,nvar_before_lake+nvar_s2l - var2_p => sfc_var2(:,:,num) + 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) + 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) + call register_restart_field(Sfc_restart, sfc%name2(num),var2_p,dimensions=(/'Time ','yaxis_1','xaxis_1'/), is_optional=.not.mand) endif enddo endif @@ -1543,44 +1232,23 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta nullify(var2_p) endif ! if not allocated - - if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. (.not.warm_start)) 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 2D variables to save - sfc_name3(1) = 'tslb' - sfc_name3(2) = 'smois' - sfc_name3(3) = 'sh2o' - sfc_name3(4) = 'smfr' - sfc_name3(5) = 'flfr' - endif + call sfc%fill_3d_names(Model,warm_start) !--- register the 3D fields - 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 '/),& + var3_p => sfc%var3ice(:,:,:) + 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) + 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 '/),& + 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.) + 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 '/),& + 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 @@ -1589,17 +1257,17 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta if (Model%lsm == Model%lsm_noahmp) then 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 '/),& + 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) - call register_restart_field(Sfc_restart, sfc_name3(7), var3_p2, dimensions=(/'xaxis_1', 'yaxis_1', 'zaxis_3', 'Time '/),& + 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) - call register_restart_field(Sfc_restart, sfc_name3(8), var3_p3, dimensions=(/'xaxis_1', 'yaxis_1', 'zaxis_4', 'Time '/),& + 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) @@ -1613,7 +1281,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta !coldstart(sfcfile doesn't include noah mp fields) or not if (Model%lsm == Model%lsm_noahmp) then - sfc_var2(1,1,nvar_s2m+19) = -66666.0_r8 + sfc%var2(1,1,nvar_s2m+19) = -66666.0_r8 endif !--- read the surface restart/data @@ -1630,9 +1298,9 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta call rrfs_sd_data%copy_from_temporaries(Model,Sfcprop,Atm_block) end if -! 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)) -! write(0,*)' sfc_var2=',sfc_var2(:,:,12) +! 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)) +! write(0,*)' sfc%var2=',sfc%var2(:,:,12) !--- place the data into the block GFS containers @@ -1647,65 +1315,65 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta !--- 2D variables ! ------------ - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%slmsk) !--- slmsk - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tg3) !--- tg3 - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorl) !--- zorl composite - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alvsf) !--- alvsf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alvwf) !--- alvwf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alnsf) !--- alnsf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alnwf) !--- alnwf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%facsf) !--- facsf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%facwf) !--- facwf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%vfrac) !--- vfrac - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%canopy) !--- canopy - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%f10m) !--- f10m - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%t2m) !--- t2m - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%q2m) !--- q2m - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%vtype) !--- vtype - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%stype) !--- stype - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%uustar) !--- uustar - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%ffmm) !--- ffmm - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%ffhh) !--- ffhh - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%hice) !--- hice - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%fice) !--- fice - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tisfc) !--- tisfc - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tprcp) !--- tprcp - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%srflag) !--- srflag - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%shdmin) !--- shdmin - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%shdmax) !--- shdmax - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%slope) !--- slope - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snoalb) !--- snoalb - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sncovr) !--- sncovr - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsfc) !--- tsfc composite - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorlw) !--- zorlw (zorl on water portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdirvis_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdirnir_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdifvis_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdifnir_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%emis_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%emis_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sncovr_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slmsk) !--- slmsk + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tg3) !--- tg3 + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorl) !--- zorl composite + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvsf) !--- alvsf + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvwf) !--- alvwf + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnsf) !--- alnsf + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnwf) !--- alnwf + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facsf) !--- facsf + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facwf) !--- facwf + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vfrac) !--- vfrac + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canopy) !--- canopy + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%f10m) !--- f10m + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t2m) !--- t2m + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%q2m) !--- q2m + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vtype) !--- vtype + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stype) !--- stype + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%uustar) !--- uustar + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffmm) !--- ffmm + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffhh) !--- ffhh + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%hice) !--- hice + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fice) !--- fice + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tisfc) !--- tisfc + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tprcp) !--- tprcp + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%srflag) !--- srflag + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmin) !--- shdmin + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmax) !--- shdmax + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slope) !--- slope + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snoalb) !--- snoalb + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr) !--- sncovr + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfc) !--- tsfc composite + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlw) !--- zorlw (zorl on water portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_lnd) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_lnd) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_lnd) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_lnd) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_lnd) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice portion of a cell) if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdirvis_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdifvis_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdirnir_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdifnir_ice) -! call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sfalb_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_ice) +! call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) endif if(Model%cplwav) then !tgs - the following line is a bug. It should be nt = nt !nt = nvar_s2m-1 ! Next item will be at nvar_s2m - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorlwav) !--- (zorl from wave model) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlwav) !--- (zorl from wave model) else Sfcprop(nb)%zorlwav = Sfcprop(nb)%zorlw endif @@ -1811,7 +1479,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta if (warm_start .and. Model%kdt > 1) then do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%slmsk(ix) = sfc_var2(ii1(ix),jj1(ix),1) !--- slmsk + Sfcprop(nb)%slmsk(ix) = sfc%var2(ii1(ix),jj1(ix),1) !--- slmsk enddo endif @@ -1842,135 +1510,135 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta Sfcprop(nb)%dt_cool = zero Sfcprop(nb)%qrain = zero elseif (Model%nstf_name(2) == 0) then ! nsst restart - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tref) !--- nsstm tref - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%z_c) !--- nsstm z_c - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%c_0) !--- nsstm c_0 - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%c_d) !--- nsstm c_d - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%w_0) !--- nsstm w_0 - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%w_d) !--- nsstm w_d - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xt) !--- nsstm xt - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xs) !--- nsstm xs - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xu) !--- nsstm xu - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xv) !--- nsstm xv - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xz) !--- nsstm xz - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zm) !--- nsstm zm - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xtts) !--- nsstm xtts - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xzts) !--- nsstm xzts - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%ifd) !--- nsstm ifd - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%dt_cool) !--- nsstm dt_cool - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%qrain) !--- nsstm qrain + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tref) !--- nsstm tref + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%z_c) !--- nsstm z_c + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_0) !--- nsstm c_0 + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_d) !--- nsstm c_d + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_0) !--- nsstm w_0 + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_d) !--- nsstm w_d + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xt) !--- nsstm xt + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xs) !--- nsstm xs + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xu) !--- nsstm xu + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xv) !--- nsstm xv + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xz) !--- nsstm xz + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zm) !--- nsstm zm + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xtts) !--- nsstm xtts + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xzts) !--- nsstm xzts + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ifd) !--- nsstm ifd + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%dt_cool) !--- nsstm dt_cool + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qrain) !--- nsstm qrain endif endif if (Model%lsm == Model%lsm_ruc .and. warm_start) then !--- Extra RUC variables - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%wetness) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%clw_surf_land) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%clw_surf_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%qwv_surf_land) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%qwv_surf_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsnow_land) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsnow_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snowfallac_land) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snowfallac_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sfalb_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sfalb_lnd_bck) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sfalb_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wetness) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_land) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_land) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_land) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_land) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd_bck) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) if (Model%rdlai) then - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xlaixy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) endif else if (Model%lsm == Model%lsm_ruc) then ! Initialize RUC snow cover on ice from snow cover Sfcprop(nb)%sncovr_ice = Sfcprop(nb)%sncovr if (Model%rdlai) then - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xlaixy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) end if elseif (Model%lsm == Model%lsm_noahmp) then !--- Extra Noah MP variables - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snowxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tvxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tgxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%canicexy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%canliqxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%eahxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tahxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%cmxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%chxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%fwetxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sneqvoxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alboldxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%qsnowxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%wslakexy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zwtxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%waxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%wtxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%lfmassxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%rtmassxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%stmassxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%woodxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%stblcpxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%fastcpxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xsaixy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xlaixy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%taussxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%smcwtdxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%deeprechxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%rechxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tvxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tgxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canicexy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canliqxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%eahxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tahxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%cmxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%chxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fwetxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sneqvoxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alboldxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qsnowxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wslakexy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zwtxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%waxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wtxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%lfmassxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rtmassxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stmassxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%woodxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stblcpxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fastcpxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xsaixy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%taussxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%smcwtdxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%deeprechxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rechxy) endif if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%T_snow) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%T_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%h_ML) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%t_ML) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%t_mnw) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%h_talb) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%t_talb) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%t_bot1) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%t_bot2) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%c_t) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_snow) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_ML) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_ML) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_mnw) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_talb) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_talb) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot1) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot2) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_t) endif if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. (.not.warm_start)) then !--- 3D variables nt=0 - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc_var3,Sfcprop(nb)%stc) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc_var3,Sfcprop(nb)%smc) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc_var3,Sfcprop(nb)%slc) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc%var3,Sfcprop(nb)%stc) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc%var3,Sfcprop(nb)%smc) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc%var3,Sfcprop(nb)%slc) if (Model%lsm == Model%lsm_noahmp) then ! These use weird indexing which is lost during a Fortran subroutine call, so we use loops instead: nt=nt+1 do lsoil = -2, 0 do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%snicexy(ix,lsoil) = sfc_var3sn(ii1(ix),jj1(ix),lsoil,nt) + Sfcprop(nb)%snicexy(ix,lsoil) = sfc%var3sn(ii1(ix),jj1(ix),lsoil,nt) enddo enddo nt=nt+1 do lsoil = -2, 0 do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%snliqxy(ix,lsoil) = sfc_var3sn(ii1(ix),jj1(ix),lsoil,nt) + Sfcprop(nb)%snliqxy(ix,lsoil) = sfc%var3sn(ii1(ix),jj1(ix),lsoil,nt) enddo enddo nt=nt+1 do lsoil = -2, 0 do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%tsnoxy(ix,lsoil) = sfc_var3sn(ii1(ix),jj1(ix),lsoil,nt) + Sfcprop(nb)%tsnoxy(ix,lsoil) = sfc%var3sn(ii1(ix),jj1(ix),lsoil,nt) enddo enddo nt=nt+1 do lsoil = 1, 4 do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%smoiseq(ix,lsoil) = sfc_var3eq(ii1(ix),jj1(ix),lsoil,nt) + Sfcprop(nb)%smoiseq(ix,lsoil) = sfc%var3eq(ii1(ix),jj1(ix),lsoil,nt) enddo enddo nt=nt+1 do lsoil = -2, 4 do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%zsnsoxy(ix,lsoil) = sfc_var3zn(ii1(ix),jj1(ix),lsoil,nt) + Sfcprop(nb)%zsnsoxy(ix,lsoil) = sfc%var3zn(ii1(ix),jj1(ix),lsoil,nt) enddo enddo endif @@ -1978,16 +1646,16 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta else if (Model%lsm == Model%lsm_ruc) then !--- 3D variables nt=0 - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc_var3,Sfcprop(nb)%tslb) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc_var3,Sfcprop(nb)%smois) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc_var3,Sfcprop(nb)%sh2o) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc_var3,Sfcprop(nb)%keepsmfr) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc_var3,Sfcprop(nb)%flag_frsoil) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%tslb) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%smois) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%sh2o) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%keepsmfr) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%flag_frsoil) endif do k = 1,Model%kice do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%tiice(ix,k) = sfc_var3ice(ii1(ix),jj1(ix),k) !--- internal ice temp + Sfcprop(nb)%tiice(ix,k) = sfc%var3ice(ii1(ix),jj1(ix),k) !--- internal ice temp enddo enddo @@ -2005,12 +1673,12 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta ! exact snow layers to pass 3D fields correctly, snow layers are ! different fro grid to grid, we have to init point by point/grid. ! It has to be done after the weasd is available -! sfc_var2(1,1,32) is the first; we need this to allocate snow related fields +! sfc%var2(1,1,32) is the first; we need this to allocate snow related fields i = Atm_block%index(1)%ii(1) - isc + 1 j = Atm_block%index(1)%jj(1) - jsc + 1 - if (sfc_var2(i,j,33) < -9990.0_r8) then + if (sfc%var2(i,j,33) < -9990.0_r8) then if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing snodl') !$omp parallel do default(shared) private(nb, ix, tem) do nb = 1, Atm_block%nblks @@ -2025,7 +1693,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta enddo endif - if (sfc_var2(i,j,34) < -9990.0_r8) then + if (sfc%var2(i,j,34) < -9990.0_r8) then if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing weasdl') !$omp parallel do default(shared) private(nb, ix, tem) do nb = 1, Atm_block%nblks @@ -2040,7 +1708,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta enddo endif - if (sfc_var2(i,j,36) < -9990.0_r8) then + if (sfc%var2(i,j,36) < -9990.0_r8) then if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing tsfcl') !$omp parallel do default(shared) private(nb, ix) do nb = 1, Atm_block%nblks @@ -2050,7 +1718,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta enddo endif - if (sfc_var2(i,j,37) < -9990.0_r8) then + if (sfc%var2(i,j,37) < -9990.0_r8) then if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing zorlw') !$omp parallel do default(shared) private(nb, ix) do nb = 1, Atm_block%nblks @@ -2062,7 +1730,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta enddo endif - if (sfc_var2(i,j,38) < -9990.0_r8) then + if (sfc%var2(i,j,38) < -9990.0_r8) then if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing zorll') !$omp parallel do default(shared) private(nb, ix) do nb = 1, Atm_block%nblks @@ -2072,7 +1740,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta enddo endif - if (sfc_var2(i,j,39) < -9990.0_r8) then + if (sfc%var2(i,j,39) < -9990.0_r8) then if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing zorli') !$omp parallel do default(shared) private(nb, ix) do nb = 1, Atm_block%nblks @@ -2084,7 +1752,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta enddo endif - if (sfc_var2(i,j,45) < -9990.0_r8) then + if (sfc%var2(i,j,45) < -9990.0_r8) then if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing emis_ice') !$omp parallel do default(shared) private(nb, ix) do nb = 1, Atm_block%nblks @@ -2094,7 +1762,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta enddo endif - if (sfc_var2(i,j,46) < -9990.0_r8 .and. Model%lsm /= Model%lsm_ruc) then + if (sfc%var2(i,j,46) < -9990.0_r8 .and. Model%lsm /= Model%lsm_ruc) then if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing sncovr_ice') !$omp parallel do default(shared) private(nb, ix) do nb = 1, Atm_block%nblks @@ -2105,7 +1773,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta enddo endif - if (sfc_var2(i,j,47) < -9990.0_r8) then + if (sfc%var2(i,j,47) < -9990.0_r8) then if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing snodi') !$omp parallel do default(shared) private(nb, ix, tem) do nb = 1, Atm_block%nblks @@ -2120,7 +1788,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta enddo endif - if (sfc_var2(i,j,48) < -9990.0_r8) then + if (sfc%var2(i,j,48) < -9990.0_r8) then if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing weasdi') !$omp parallel do default(shared) private(nb, ix, tem) do nb = 1, Atm_block%nblks @@ -2136,7 +1804,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta endif if (Model%use_cice_alb) then - if (sfc_var2(i,j,49) < -9990.0_r8) then + if (sfc%var2(i,j,49) < -9990.0_r8) then !$omp parallel do default(shared) private(nb, ix) do nb = 1, Atm_block%nblks do ix = 1, Atm_block%blksz(nb) @@ -2154,7 +1822,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta endif ! Fill in composite tsfc for coldstart runs - must happen after tsfcl is computed - compute_tsfc_for_colstart: if (sfc_var2(i,j,35) < -9990.0_r8) then + compute_tsfc_for_colstart: if (sfc%var2(i,j,35) < -9990.0_r8) then if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing composite tsfc') if(Model%frac_grid) then ! 3-way composite !$omp parallel do default(shared) private(nb, ix, tem, tem1) @@ -2184,7 +1852,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta endif endif compute_tsfc_for_colstart - if (sfc_var2(i,j,nvar_s2m) < -9990.0_r8) then + if (sfc%var2(i,j,nvar_s2m) < -9990.0_r8) then if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing zorlwav') !$omp parallel do default(shared) private(nb, ix) do nb = 1, Atm_block%nblks @@ -2194,7 +1862,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta enddo endif - if (nint(sfc_var3ice(1,1,1)) == -9999) then !--- initialize internal ice temp from layer 1 and 2 soil temp + if (nint(sfc%var3ice(1,1,1)) == -9999) then !--- initialize internal ice temp from layer 1 and 2 soil temp if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing tiice') do nb = 1, Atm_block%nblks do ix = 1, Atm_block%blksz(nb) @@ -2301,16 +1969,16 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta nvar_before_lake=nvar2m+nvar2o+nvar2r+nvar2mp if (Model%lsm == Model%lsm_ruc) then - if (allocated(sfc_name2)) then + if (associated(sfc%name2)) then ! Re-allocate if one or more of the dimensions don't match - if (size(sfc_name2).ne.nvar2m+nvar2o+nvar2mp+nvar2r+nvar2l .or. & - size(sfc_name3).ne.nvar3+nvar3mp .or. & - size(sfc_var3,dim=3).ne.Model%lsoil_lsm) then + if (size(sfc%name2).ne.nvar2m+nvar2o+nvar2mp+nvar2r+nvar2l .or. & + size(sfc%name3).ne.nvar3+nvar3mp .or. & + size(sfc%var3,dim=3).ne.Model%lsoil_lsm) then !--- deallocate containers and free restart container - deallocate(sfc_name2) - deallocate(sfc_name3) - deallocate(sfc_var2) - deallocate(sfc_var3) + deallocate(sfc%name2) + deallocate(sfc%name3) + deallocate(sfc%var2) + deallocate(sfc%var3) end if end if end if @@ -2400,36 +2068,36 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta call rrfs_sd_data%write_axis(Model) end if - if (.not. allocated(sfc_name2)) then + if (.not. associated(sfc%name2)) then !--- allocate the various containers needed for restarts - allocate(sfc_name2(nvar2m+nvar2o+nvar2mp+nvar2r+nvar2l)) - allocate(sfc_name3(0:nvar3+nvar3mp)) - allocate(sfc_var2(nx,ny,nvar2m+nvar2o+nvar2mp+nvar2r+nvar2l)) + allocate(sfc%name2(nvar2m+nvar2o+nvar2mp+nvar2r+nvar2l)) + allocate(sfc%name3(0:nvar3+nvar3mp)) + allocate(sfc%var2(nx,ny,nvar2m+nvar2o+nvar2mp+nvar2r+nvar2l)) if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp) then - allocate(sfc_var3(nx,ny,Model%lsoil,nvar3)) + allocate(sfc%var3(nx,ny,Model%lsoil,nvar3)) elseif (Model%lsm == Model%lsm_ruc) then - allocate(sfc_var3(nx,ny,Model%lsoil_lsm,nvar3)) + allocate(sfc%var3(nx,ny,Model%lsoil_lsm,nvar3)) endif - sfc_var2 = -9999.0_r8 - sfc_var3 = -9999.0_r8 + sfc%var2 = -9999.0_r8 + sfc%var3 = -9999.0_r8 if (Model%lsm == Model%lsm_noahmp) then - allocate(sfc_var3sn(nx,ny,-2:0,4:6)) - allocate(sfc_var3eq(nx,ny,1:4,7:7)) - allocate(sfc_var3zn(nx,ny,-2:4,8:8)) + allocate(sfc%var3sn(nx,ny,-2:0,4:6)) + allocate(sfc%var3eq(nx,ny,1:4,7:7)) + allocate(sfc%var3zn(nx,ny,-2:4,8:8)) - sfc_var3sn = -9999.0_r8 - sfc_var3eq = -9999.0_r8 - sfc_var3zn = -9999.0_r8 + sfc%var3sn = -9999.0_r8 + sfc%var3eq = -9999.0_r8 + sfc%var3zn = -9999.0_r8 endif - call fill_Sfcprop_names(Model,sfc_name2,sfc_name3,nvar2m,.true.) + call fill_Sfcprop_names(Model,nvar2m,.true.) end if if(Model%lkm>0) then if(Model%iopt_lake==Model%iopt_lake_flake ) then if(Model%me==0) then - if(size(sfc_name2)/=nvar_before_lake+10) then -3814 format("ERROR: size mismatch size(sfc_name2)=",I0," /= nvar_before_lake+10=",I0) - write(0,3814) size(sfc_name2),nvar_before_lake+10 + if(size(sfc%name2)/=nvar_before_lake+10) then +3814 format("ERROR: size mismatch size(sfc%name2)=",I0," /= nvar_before_lake+10=",I0) + write(0,3814) size(sfc%name2),nvar_before_lake+10 endif endif else if(Model%iopt_lake==Model%iopt_lake_clm) then @@ -2444,86 +2112,66 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta !--- 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)) == 'snodi' .or. trim(sfc_name2(num)) == 'weasdi' & - .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' .or. trim(sfc_name2(num)) == 'emis_ice' & - .or. trim(sfc_name2(num)) == 'sncovr_ice' ) then - call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'xaxis_1','yaxis_1','Time '/), is_optional=.true.) + 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)) == 'snodi' .or. trim(sfc%name2(num)) == 'weasdi' & + .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' .or. trim(sfc%name2(num)) == 'emis_ice' & + .or. trim(sfc%name2(num)) == 'sncovr_ice' ) 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 '/) ) + 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 '/),& + 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 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 '/)) + var2_p => sfc%var2(:,:,num) + call register_restart_field(Sfc_restart, sfc%name2(num), var2_p, dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/)) 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) - call register_restart_field(Sfc_restart, sfc_name2(num), var2_p, dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/),& + 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_noah .or. Model%lsm == Model%lsm_noahmp) 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 + call sfc%fill_3d_names(Model,.true.) !--- 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 '/)) + 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) - call register_restart_field(Sfc_restart, sfc_name3(num), var3_p, dimensions=(/'xaxis_1', 'yaxis_1', 'zaxis_1', 'Time '/)) + 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 '/)) + 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 @@ -2531,17 +2179,17 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta 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 '/),& + 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 - var3_p2 => sfc_var3eq(:,:,:,7) - call register_restart_field(Sfc_restart, sfc_name3(7), var3_p2, dimensions=(/'xaxis_1', 'yaxis_1', 'zaxis_2', 'Time '/),& + 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 '/),& + 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) @@ -2553,8 +2201,8 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then mand = .false. do num = nvar_before_lake+1,nvar_before_lake+nvar2l - var2_p => sfc_var2(:,:,num) - call register_restart_field(Sfc_restart, sfc_name2(num),var2_p,dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/),& + 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 @@ -2577,165 +2225,165 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta nt=0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%slmsk) !--- slmsk - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tg3) !--- tg3 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorl) !--- zorl - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alvsf) !--- alvsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alvwf) !--- alvwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alnsf) !--- alnsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alnwf) !--- alnwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%facsf) !--- facsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%facwf) !--- facwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%vfrac) !--- vfrac - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%canopy)!--- canopy - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%f10m) !--- f10m - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%t2m) !--- t2m - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%q2m) !--- q2m - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%vtype) !--- vtype - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%stype) !--- stype - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%uustar)!--- uustar - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%ffmm) !--- ffmm - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%ffhh) !--- ffhh - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%hice) !--- hice - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%fice) !--- fice - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tisfc) !--- tisfc - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tprcp) !--- tprcp - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%srflag)!--- srflag - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%shdmin)!--- shdmin - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%shdmax)!--- shdmax - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%slope) !--- slope - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snoalb)!--- snoalb - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sncovr) !--- sncovr - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsfc) !--- tsfc composite - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorlw) !--- zorl (zorl on water) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdirvis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdirnir_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdifvis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdifnir_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%emis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%emis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sncovr_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slmsk) !--- slmsk + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tg3) !--- tg3 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorl) !--- zorl + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvsf) !--- alvsf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvwf) !--- alvwf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnsf) !--- alnsf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnwf) !--- alnwf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facsf) !--- facsf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facwf) !--- facwf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vfrac) !--- vfrac + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canopy)!--- canopy + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%f10m) !--- f10m + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t2m) !--- t2m + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%q2m) !--- q2m + + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vtype) !--- vtype + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stype) !--- stype + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%uustar)!--- uustar + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffmm) !--- ffmm + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffhh) !--- ffhh + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%hice) !--- hice + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fice) !--- fice + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tisfc) !--- tisfc + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tprcp) !--- tprcp + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%srflag)!--- srflag + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmin)!--- shdmin + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmax)!--- shdmax + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slope) !--- slope + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snoalb)!--- snoalb + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr) !--- sncovr + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfc) !--- tsfc composite + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlw) !--- zorl (zorl on water) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice) if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdirvis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdifvis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdirnir_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdifnir_ice) -! sfc_var2(i,j,53) = Sfcprop(nb)%sfalb_ice(ix) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_ice) +! sfc%var2(i,j,53) = Sfcprop(nb)%sfalb_ice(ix) endif if (Model%cplwav) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorlwav) !--- zorlwav (zorl from wav) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlwav) !--- zorlwav (zorl from wav) endif !--- NSSTM variables if (Model%nstf_name(1) > 0) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tref) !--- nsstm tref - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%z_c) !--- nsstm z_c - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%c_0) !--- nsstm c_0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%c_d) !--- nsstm c_d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%w_0) !--- nsstm w_0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%w_d) !--- nsstm w_d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xt) !--- nsstm xt - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xs) !--- nsstm xs - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xu) !--- nsstm xu - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xv) !--- nsstm xv - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xz) !--- nsstm xz - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zm) !--- nsstm zm - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xtts) !--- nsstm xtts - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xzts) !--- nsstm xzts - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%ifd) !--- nsstm ifd - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%dt_cool)!--- nsstm dt_cool - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%qrain) !--- nsstm qrain + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tref) !--- nsstm tref + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%z_c) !--- nsstm z_c + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_0) !--- nsstm c_0 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_d) !--- nsstm c_d + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_0) !--- nsstm w_0 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_d) !--- nsstm w_d + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xt) !--- nsstm xt + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xs) !--- nsstm xs + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xu) !--- nsstm xu + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xv) !--- nsstm xv + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xz) !--- nsstm xz + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zm) !--- nsstm zm + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xtts) !--- nsstm xtts + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xzts) !--- nsstm xzts + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ifd) !--- nsstm ifd + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%dt_cool)!--- nsstm dt_cool + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qrain) !--- nsstm qrain endif if (Model%lsm == Model%lsm_ruc) then !--- Extra RUC variables - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%wetness) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%clw_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%clw_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%qwv_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%qwv_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsnow_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsnow_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snowfallac_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snowfallac_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sfalb_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sfalb_lnd_bck) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sfalb_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wetness) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd_bck) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) if (Model%rdlai) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xlaixy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) endif else if (Model%lsm == Model%lsm_noahmp) then !--- Extra Noah MP variables - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tvxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tgxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%canicexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%canliqxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%eahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%cmxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%chxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%fwetxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sneqvoxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alboldxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%qsnowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%wslakexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zwtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%waxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%wtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%lfmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%rtmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%stmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%woodxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%stblcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%fastcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xsaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xlaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%taussxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%smcwtdxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%deeprechxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%rechxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tvxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tgxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canicexy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canliqxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%eahxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tahxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%cmxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%chxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fwetxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sneqvoxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alboldxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qsnowxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wslakexy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zwtxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%waxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wtxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%lfmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rtmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%woodxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stblcpxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fastcpxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xsaixy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%taussxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%smcwtdxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%deeprechxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rechxy) endif ! Flake if(Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%T_snow) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%T_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%h_ML) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%t_ML) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%t_mnw) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%h_talb) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%t_talb) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%t_bot1) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%t_bot2) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%c_t) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_snow) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_ML) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_ML) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_mnw) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_talb) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_talb) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot1) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot2) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_t) endif do k = 1,Model%kice do ix = 1, Atm_block%blksz(nb) ice=Sfcprop(nb)%tiice(ix,k) if(ice null() + real(kind=kind_phys), pointer, dimension(:,:,:), public :: var3ice => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3 => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3sn => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3eq => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3zn => null() + + ! FIXME: Move the sanity check code to this file so the name2 can be private: + character(len=32), pointer, dimension(:), public :: name2 => null() + + character(len=32), pointer, dimension(:), public :: name3 => null() + contains + procedure, public :: fill_2d_names => Sfc_io_fill_2d_names + procedure, public :: fill_3d_names => Sfc_io_fill_3d_names + final :: Sfc_io_final + end type Sfc_io_data_type + +contains + + subroutine Sfc_io_fill_3d_names(sfc,Model,warm_start) + implicit none + class(Sfc_io_data_type) :: sfc + type(GFS_control_type), intent(in) :: Model + logical, intent(in) :: warm_start + integer :: nt + + !--- names of the 3d variables to save + if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. (.not.warm_start)) 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 + sfc%name3(0) = 'tiice' + end subroutine Sfc_io_fill_3d_names + + subroutine Sfc_io_fill_2d_names(sfc,Model,warm_start) + implicit none + class(Sfc_io_data_type) :: sfc + type(GFS_control_type), intent(in) :: Model + logical, intent(in) :: warm_start + integer :: nt + + !--- names of the 2D variables to save + nt=0 + nt=nt+1 ; sfc%name2(nt) = 'slmsk' + nt=nt+1 ; sfc%name2(nt) = 'tsea' !tsfc + nt=nt+1 ; sfc%name2(nt) = 'sheleg' !weasd + nt=nt+1 ; sfc%name2(nt) = 'tg3' + nt=nt+1 ; sfc%name2(nt) = 'zorl' + nt=nt+1 ; sfc%name2(nt) = 'alvsf' + nt=nt+1 ; sfc%name2(nt) = 'alvwf' + nt=nt+1 ; sfc%name2(nt) = 'alnsf' + nt=nt+1 ; sfc%name2(nt) = 'alnwf' + nt=nt+1 ; sfc%name2(nt) = 'facsf' + nt=nt+1 ; sfc%name2(nt) = 'facwf' + nt=nt+1 ; sfc%name2(nt) = 'vfrac' + nt=nt+1 ; sfc%name2(nt) = 'canopy' + nt=nt+1 ; sfc%name2(nt) = 'f10m' + nt=nt+1 ; sfc%name2(nt) = 't2m' + nt=nt+1 ; sfc%name2(nt) = 'q2m' + nt=nt+1 ; sfc%name2(nt) = 'vtype' + nt=nt+1 ; sfc%name2(nt) = 'stype' + nt=nt+1 ; sfc%name2(nt) = 'uustar' + nt=nt+1 ; sfc%name2(nt) = 'ffmm' + nt=nt+1 ; sfc%name2(nt) = 'ffhh' + nt=nt+1 ; sfc%name2(nt) = 'hice' + nt=nt+1 ; sfc%name2(nt) = 'fice' + nt=nt+1 ; sfc%name2(nt) = 'tisfc' + nt=nt+1 ; sfc%name2(nt) = 'tprcp' + nt=nt+1 ; sfc%name2(nt) = 'srflag' + nt=nt+1 ; sfc%name2(nt) = 'snwdph' !snowd + nt=nt+1 ; sfc%name2(nt) = 'shdmin' + nt=nt+1 ; sfc%name2(nt) = 'shdmax' + nt=nt+1 ; sfc%name2(nt) = 'slope' + nt=nt+1 ; sfc%name2(nt) = 'snoalb' + !--- variables below here are optional + nt=nt+1 ; sfc%name2(nt) = 'sncovr' + nt=nt+1 ; sfc%name2(nt) = 'snodl' !snowd on land portion of a cell + nt=nt+1 ; sfc%name2(nt) = 'weasdl'!weasd on land portion of a cell + nt=nt+1 ; sfc%name2(nt) = 'tsfc' !tsfc composite + nt=nt+1 ; sfc%name2(nt) = 'tsfcl' !temp on land portion of a cell + nt=nt+1 ; sfc%name2(nt) = 'zorlw' !zorl on water portion of a cell + nt=nt+1 ; sfc%name2(nt) = 'zorll' !zorl on land portion of a cell + nt=nt+1 ; sfc%name2(nt) = 'zorli' !zorl on ice portion of a cell + nt=nt+1 ; sfc%name2(nt) = 'albdirvis_lnd' + nt=nt+1 ; sfc%name2(nt) = 'albdirnir_lnd' + nt=nt+1 ; sfc%name2(nt) = 'albdifvis_lnd' + nt=nt+1 ; sfc%name2(nt) = 'albdifnir_lnd' + nt=nt+1 ; sfc%name2(nt) = 'emis_lnd' + nt=nt+1 ; sfc%name2(nt) = 'emis_ice' + nt=nt+1 ; sfc%name2(nt) = 'sncovr_ice' + nt=nt+1 ; sfc%name2(nt) = 'snodi' ! snowd on ice portion of a cell + nt=nt+1 ; sfc%name2(nt) = 'weasdi'! weasd on ice portion of a cell + + if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then + nt=nt+1 ; sfc%name2(nt) = 'albdirvis_ice' + nt=nt+1 ; sfc%name2(nt) = 'albdifvis_ice' + nt=nt+1 ; sfc%name2(nt) = 'albdirnir_ice' + nt=nt+1 ; sfc%name2(nt) = 'albdifnir_ice' + endif + + if(Model%cplwav) then + nt=nt+1 ; sfc%name2(nt) = 'zorlwav' !zorl from wave component + sfc%nvar2m = nt + endif + + if (Model%nstf_name(1) > 0) then + !--- NSSTM inputs only needed when (nstf_name(1) > 0) .and. (nstf_name(2)) == 0) + nt=nt+1 ; sfc%name2(nt) = 'tref' + nt=nt+1 ; sfc%name2(nt) = 'z_c' + nt=nt+1 ; sfc%name2(nt) = 'c_0' + nt=nt+1 ; sfc%name2(nt) = 'c_d' + nt=nt+1 ; sfc%name2(nt) = 'w_0' + nt=nt+1 ; sfc%name2(nt) = 'w_d' + nt=nt+1 ; sfc%name2(nt) = 'xt' + nt=nt+1 ; sfc%name2(nt) = 'xs' + nt=nt+1 ; sfc%name2(nt) = 'xu' + nt=nt+1 ; sfc%name2(nt) = 'xv' + nt=nt+1 ; sfc%name2(nt) = 'xz' + nt=nt+1 ; sfc%name2(nt) = 'zm' + nt=nt+1 ; sfc%name2(nt) = 'xtts' + nt=nt+1 ; sfc%name2(nt) = 'xzts' + nt=nt+1 ; sfc%name2(nt) = 'd_conv' + nt=nt+1 ; sfc%name2(nt) = 'ifd' + nt=nt+1 ; sfc%name2(nt) = 'dt_cool' + nt=nt+1 ; sfc%name2(nt) = 'qrain' + endif + ! + ! Only needed when Noah MP LSM is used - 29 2D + ! + if (Model%lsm == Model%lsm_noahmp) then + nt=nt+1 ; sfc%name2(nt) = 'snowxy' + nt=nt+1 ; sfc%name2(nt) = 'tvxy' + nt=nt+1 ; sfc%name2(nt) = 'tgxy' + nt=nt+1 ; sfc%name2(nt) = 'canicexy' + nt=nt+1 ; sfc%name2(nt) = 'canliqxy' + nt=nt+1 ; sfc%name2(nt) = 'eahxy' + nt=nt+1 ; sfc%name2(nt) = 'tahxy' + nt=nt+1 ; sfc%name2(nt) = 'cmxy' + nt=nt+1 ; sfc%name2(nt) = 'chxy' + nt=nt+1 ; sfc%name2(nt) = 'fwetxy' + nt=nt+1 ; sfc%name2(nt) = 'sneqvoxy' + nt=nt+1 ; sfc%name2(nt) = 'alboldxy' + nt=nt+1 ; sfc%name2(nt) = 'qsnowxy' + nt=nt+1 ; sfc%name2(nt) = 'wslakexy' + nt=nt+1 ; sfc%name2(nt) = 'zwtxy' + nt=nt+1 ; sfc%name2(nt) = 'waxy' + nt=nt+1 ; sfc%name2(nt) = 'wtxy' + nt=nt+1 ; sfc%name2(nt) = 'lfmassxy' + nt=nt+1 ; sfc%name2(nt) = 'rtmassxy' + nt=nt+1 ; sfc%name2(nt) = 'stmassxy' + nt=nt+1 ; sfc%name2(nt) = 'woodxy' + nt=nt+1 ; sfc%name2(nt) = 'stblcpxy' + nt=nt+1 ; sfc%name2(nt) = 'fastcpxy' + nt=nt+1 ; sfc%name2(nt) = 'xsaixy' + nt=nt+1 ; sfc%name2(nt) = 'xlaixy' + nt=nt+1 ; sfc%name2(nt) = 'taussxy' + nt=nt+1 ; sfc%name2(nt) = 'smcwtdxy' + nt=nt+1 ; sfc%name2(nt) = 'deeprechxy' + nt=nt+1 ; sfc%name2(nt) = 'rechxy' + else if (Model%lsm == Model%lsm_ruc .and. warm_start) then + nt=nt+1 ; sfc%name2(nt) = 'wetness' + nt=nt+1 ; sfc%name2(nt) = 'clw_surf_land' + nt=nt+1 ; sfc%name2(nt) = 'clw_surf_ice' + nt=nt+1 ; sfc%name2(nt) = 'qwv_surf_land' + nt=nt+1 ; sfc%name2(nt) = 'qwv_surf_ice' + nt=nt+1 ; sfc%name2(nt) = 'tsnow_land' + nt=nt+1 ; sfc%name2(nt) = 'tsnow_ice' + nt=nt+1 ; sfc%name2(nt) = 'snowfall_acc_land' + nt=nt+1 ; sfc%name2(nt) = 'snowfall_acc_ice' + nt=nt+1 ; sfc%name2(nt) = 'sfalb_lnd' + nt=nt+1 ; sfc%name2(nt) = 'sfalb_lnd_bck' + nt=nt+1 ; sfc%name2(nt) = 'sfalb_ice' + if (Model%rdlai) then + nt=nt+1 ; sfc%name2(nt) = 'lai' + endif + else if (Model%lsm == Model%lsm_ruc .and. Model%rdlai) then + nt=nt+1 ; sfc%name2(nt) = 'lai' + endif + + if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then + nt=nt+1 ; sfc%name2(nt) = 'T_snow' + nt=nt+1 ; sfc%name2(nt) = 'T_ice' + nt=nt+1 ; sfc%name2(nt) = 'h_ML' + nt=nt+1 ; sfc%name2(nt) = 't_ML' + nt=nt+1 ; sfc%name2(nt) = 't_mnw' + nt=nt+1 ; sfc%name2(nt) = 'h_talb' + nt=nt+1 ; sfc%name2(nt) = 't_talb' + nt=nt+1 ; sfc%name2(nt) = 't_bot1' + nt=nt+1 ; sfc%name2(nt) = 't_bot2' + nt=nt+1 ; sfc%name2(nt) = 'c_t' + endif + end subroutine Sfc_io_fill_2d_names + + subroutine Sfc_io_final(sfc) + implicit none + type(Sfc_io_data_type) :: sfc + + ! This #define reduces code length by a lot +#define IF_ASSOC_DEALLOC_NULL(var) \ + if(associated(sfc%var)) then ; \ + deallocate(sfc%var) ; \ + nullify(sfc%var) ; \ + endif + + IF_ASSOC_DEALLOC_NULL(var2) + IF_ASSOC_DEALLOC_NULL(var3ice) + IF_ASSOC_DEALLOC_NULL(var3) + IF_ASSOC_DEALLOC_NULL(var3sn) + IF_ASSOC_DEALLOC_NULL(var3eq) + IF_ASSOC_DEALLOC_NULL(var3zn) + IF_ASSOC_DEALLOC_NULL(name2) + IF_ASSOC_DEALLOC_NULL(name3) + +#undef IF_ASSOC_DEALLOC_NULL + + end subroutine Sfc_io_final +end module FV3GFS_sfc_io From 2a081b3711768696e35d195ddcf29c486963c28e Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Fri, 5 May 2023 17:58:42 +0000 Subject: [PATCH 02/27] move RRFS SD state restart io to separate file and rename clm_lake_io.F90 --- CMakeLists.txt | 3 +- ...clm_lake_io.F90 => FV3GFS_clm_lake_io.F90} | 0 io/FV3GFS_io.F90 | 239 +---------------- io/FV3GFS_rrfs_sd_io.F90 | 249 ++++++++++++++++++ 4 files changed, 262 insertions(+), 229 deletions(-) rename io/{clm_lake_io.F90 => FV3GFS_clm_lake_io.F90} (100%) create mode 100644 io/FV3GFS_rrfs_sd_io.F90 diff --git a/CMakeLists.txt b/CMakeLists.txt index 236da3b17..bbbe9fe19 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,8 +85,9 @@ add_library(fv3atm cpl/module_block_data.F90 cpl/module_cplfields.F90 cpl/module_cap_cpl.F90 - io/clm_lake_io.F90 io/FV3GFS_common_io.F90 + io/FV3GFS_clm_lake_io.F90 + io/FV3GFS_rrfs_sd_io.F90 io/FV3GFS_sfc_io.F90 io/FV3GFS_io.F90 io/FV3GFS_restart_io.F90 diff --git a/io/clm_lake_io.F90 b/io/FV3GFS_clm_lake_io.F90 similarity index 100% rename from io/clm_lake_io.F90 rename to io/FV3GFS_clm_lake_io.F90 diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index 26bc985a5..36a97b6ac 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -114,28 +114,6 @@ module FV3GFS_io_mod logical :: use_wrtgridcomp_output = .FALSE. logical :: module_is_initialized = .FALSE. - type rrfs_sd_data_type - ! The smoke_data_type stores temporary arrays used to read or - ! write RRFS-SD restart and axis variables. - - real(kind_phys), pointer, private, dimension(:,:) :: & ! i,j variables - emdust=>null(), emseas=>null(), emanoc=>null(), fhist=>null(), coef_bb_dc=>null() - - real(kind_phys), pointer, private, dimension(:,:,:) :: & - fire_in=>null() ! i, j, fire_aux_data_levels - - contains - procedure, public :: register_axis => rrfs_sd_register_axis ! register fire_aux_data_levels axis - procedure, public :: write_axis => rrfs_sd_write_axis ! write fire_aux_data_levels variable - procedure, public :: allocate_data => rrfs_sd_allocate_data ! allocate all pointers - procedure, public :: fill_data => rrfs_sd_fill_data ! fill data with default values - procedure, public :: register_fields => rrfs_sd_register_fields ! register rrfs_sd fields - procedure, public :: deallocate_data => rrfs_sd_deallocate_data ! deallocate pointers - procedure, public :: copy_to_temporaries => rrfs_sd_copy_to_temporaries ! Copy Sfcprop to arrays - procedure, public :: copy_from_temporaries => rrfs_sd_copy_from_temporaries ! Copy arrays to Sfcprop - final :: rrfs_sd_final ! Destructor; calls deallocate_data - end type rrfs_sd_data_type - CONTAINS !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -573,6 +551,8 @@ end subroutine fill_Sfcprop_names ! !---------------------------------------------------------------------- subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) + use rrfs_sd_io + implicit none !--- interface variable definitions type(GFS_sfcprop_type), intent(inout) :: Sfcprop(:) type (block_control_type), intent(in) :: Atm_block @@ -608,7 +588,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta logical :: is_lsoil type(clm_lake_data_type) :: clm_lake - type(rrfs_sd_data_type) :: rrfs_sd_data + type(rrfs_sd_state_type) :: rrfs_sd_data nvar_o2 = 19 nvar_oro_ls_ss = 10 @@ -1143,8 +1123,8 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta if(Model%rrfs_sd) then call rrfs_sd_data%allocate_data(Model) call rrfs_sd_data%fill_data(Model, Sfcprop, Atm_block) - call rrfs_sd_data%register_axis(Model) - call rrfs_sd_data%register_fields + call rrfs_sd_data%register_axis(Model, Sfc_restart) + call rrfs_sd_data%register_fields(Sfc_restart) endif !--- register the 2D fields @@ -1888,6 +1868,8 @@ end subroutine sfc_prop_restart_read ! calls: register_restart_field, save_restart !---------------------------------------------------------------------- subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timestamp) + use rrfs_sd_io + implicit none !--- interface variable definitions type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) type(block_control_type), intent(in) :: Atm_block @@ -1919,7 +1901,7 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta integer, allocatable, dimension(:) :: buffer type(clm_lake_data_type), target :: clm_lake !--- temporary variables for storing rrfs_sd fields - type(rrfs_sd_data_type) :: rrfs_sd_data + type(rrfs_sd_state_type) :: rrfs_sd_data nvar2m = 48 if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then @@ -2064,8 +2046,8 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta if(Model%rrfs_sd) then call rrfs_sd_data%allocate_data(Model) - call rrfs_sd_data%register_axis(Model) - call rrfs_sd_data%write_axis(Model) + call rrfs_sd_data%register_axis(Model,Sfc_restart) + call rrfs_sd_data%write_axis(Model,Sfc_restart) end if if (.not. associated(sfc%name2)) then @@ -2107,7 +2089,7 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta endif if(Model%rrfs_sd) then - call rrfs_sd_data%register_fields + call rrfs_sd_data%register_fields(Sfc_restart) endif !--- register the 2D fields @@ -2446,205 +2428,6 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta end subroutine sfc_prop_restart_write - subroutine rrfs_sd_register_axis(data,Model) - implicit none - class(rrfs_sd_data_type) :: data - type(GFS_control_type), intent(in) :: Model - call register_axis(Sfc_restart, 'fire_aux_data_levels', & - dimension_length=Model%fire_aux_data_levels) - end subroutine rrfs_sd_register_axis - - subroutine rrfs_sd_write_axis(data,Model) - implicit none - class(rrfs_sd_data_type) :: data - type(GFS_control_type), intent(in) :: Model - real(kind_phys) :: fire_aux_data_levels(Model%fire_aux_data_levels) - integer :: i - - call register_field(Sfc_restart, 'fire_aux_data_levels', 'double', (/'fire_aux_data_levels'/)) - call register_variable_attribute(Sfc_restart, 'fire_aux_data_levels', 'cartesian_axis' ,'Z', str_len=1) - - do i=1,Model%fire_aux_data_levels - fire_aux_data_levels(i) = i - enddo - - call write_data(Sfc_restart, 'fire_aux_data_levels', fire_aux_data_levels) - end subroutine rrfs_sd_write_axis - - subroutine rrfs_sd_allocate_data(data,Model) - implicit none - class(rrfs_sd_data_type) :: data - type(GFS_control_type), intent(in) :: Model - integer :: nx, ny - - call data%deallocate_data - - nx=Model%nx - ny=Model%ny - - allocate(data%emdust(nx,ny)) - allocate(data%emseas(nx,ny)) - allocate(data%emanoc(nx,ny)) - allocate(data%fhist(nx,ny)) - allocate(data%coef_bb_dc(nx,ny)) - - allocate(data%fire_in(nx,ny,Model%fire_aux_data_levels)) - - end subroutine rrfs_sd_allocate_data - - subroutine rrfs_sd_fill_data(data, Model, Sfcprop, Atm_block) - ! Fills all temporary variables with default values. - ! Terrible things will happen if you don't call data%allocate_data first. - ! IMPORTANT: This must match the corresponding code in sfcprop_create in - ! GFS_typedefs.F90 - implicit none - class(rrfs_sd_data_type) :: data - type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) - type(GFS_control_type), intent(in) :: Model - type(block_control_type), intent(in) :: Atm_block - - integer :: nb, ix, isc, jsc, i, j - - isc = Model%isc - jsc = Model%jsc - -!$omp parallel do default(shared) private(i, j, nb, ix) - do nb = 1, Atm_block%nblks - 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 - - data%emdust(i,j) = 0 - data%emseas(i,j) = 0 - data%emanoc(i,j) = 0 - data%fhist(i,j) = 1. - data%coef_bb_dc(i,j) = 0 - - data%fire_in(i,j,:) = 0 - end do - end do - end subroutine rrfs_sd_fill_data - - subroutine rrfs_sd_register_fields(data) - ! Registers all restart fields needed by the RRFS-SD - ! Terrible things will happen if you don't call data%allocate_data - ! and data%register_axes first. - implicit none - class(rrfs_sd_data_type) :: data - - ! Register 2D fields - call register_restart_field(Sfc_restart, 'emdust', data%emdust, & - dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart, 'emseas', data%emseas, & - dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart, 'emanoc', data%emanoc, & - dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart, 'fhist', data%fhist, & - dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart, 'coef_bb_dc', data%coef_bb_dc, & - dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) - - ! Register 3D field - call register_restart_field(Sfc_restart, 'fire_in', data%fire_in, & - dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'fire_aux_data_levels', 'Time '/), & - is_optional=.true.) - end subroutine rrfs_sd_register_fields - - subroutine rrfs_sd_final(data) - ! Final routine for rrfs_sd_data_type, called automatically when - ! an object of that type goes out of scope. This is a wrapper - ! around data%deallocate_data() with necessary syntactic - ! differences. - implicit none - type(rrfs_sd_data_type) :: data - call rrfs_sd_deallocate_data(data) - end subroutine rrfs_sd_final - - subroutine rrfs_sd_deallocate_data(data) - ! Deallocates all data used, and nullifies the pointers. The data - ! object can safely be used again after this call. This is also - ! the implementation of the rrfs_sd_deallocate_data final routine. - implicit none - class(rrfs_sd_data_type) :: data - - ! This #define reduces code length by a lot -#define IF_ASSOC_DEALLOC_NULL(var) \ - if(associated(data%var)) then ; \ - deallocate(data%var) ; \ - nullify(data%var) ; \ - endif - - IF_ASSOC_DEALLOC_NULL(emdust) - IF_ASSOC_DEALLOC_NULL(emseas) - IF_ASSOC_DEALLOC_NULL(emanoc) - IF_ASSOC_DEALLOC_NULL(fhist) - IF_ASSOC_DEALLOC_NULL(coef_bb_dc) - - IF_ASSOC_DEALLOC_NULL(fire_in) - - ! Undefine this to avoid cluttering the cpp scope: -#undef IF_ASSOC_DEALLOC_NULL - end subroutine rrfs_sd_deallocate_data - - subroutine rrfs_sd_copy_from_temporaries(data, Model, Sfcprop, Atm_block) - implicit none - class(rrfs_sd_data_type) :: data - type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) - type(GFS_control_type), intent(in) :: Model - type(block_control_type), intent(in) :: Atm_block - - integer :: nb, ix, isc, jsc, i, j - - isc = Model%isc - jsc = Model%jsc - -!$omp parallel do default(shared) private(i, j, nb, ix) - do nb = 1, Atm_block%nblks - 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 - - Sfcprop(nb)%emdust(ix) = data%emdust(i,j) - Sfcprop(nb)%emseas(ix) = data%emseas(i,j) - Sfcprop(nb)%emanoc(ix) = data%emanoc(i,j) - Sfcprop(nb)%fhist(ix) = data%fhist(i,j) - Sfcprop(nb)%coef_bb_dc(ix) = data%coef_bb_dc(i,j) - - Sfcprop(nb)%fire_in(ix,:) = data%fire_in(i,j,:) - enddo - enddo - end subroutine rrfs_sd_copy_from_temporaries - - subroutine rrfs_sd_copy_to_temporaries(data, Model, Sfcprop, Atm_block) - implicit none - class(rrfs_sd_data_type) :: data - type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) - type(GFS_control_type), intent(in) :: Model - type(block_control_type), intent(in) :: Atm_block - - integer :: nb, ix, isc, jsc, i, j - - isc = Model%isc - jsc = Model%jsc - -!$omp parallel do default(shared) private(i, j, nb, ix) - do nb = 1, Atm_block%nblks - 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 - - data%emdust(i,j) = Sfcprop(nb)%emdust(ix) - data%emseas(i,j) = Sfcprop(nb)%emseas(ix) - data%emanoc(i,j) = Sfcprop(nb)%emanoc(ix) - data%fhist(i,j) = Sfcprop(nb)%fhist(ix) - data%coef_bb_dc(i,j) = Sfcprop(nb)%coef_bb_dc(ix) - - data%fire_in(i,j,:) = Sfcprop(nb)%fire_in(ix,:) - enddo - enddo - end subroutine rrfs_sd_copy_to_temporaries - !---------------------------------------------------------------------- ! phys_restart_read !---------------------------------------------------------------------- diff --git a/io/FV3GFS_rrfs_sd_io.F90 b/io/FV3GFS_rrfs_sd_io.F90 new file mode 100644 index 000000000..9da740e60 --- /dev/null +++ b/io/FV3GFS_rrfs_sd_io.F90 @@ -0,0 +1,249 @@ +module rrfs_sd_io + use block_control_mod, only: block_control_type + 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 GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, & + GFS_data_type, kind_phys + use GFS_restart, only: GFS_restart_type + use GFS_diagnostics, only: GFS_externaldiag_type + + implicit none + + private + + public :: rrfs_sd_state_type, rrfs_sd_state_register_axis, rrfs_sd_state_write_axis, & + rrfs_sd_state_fill_data, rrfs_sd_state_register_fields, rrfs_sd_state_deallocate_data, & + rrfs_sd_state_copy_to_temporaries, rrfs_sd_state_copy_from_temporaries, & + rrfs_sd_state_final + + type rrfs_sd_state_type + ! The rrfs_sd_state_type stores temporary arrays used to read or + ! write RRFS-SD restart and axis variables. + + real(kind_phys), pointer, private, dimension(:,:) :: & ! i,j variables + emdust=>null(), emseas=>null(), emanoc=>null(), fhist=>null(), coef_bb_dc=>null() + + real(kind_phys), pointer, private, dimension(:,:,:) :: & + fire_in=>null() ! i, j, fire_aux_data_levels + + contains + procedure, public :: register_axis => rrfs_sd_state_register_axis ! register fire_aux_data_levels axis + procedure, public :: write_axis => rrfs_sd_state_write_axis ! write fire_aux_data_levels variable + procedure, public :: allocate_data => rrfs_sd_state_allocate_data ! allocate all pointers + procedure, public :: fill_data => rrfs_sd_state_fill_data ! fill data with default values + procedure, public :: register_fields => rrfs_sd_state_register_fields ! register rrfs_sd fields + procedure, public :: deallocate_data => rrfs_sd_state_deallocate_data ! deallocate pointers + procedure, public :: copy_to_temporaries => rrfs_sd_state_copy_to_temporaries ! Copy Sfcprop to arrays + procedure, public :: copy_from_temporaries => rrfs_sd_state_copy_from_temporaries ! Copy arrays to Sfcprop + final :: rrfs_sd_state_final ! Destructor; calls deallocate_data + end type rrfs_sd_state_type + +contains + + subroutine rrfs_sd_state_register_axis(data,Model,Sfc_restart) + implicit none + class(rrfs_sd_state_type) :: data + type(FmsNetcdfDomainFile_t) :: Sfc_restart + type(GFS_control_type), intent(in) :: Model + call register_axis(Sfc_restart, 'fire_aux_data_levels', & + dimension_length=Model%fire_aux_data_levels) + end subroutine rrfs_sd_state_register_axis + + subroutine rrfs_sd_state_write_axis(data,Model,Sfc_restart) + implicit none + class(rrfs_sd_state_type) :: data + type(FmsNetcdfDomainFile_t) :: Sfc_restart + type(GFS_control_type), intent(in) :: Model + real(kind_phys) :: fire_aux_data_levels(Model%fire_aux_data_levels) + integer :: i + + call register_field(Sfc_restart, 'fire_aux_data_levels', 'double', (/'fire_aux_data_levels'/)) + call register_variable_attribute(Sfc_restart, 'fire_aux_data_levels', 'cartesian_axis' ,'Z', str_len=1) + + do i=1,Model%fire_aux_data_levels + fire_aux_data_levels(i) = i + enddo + + call write_data(Sfc_restart, 'fire_aux_data_levels', fire_aux_data_levels) + end subroutine rrfs_sd_state_write_axis + + subroutine rrfs_sd_state_allocate_data(data,Model) + implicit none + class(rrfs_sd_state_type) :: data + type(GFS_control_type), intent(in) :: Model + integer :: nx, ny + + call data%deallocate_data + + nx=Model%nx + ny=Model%ny + + allocate(data%emdust(nx,ny)) + allocate(data%emseas(nx,ny)) + allocate(data%emanoc(nx,ny)) + allocate(data%fhist(nx,ny)) + allocate(data%coef_bb_dc(nx,ny)) + + allocate(data%fire_in(nx,ny,Model%fire_aux_data_levels)) + + end subroutine rrfs_sd_state_allocate_data + + subroutine rrfs_sd_state_fill_data(data, Model, Sfcprop, Atm_block) + ! Fills all temporary variables with default values. + ! Terrible things will happen if you don't call data%allocate_data first. + ! IMPORTANT: This must match the corresponding code in sfcprop_create in + ! GFS_typedefs.F90 + implicit none + class(rrfs_sd_state_type) :: data + type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) + type(GFS_control_type), intent(in) :: Model + type(block_control_type), intent(in) :: Atm_block + + integer :: nb, ix, isc, jsc, i, j + + isc = Model%isc + jsc = Model%jsc + +!$omp parallel do default(shared) private(i, j, nb, ix) + do nb = 1, Atm_block%nblks + 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 + + data%emdust(i,j) = 0 + data%emseas(i,j) = 0 + data%emanoc(i,j) = 0 + data%fhist(i,j) = 1. + data%coef_bb_dc(i,j) = 0 + + data%fire_in(i,j,:) = 0 + end do + end do + end subroutine rrfs_sd_state_fill_data + + subroutine rrfs_sd_state_register_fields(data,Sfc_restart) + ! Registers all restart fields needed by the RRFS-SD + ! Terrible things will happen if you don't call data%allocate_data + ! and data%register_axes first. + implicit none + class(rrfs_sd_state_type) :: data + type(FmsNetcdfDomainFile_t) :: Sfc_restart + + ! Register 2D fields + call register_restart_field(Sfc_restart, 'emdust', data%emdust, & + dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) + call register_restart_field(Sfc_restart, 'emseas', data%emseas, & + dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) + call register_restart_field(Sfc_restart, 'emanoc', data%emanoc, & + dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) + call register_restart_field(Sfc_restart, 'fhist', data%fhist, & + dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) + call register_restart_field(Sfc_restart, 'coef_bb_dc', data%coef_bb_dc, & + dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) + + ! Register 3D field + call register_restart_field(Sfc_restart, 'fire_in', data%fire_in, & + dimensions=(/'xaxis_1 ', 'yaxis_1 ', & + 'fire_aux_data_levels', 'Time '/), & + is_optional=.true.) + end subroutine rrfs_sd_state_register_fields + + subroutine rrfs_sd_state_final(data) + ! Final routine for rrfs_sd_state_type, called automatically when + ! an object of that type goes out of scope. This is a wrapper + ! around data%deallocate_data() with necessary syntactic + ! differences. + implicit none + type(rrfs_sd_state_type) :: data + call rrfs_sd_state_deallocate_data(data) + end subroutine rrfs_sd_state_final + + subroutine rrfs_sd_state_deallocate_data(data) + ! Deallocates all data used, and nullifies the pointers. The data + ! object can safely be used again after this call. This is also + ! the implementation of the rrfs_sd_state_deallocate_data final routine. + implicit none + class(rrfs_sd_state_type) :: data + + ! This #define reduces code length by a lot +#define IF_ASSOC_DEALLOC_NULL(var) \ + if(associated(data%var)) then ; \ + deallocate(data%var) ; \ + nullify(data%var) ; \ + endif + + IF_ASSOC_DEALLOC_NULL(emdust) + IF_ASSOC_DEALLOC_NULL(emseas) + IF_ASSOC_DEALLOC_NULL(emanoc) + IF_ASSOC_DEALLOC_NULL(fhist) + IF_ASSOC_DEALLOC_NULL(coef_bb_dc) + + IF_ASSOC_DEALLOC_NULL(fire_in) + + ! Undefine this to avoid cluttering the cpp scope: +#undef IF_ASSOC_DEALLOC_NULL + end subroutine rrfs_sd_state_deallocate_data + + subroutine rrfs_sd_state_copy_from_temporaries(data, Model, Sfcprop, Atm_block) + implicit none + class(rrfs_sd_state_type) :: data + type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) + type(GFS_control_type), intent(in) :: Model + type(block_control_type), intent(in) :: Atm_block + + integer :: nb, ix, isc, jsc, i, j + + isc = Model%isc + jsc = Model%jsc + +!$omp parallel do default(shared) private(i, j, nb, ix) + do nb = 1, Atm_block%nblks + 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 + + Sfcprop(nb)%emdust(ix) = data%emdust(i,j) + Sfcprop(nb)%emseas(ix) = data%emseas(i,j) + Sfcprop(nb)%emanoc(ix) = data%emanoc(i,j) + Sfcprop(nb)%fhist(ix) = data%fhist(i,j) + Sfcprop(nb)%coef_bb_dc(ix) = data%coef_bb_dc(i,j) + + Sfcprop(nb)%fire_in(ix,:) = data%fire_in(i,j,:) + enddo + enddo + end subroutine rrfs_sd_state_copy_from_temporaries + + subroutine rrfs_sd_state_copy_to_temporaries(data, Model, Sfcprop, Atm_block) + implicit none + class(rrfs_sd_state_type) :: data + type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) + type(GFS_control_type), intent(in) :: Model + type(block_control_type), intent(in) :: Atm_block + + integer :: nb, ix, isc, jsc, i, j + + isc = Model%isc + jsc = Model%jsc + +!$omp parallel do default(shared) private(i, j, nb, ix) + do nb = 1, Atm_block%nblks + 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 + + data%emdust(i,j) = Sfcprop(nb)%emdust(ix) + data%emseas(i,j) = Sfcprop(nb)%emseas(ix) + data%emanoc(i,j) = Sfcprop(nb)%emanoc(ix) + data%fhist(i,j) = Sfcprop(nb)%fhist(ix) + data%coef_bb_dc(i,j) = Sfcprop(nb)%coef_bb_dc(ix) + + data%fire_in(i,j,:) = Sfcprop(nb)%fire_in(ix,:) + enddo + enddo + end subroutine rrfs_sd_state_copy_to_temporaries + +end module rrfs_sd_io From d527301a14040fad745ab4d91c6e30c24884301c Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Fri, 5 May 2023 21:39:34 +0000 Subject: [PATCH 03/27] sfc array indices are calculated in FV3GFS_sfc_io.F90 --- io/FV3GFS_io.F90 | 179 ++++++++++++------------------------------- io/FV3GFS_sfc_io.F90 | 91 +++++++++++++++++++++- 2 files changed, 141 insertions(+), 129 deletions(-) diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index 36a97b6ac..d9fe6dfb1 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -564,11 +564,11 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta integer :: i, j, k, ix, lsoil, num, nb, i_start, j_start, i_end, j_end, nt, n integer :: isc, iec, jsc, jec, npz, nx, ny integer :: id_restart - integer :: nvar_o2, nvar_s2m, nvar_s2o, nvar_s3 + integer :: nvar_o2 integer :: nvar_oro_ls_ss integer :: nvar_vegfr, nvar_soilfr - integer :: nvar_s2r, nvar_s2mp, nvar_s3mp, isnow - integer :: nvar_emi, nvar_dust12m, nvar_gbbepx, nvar_before_lake, nvar_s2l, nvar_rrfssd + integer :: isnow + integer :: nvar_emi, nvar_dust12m, nvar_gbbepx, nvar_rrfssd integer, allocatable :: ii1(:), jj1(:) real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() @@ -587,20 +587,19 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta logical :: amiopen logical :: is_lsoil + logical :: indexes_changed + type(clm_lake_data_type) :: clm_lake type(rrfs_sd_state_type) :: rrfs_sd_data + indexes_changed = sfc%calculate_indices(Model, .false., warm_start) + nvar_o2 = 19 nvar_oro_ls_ss = 10 nvar_vegfr = Model%nvegcat nvar_soilfr = Model%nsoilcat - if (Model%nstf_name(1) > 0) then - nvar_s2o = 18 - else - nvar_s2o = 0 - endif if(Model%rrfs_sd) then nvar_dust12m = 5 nvar_rrfssd = 3 @@ -611,30 +610,6 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta nvar_emi = 0 endif - if (Model%lsm == Model%lsm_ruc .and. warm_start) then - if(Model%rdlai) then - nvar_s2r = 13 - else - nvar_s2r = 12 - end if - nvar_s3 = 5 - else - if(Model%rdlai) then - nvar_s2r = 1 - else - nvar_s2r = 0 - endif - nvar_s3 = 3 - endif - - if (Model%lsm == Model%lsm_noahmp) then - nvar_s2mp = 29 !mp 2D - nvar_s3mp = 5 !mp 3D - else - nvar_s2mp = 0 !mp 2D - nvar_s3mp = 0 !mp 3D - endif - isc = Atm_block%isc iec = Atm_block%iec jsc = Atm_block%jsc @@ -774,23 +749,6 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta enddo enddo - nvar_s2m = 48 - if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - nvar_s2m = nvar_s2m + 4 -! nvar_s2m = nvar_s2m + 5 - endif - if (Model%cplwav) then - nvar_s2m = nvar_s2m + 1 - endif -! CLM Lake and Flake - if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake ) then - nvar_s2l = 10 - else - nvar_s2l = 0 - endif - - nvar_before_lake=nvar_s2m+nvar_s2o+nvar_s2r+nvar_s2mp - !--- deallocate containers and free restart container deallocate(oro_name2, oro_var2) deallocate(oro_var3v) @@ -1053,18 +1011,18 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta if (.not. associated(sfc%name2)) then !--- allocate the various containers needed for restarts - allocate(sfc%name2(nvar_s2m+nvar_s2o+nvar_s2mp+nvar_s2r+nvar_s2l)) - allocate(sfc%name3(0:nvar_s3+nvar_s3mp)) - allocate(sfc%var2(nx,ny,nvar_s2m+nvar_s2o+nvar_s2mp+nvar_s2r+nvar_s2l)) + allocate(sfc%name2(sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp+sfc%nvar2r+sfc%nvar2l)) + allocate(sfc%name3(0:sfc%nvar3+sfc%nvar3mp)) + allocate(sfc%var2(nx,ny,sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp+sfc%nvar2r+sfc%nvar2l)) ! Note that this may cause problems with RUC LSM for coldstart runs from GFS data ! if the initial conditions do contain this variable, because Model%kice is 9 for ! RUC LSM, but tiice in the initial conditions will only have two vertical layers allocate(sfc%var3ice(nx,ny,Model%kice)) if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. (.not.warm_start)) then - allocate(sfc%var3(nx,ny,Model%lsoil,nvar_s3)) + allocate(sfc%var3(nx,ny,Model%lsoil,sfc%nvar3)) else if (Model%lsm == Model%lsm_ruc) then - allocate(sfc%var3(nx,ny,Model%lsoil_lsm,nvar_s3)) + allocate(sfc%var3(nx,ny,Model%lsoil_lsm,sfc%nvar3)) end if sfc%var2 = -9999.0_r8 @@ -1080,7 +1038,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta sfc%var3zn = -9999.0_r8 end if - call fill_Sfcprop_names(Model,nvar_s2m,warm_start) + call fill_Sfcprop_names(Model,sfc%nvar2m,warm_start) is_lsoil=.false. if ( .not. warm_start ) then @@ -1128,7 +1086,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta endif !--- register the 2D fields - do num = 1,nvar_s2m + do num = 1,sfc%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' & @@ -1159,7 +1117,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta 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 + do num = sfc%nvar2m+1,sfc%nvar2m+sfc%nvar2o 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) @@ -1170,8 +1128,8 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta 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 + if (Model%lsm == Model%lsm_ruc) then ! sfc%nvar2mp = 0 + do num = sfc%nvar2m+sfc%nvar2o+1, sfc%nvar2m+sfc%nvar2o+sfc%nvar2r var2_p => sfc%var2(:,:,num) if(is_lsoil) then call register_restart_field(Sfc_restart, sfc%name2(num), var2_p, dimensions=(/'lat','lon'/) ) @@ -1183,9 +1141,9 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta ! Noah MP register only necessary only lsm = 2, not necessary has values - if (nvar_s2mp > 0) then + if (sfc%nvar2mp > 0) then mand = .false. - do num = nvar_s2m+nvar_s2o+1,nvar_s2m+nvar_s2o+nvar_s2mp + do num = sfc%nvar2m+sfc%nvar2o+1,sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp 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) @@ -1199,7 +1157,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta ! Flake if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then mand = .false. - do num = nvar_before_lake+1,nvar_before_lake+nvar_s2l + do num = sfc%nvar_before_lake+1,sfc%nvar_before_lake+sfc%nvar2l 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) @@ -1219,7 +1177,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta 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 + do num = 1,sfc%nvar3 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 '/),& @@ -1236,7 +1194,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta if (Model%lsm == Model%lsm_noahmp) then mand = .false. - do num = nvar_s3+1,nvar_s3+3 + do num = sfc%nvar3+1,sfc%nvar3+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) @@ -1261,7 +1219,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta !coldstart(sfcfile doesn't include noah mp fields) or not if (Model%lsm == Model%lsm_noahmp) then - sfc%var2(1,1,nvar_s2m+19) = -66666.0_r8 + sfc%var2(1,1,sfc%nvar2m+19) = -66666.0_r8 endif !--- read the surface restart/data @@ -1352,7 +1310,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta endif if(Model%cplwav) then !tgs - the following line is a bug. It should be nt = nt - !nt = nvar_s2m-1 ! Next item will be at nvar_s2m + !nt = sfc%nvar2m-1 ! Next item will be at sfc%nvar2m call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlwav) !--- (zorl from wave model) else Sfcprop(nb)%zorlwav = Sfcprop(nb)%zorlw @@ -1466,7 +1424,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta ! !--- NSSTM variables !tgs - the following line is a bug that will show if(Model%cplwav) = true - !nt = nvar_s2m + !nt = sfc%nvar2m if (Model%nstf_name(1) > 0) then if (Model%nstf_name(2) == 1) then ! nsst spinup !--- nsstm tref @@ -1832,7 +1790,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta endif endif compute_tsfc_for_colstart - if (sfc%var2(i,j,nvar_s2m) < -9990.0_r8) then + if (sfc%var2(i,j,sfc%nvar2m) < -9990.0_r8) then if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing zorlwav') !$omp parallel do default(shared) private(nb, ix) do nb = 1, Atm_block%nblks @@ -1880,8 +1838,6 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta integer :: i, j, k, nb, ix, lsoil, num, nt integer :: isc, iec, jsc, jec, npz, nx, ny integer :: id_restart - integer :: nvar2m, nvar2o, nvar3 - integer :: nvar2r, nvar2mp, nvar3mp, nvar_before_lake, nvar2l logical :: mand integer, allocatable :: ii1(:), jj1(:) character(len=32) :: fn_srf = 'sfc_data.nc' @@ -1903,42 +1859,11 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta !--- temporary variables for storing rrfs_sd fields type(rrfs_sd_state_type) :: rrfs_sd_data - nvar2m = 48 - if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - nvar2m = nvar2m + 4 -! nvar2m = nvar2m + 5 - endif - if (Model%cplwav) nvar2m = nvar2m + 1 - if (Model%nstf_name(1) > 0) then - nvar2o = 18 - else - nvar2o = 0 - endif - if (Model%lsm == Model%lsm_ruc) then - if (Model%rdlai) then - nvar2r = 13 - else - nvar2r = 12 - endif - nvar3 = 5 - else - nvar2r = 0 - nvar3 = 3 - endif - nvar2mp = 0 - nvar3mp = 0 - if (Model%lsm == Model%lsm_noahmp) then - nvar2mp = 29 - nvar3mp = 5 - endif -!CLM Lake and Flake - if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then - nvar2l = 10 - else - nvar2l = 0 - endif + logical :: indexes_changed - nvar_before_lake=nvar2m+nvar2o+nvar2r+nvar2mp + print *,sfc%nvar_before_lake + + indexes_changed = sfc%calculate_indices(Model, .true., .true.) isc = Atm_block%isc iec = Atm_block%iec @@ -1948,13 +1873,11 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta nx = (iec - isc + 1) ny = (jec - jsc + 1) - nvar_before_lake=nvar2m+nvar2o+nvar2r+nvar2mp - if (Model%lsm == Model%lsm_ruc) then if (associated(sfc%name2)) then ! Re-allocate if one or more of the dimensions don't match - if (size(sfc%name2).ne.nvar2m+nvar2o+nvar2mp+nvar2r+nvar2l .or. & - size(sfc%name3).ne.nvar3+nvar3mp .or. & + if (size(sfc%name2).ne.sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp+sfc%nvar2r+sfc%nvar2l .or. & + size(sfc%name3).ne.sfc%nvar3+sfc%nvar3mp .or. & size(sfc%var3,dim=3).ne.Model%lsoil_lsm) then !--- deallocate containers and free restart container deallocate(sfc%name2) @@ -2052,13 +1975,13 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta if (.not. associated(sfc%name2)) then !--- allocate the various containers needed for restarts - allocate(sfc%name2(nvar2m+nvar2o+nvar2mp+nvar2r+nvar2l)) - allocate(sfc%name3(0:nvar3+nvar3mp)) - allocate(sfc%var2(nx,ny,nvar2m+nvar2o+nvar2mp+nvar2r+nvar2l)) + allocate(sfc%name2(sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp+sfc%nvar2r+sfc%nvar2l)) + allocate(sfc%name3(0:sfc%nvar3+sfc%nvar3mp)) + allocate(sfc%var2(nx,ny,sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp+sfc%nvar2r+sfc%nvar2l)) if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp) then - allocate(sfc%var3(nx,ny,Model%lsoil,nvar3)) + allocate(sfc%var3(nx,ny,Model%lsoil,sfc%nvar3)) elseif (Model%lsm == Model%lsm_ruc) then - allocate(sfc%var3(nx,ny,Model%lsoil_lsm,nvar3)) + allocate(sfc%var3(nx,ny,Model%lsoil_lsm,sfc%nvar3)) endif sfc%var2 = -9999.0_r8 sfc%var3 = -9999.0_r8 @@ -2071,15 +1994,15 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta sfc%var3eq = -9999.0_r8 sfc%var3zn = -9999.0_r8 endif - call fill_Sfcprop_names(Model,nvar2m,.true.) + call fill_Sfcprop_names(Model,sfc%nvar2m,.true.) end if if(Model%lkm>0) then if(Model%iopt_lake==Model%iopt_lake_flake ) then if(Model%me==0) then - if(size(sfc%name2)/=nvar_before_lake+10) then -3814 format("ERROR: size mismatch size(sfc%name2)=",I0," /= nvar_before_lake+10=",I0) - write(0,3814) size(sfc%name2),nvar_before_lake+10 + if(size(sfc%name2)/=sfc%nvar_before_lake+10) then +3814 format("ERROR: size mismatch size(sfc%name2)=",I0," /= sfc%nvar_before_lake+10=",I0) + write(0,3814) size(sfc%name2),sfc%nvar_before_lake+10 endif endif else if(Model%iopt_lake==Model%iopt_lake_clm) then @@ -2093,7 +2016,7 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta endif !--- register the 2D fields - do num = 1,nvar2m + do num = 1,sfc%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' & @@ -2114,21 +2037,21 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta if (Model%nstf_name(1) > 0) then mand = .false. if (Model%nstf_name(2) ==0) mand = .true. - do num = nvar2m+1,nvar2m+nvar2o + do num = sfc%nvar2m+1,sfc%nvar2m+sfc%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 - if (Model%lsm == Model%lsm_ruc) then ! nvar2mp =0 - do num = nvar2m+nvar2o+1, nvar2m+nvar2o+nvar2r + if (Model%lsm == Model%lsm_ruc) then ! sfc%nvar2mp =0 + do num = sfc%nvar2m+sfc%nvar2o+1, sfc%nvar2m+sfc%nvar2o+sfc%nvar2r var2_p => sfc%var2(:,:,num) call register_restart_field(Sfc_restart, sfc%name2(num), var2_p, dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/)) enddo - else if (Model%lsm == Model%lsm_noahmp) then ! nvar2r =0 + else if (Model%lsm == Model%lsm_noahmp) then ! sfc%nvar2r =0 mand = .true. ! actually should be true since it is after cold start - do num = nvar2m+nvar2o+1,nvar2m+nvar2o+nvar2mp + do num = sfc%nvar2m+sfc%nvar2o+1,sfc%nvar2m+sfc%nvar2o+sfc%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) @@ -2145,13 +2068,13 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta ! endif if(Model%lsm == Model%lsm_ruc) then - do num = 1,nvar3 + do num = 1,sfc%nvar3 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 + do num = 1,sfc%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 @@ -2160,7 +2083,7 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta if (Model%lsm == Model%lsm_noahmp) then mand = .true. - do num = nvar3+1,nvar3+3 + do num = sfc%nvar3+1,sfc%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) @@ -2182,7 +2105,7 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta !Flake if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then mand = .false. - do num = nvar_before_lake+1,nvar_before_lake+nvar2l + do num = sfc%nvar_before_lake+1,sfc%nvar_before_lake+sfc%nvar2l 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) diff --git a/io/FV3GFS_sfc_io.F90 b/io/FV3GFS_sfc_io.F90 index d0afbfd03..d13c54782 100644 --- a/io/FV3GFS_sfc_io.F90 +++ b/io/FV3GFS_sfc_io.F90 @@ -17,6 +17,7 @@ module FV3GFS_sfc_io private public :: Sfc_io_data_type + public :: Sfc_io_fill_2d_names, Sfc_io_fill_3d_names, Sfc_io_calculate_indices, Sfc_io_final type Sfc_io_data_type integer, public :: nvar2o = 0 @@ -48,18 +49,95 @@ module FV3GFS_sfc_io real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3eq => null() real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3zn => null() - ! FIXME: Move the sanity check code to this file so the name2 can be private: character(len=32), pointer, dimension(:), public :: name2 => null() character(len=32), pointer, dimension(:), public :: name3 => null() contains procedure, public :: fill_2d_names => Sfc_io_fill_2d_names procedure, public :: fill_3d_names => Sfc_io_fill_3d_names + procedure, public :: calculate_indices => Sfc_io_calculate_indices final :: Sfc_io_final end type Sfc_io_data_type contains + function Sfc_io_calculate_indices(sfc, Model, for_write, warm_start) + implicit none + class(Sfc_io_data_type) :: sfc + type(GFS_control_type), intent(in) :: Model + logical :: Sfc_io_calculate_indices + logical, intent(in) :: for_write, warm_start + + integer :: nvar2m, nvar2o, nvar3, nvar2r, nvar2mp, nvar3mp, nvar2l + integer :: nvar_before_lake + + nvar2m = 48 + if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then + nvar2m = nvar2m + 4 + !nvar2m = nvar2m + 5 + endif + if (Model%cplwav) then + nvar2m = nvar2m + 1 + endif + if (Model%nstf_name(1) > 0) then + nvar2o = 18 + else + nvar2o = 0 + endif + if (Model%lsm == Model%lsm_ruc .and. warm_start) then + if (Model%rdlai) then + nvar2r = 13 + else + nvar2r = 12 + endif + nvar3 = 5 + else + if(for_write .and. Model%rdlai) then + nvar2r = 1 + else + nvar2r = 0 + endif + nvar3 = 3 + endif + if (Model%lsm == Model%lsm_noahmp) then + nvar2mp = 29 + nvar3mp = 5 + else + nvar2mp = 0 + nvar3mp = 0 + endif + !CLM Lake and Flake + if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then + nvar2l = 10 + else + nvar2l = 0 + endif + + nvar_before_lake=nvar2m+nvar2o+nvar2r+nvar2mp + + Sfc_io_calculate_indices = & + nvar2m /= sfc%nvar2m .or. & + nvar2o /= sfc%nvar2o .or. & + nvar3 /= sfc%nvar3 .or. & + nvar2r /= sfc%nvar2r .or. & + nvar2mp /= sfc%nvar2mp .or. & + nvar3mp /= sfc%nvar3mp .or. & + nvar2l /= sfc%nvar2l .or. & + nvar2m /= sfc%nvar2m .or. & + nvar_before_lake /= sfc%nvar_before_lake + + sfc%nvar2m = nvar2m + sfc%nvar2o = nvar2o + sfc%nvar3 = nvar3 + sfc%nvar2r = nvar2r + sfc%nvar2mp = nvar2mp + sfc%nvar3mp = nvar3mp + sfc%nvar2l = nvar2l + sfc%nvar2m = nvar2m + sfc%nvar_before_lake = nvar_before_lake + + end function Sfc_io_calculate_indices + subroutine Sfc_io_fill_3d_names(sfc,Model,warm_start) implicit none class(Sfc_io_data_type) :: sfc @@ -254,6 +332,17 @@ subroutine Sfc_io_final(sfc) implicit none type(Sfc_io_data_type) :: sfc + sfc%nvar2m=0 + sfc%nvar2o=0 + sfc%nvar2l=0 + sfc%nvar3=0 + sfc%nvar2r=0 + sfc%nvar2mp=0 + sfc%nvar3mp=0 + sfc%nvar2m=0 + sfc%nvar_before_lake=0 + sfc%is_lsoil=.false. + ! This #define reduces code length by a lot #define IF_ASSOC_DEALLOC_NULL(var) \ if(associated(sfc%var)) then ; \ From e597b95c94adda38b2cfbff2f9446ca51c72c6fc Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Sat, 6 May 2023 00:24:09 +0000 Subject: [PATCH 04/27] move rrfs sd emissions input code to FV3GFS_rrfs_sd_io.F90 --- io/FV3GFS_common_io.F90 | 20 +++ io/FV3GFS_io.F90 | 233 ++++++++------------------- io/FV3GFS_rrfs_sd_io.F90 | 340 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 401 insertions(+), 192 deletions(-) diff --git a/io/FV3GFS_common_io.F90 b/io/FV3GFS_common_io.F90 index 61c6bf817..8d3f23df4 100644 --- a/io/FV3GFS_common_io.F90 +++ b/io/FV3GFS_common_io.F90 @@ -1,5 +1,6 @@ module FV3GFS_common_io use GFS_typedefs, only: kind_phys + use block_control_mod, only: block_control_type implicit none private @@ -31,8 +32,27 @@ module FV3GFS_common_io copy_to_GFS_Data_3d_slice_phys2phys end interface copy_to_GFS_Data + public :: get_nx_ny_from_atm + contains + pure subroutine get_nx_ny_from_atm(Atm_block, nx, ny) + implicit none + type(block_control_type), intent(in) :: Atm_block + integer, intent(out), optional :: nx, ny + integer :: isc, iec, jsc, jec + if(present(nx)) then + isc = Atm_block%isc + iec = Atm_block%iec + nx = (iec - isc + 1) + end if + if(present(ny)) then + jsc = Atm_block%jsc + jec = Atm_block%jec + ny = (jec - jsc + 1) + endif + end subroutine get_nx_ny_from_atm + pure subroutine copy_from_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) implicit none integer, intent(in) :: ii1(:), jj1(:), isc, jsc diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index d9fe6dfb1..5fe3718fc 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -77,10 +77,6 @@ module FV3GFS_io_mod character(len=32), allocatable, dimension(:) :: oro_ls_ss_name real(kind=kind_phys), allocatable, target, dimension(:,:,:) :: oro_ls_var, oro_ss_var, oro_var3v, oro_var3s real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: phy_var3 - character(len=32), allocatable, dimension(:) :: dust12m_name, emi_name, rrfssd_name - real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: rrfssd_var - real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: dust12m_var - real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: emi_var !--- Noah MP restart containers real(kind=kind_phys) :: zhour ! @@ -568,7 +564,6 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta integer :: nvar_oro_ls_ss integer :: nvar_vegfr, nvar_soilfr integer :: isnow - integer :: nvar_emi, nvar_dust12m, nvar_gbbepx, nvar_rrfssd integer, allocatable :: ii1(:), jj1(:) real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() @@ -590,7 +585,8 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta logical :: indexes_changed type(clm_lake_data_type) :: clm_lake - type(rrfs_sd_state_type) :: rrfs_sd_data + type(rrfs_sd_state_type) :: rrfs_sd_state + type(rrfs_sd_emissions_type) :: rrfs_sd_emis indexes_changed = sfc%calculate_indices(Model, .false., warm_start) @@ -600,16 +596,6 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta nvar_vegfr = Model%nvegcat nvar_soilfr = Model%nsoilcat - if(Model%rrfs_sd) then - nvar_dust12m = 5 - nvar_rrfssd = 3 - nvar_emi = 1 - else - nvar_dust12m = 0 - nvar_rrfssd = 0 - nvar_emi = 0 - endif - isc = Atm_block%isc iec = Atm_block%iec jsc = Atm_block%jsc @@ -756,153 +742,60 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta if_smoke: if(Model%rrfs_sd) then ! for RRFS-SD - !--- Dust input FILE - !--- open file - infile=trim(indir)//'/'//trim(fn_dust12m) - amiopen=open_file(dust12m_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(dust12m_name)) then - !--- allocate the various containers needed for fengsha dust12m data - allocate(dust12m_name(nvar_dust12m)) - allocate(dust12m_var(nx,ny,12,nvar_dust12m)) - - dust12m_name(1) = 'clay' - dust12m_name(2) = 'rdrag' - dust12m_name(3) = 'sand' - dust12m_name(4) = 'ssm' - dust12m_name(5) = 'uthr' - - !--- register axis - call register_axis(dust12m_restart, 'lon', 'X') - call register_axis(dust12m_restart, 'lat', 'Y') - call register_axis(dust12m_restart, 'time', 12) - !--- register the 3D fields - do num = 1,nvar_dust12m - var3_p2 => dust12m_var(:,:,:,num) - call register_restart_field(dust12m_restart, dust12m_name(num), var3_p2, dimensions=(/'time', 'lat ', 'lon '/),& - &is_optional=.not.mand) - enddo - nullify(var3_p2) - endif - - !--- read new GSL created dust12m restart/data - call mpp_error(NOTE,'reading dust12m information from INPUT/dust12m_data.tile*.nc') - call read_restart(dust12m_restart) - call close_file(dust12m_restart) - - do nb = 1, Atm_block%nblks - !--- 3D variables - 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 - do k = 1, 12 - Sfcprop(nb)%dust12m_in(ix,k,1) = dust12m_var(i,j,k,1) - Sfcprop(nb)%dust12m_in(ix,k,2) = dust12m_var(i,j,k,2) - Sfcprop(nb)%dust12m_in(ix,k,3) = dust12m_var(i,j,k,3) - Sfcprop(nb)%dust12m_in(ix,k,4) = dust12m_var(i,j,k,4) - Sfcprop(nb)%dust12m_in(ix,k,5) = dust12m_var(i,j,k,5) - enddo - enddo - enddo - - deallocate(dust12m_name,dust12m_var) - - read_emi: if(nvar_emi>0) then - !--- open anthropogenic emission file - infile=trim(indir)//'/'//trim(fn_emi) - amiopen=open_file(emi_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(emi_name)) then - !--- allocate the various containers needed for anthropogenic emission data - if(allocated(emi_name)) deallocate(emi_name) - if(allocated(emi_var)) deallocate(emi_var) - allocate(emi_name(nvar_emi)) - allocate(emi_var(nx,ny,1,nvar_emi)) - - emi_name(1) = 'e_oc' - !--- register axis - call register_axis( emi_restart, 'time', 1) ! only read first time level, even if multiple are present - call register_axis( emi_restart, "grid_xt", 'X' ) - call register_axis( emi_restart, "grid_yt", 'Y' ) - !--- register the 2D fields - do num = 1,nvar_emi - var3_p2 => emi_var(:,:,:,num) - call register_restart_field(emi_restart, emi_name(num), var3_p2, dimensions=(/'time ','grid_yt','grid_xt'/)) - enddo - nullify(var3_p2) - !endif - - !--- read anthropogenic emi restart/data - call mpp_error(NOTE,'reading emi information from INPUT/emi_data.tile*.nc') - call read_restart(emi_restart) - call close_file(emi_restart) - - do num=1,nvar_emi - do nb = 1, Atm_block%nblks - !--- 2D variables - 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 - Sfcprop(nb)%emi_in(ix,num) = emi_var(i,j,1,num) - enddo - enddo - enddo - - !--- deallocate containers and free restart container - deallocate(emi_name, emi_var) - endif read_emi - - !--- Dust input FILE - !--- open file - infile=trim(indir)//'/'//trim(fn_rrfssd) - amiopen=open_file(rrfssd_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(rrfssd_name)) then - !--- allocate the various containers needed for rrfssd fire data - allocate(rrfssd_name(nvar_rrfssd)) - allocate(rrfssd_var(nx,ny,24,nvar_rrfssd)) - - rrfssd_name(1) = 'ebb_smoke_hr' - rrfssd_name(2) = 'frp_avg_hr' - rrfssd_name(3) = 'frp_std_hr' + !--- Dust input FILE + !--- open file + infile=trim(indir)//'/'//trim(fn_dust12m) + amiopen=open_file(dust12m_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) ) + + !--- Register axes and variables, allocate memory: + call rrfs_sd_emis%register_dust12m(dust12m_restart, Atm_block) + + !--- read new GSL created dust12m restart/data + call mpp_error(NOTE,'reading dust12m information from INPUT/dust12m_data.tile*.nc') + call read_restart(dust12m_restart) + call close_file(dust12m_restart) + + !--- Copy to Sfcprop and free temporary arrays: + call rrfs_sd_emis%copy_dust12m(Sfcprop, Atm_block) + + !---------------------------------------------- + + !--- open anthropogenic emission file + infile=trim(indir)//'/'//trim(fn_emi) + amiopen=open_file(emi_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) ) + + ! Register axes and variables, allocate memory + call rrfs_sd_emis%register_emi(emi_restart, Atm_block) + + !--- read anthropogenic emi restart/data + call mpp_error(NOTE,'reading emi information from INPUT/emi_data.tile*.nc') + call read_restart(emi_restart) + call close_file(emi_restart) + + !--- Copy to Sfcprop and free temporary arrays: + call rrfs_sd_emis%copy_emi(Sfcprop, Atm_block) + + !---------------------------------------------- + + !--- Dust input FILE + !--- open file + infile=trim(indir)//'/'//trim(fn_rrfssd) + amiopen=open_file(rrfssd_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) ) - !--- register axis - call register_axis(rrfssd_restart, 'lon', 'X') - call register_axis(rrfssd_restart, 'lat', 'Y') - call register_axis(rrfssd_restart, 't', 24) - !--- register the 3D fields - mand = .false. - do num = 1,nvar_rrfssd - var3_p2 => rrfssd_var(:,:,:,num) - call register_restart_field(rrfssd_restart, rrfssd_name(num), var3_p2, dimensions=(/'t ', 'lat', 'lon'/),& - &is_optional=.not.mand) - enddo - nullify(var3_p2) - endif + ! Register axes and variables, allocate memory + call rrfs_sd_emis%register_fire(rrfssd_restart, Atm_block) - !--- read new GSL created rrfssd restart/data - call mpp_error(NOTE,'reading rrfssd information from INPUT/SMOKE_RRFS_data.nc') - call read_restart(rrfssd_restart) - call close_file(rrfssd_restart) + !--- read new GSL created rrfssd restart/data + call mpp_error(NOTE,'reading rrfssd information from INPUT/SMOKE_RRFS_data.nc') + call read_restart(rrfssd_restart) + call close_file(rrfssd_restart) - do nb = 1, Atm_block%nblks - !--- 3D variables - 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 - !--- assign hprime(1:10) and hprime(15:24) with new oro stat data - do k = 1, 24 - Sfcprop(nb)%smoke_RRFS(ix,k,1) = rrfssd_var(i,j,k,1) - Sfcprop(nb)%smoke_RRFS(ix,k,2) = rrfssd_var(i,j,k,2) - Sfcprop(nb)%smoke_RRFS(ix,k,3) = rrfssd_var(i,j,k,3) - enddo - enddo - enddo + !--- Copy to Sfcprop and free temporary arrays: + call rrfs_sd_emis%copy_fire(Sfcprop, Atm_block) - deallocate(rrfssd_name, rrfssd_var) endif if_smoke ! RRFS_SD !--- Modify/read-in additional orographic static fields for GSL drag suite @@ -1079,10 +972,10 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta endif if(Model%rrfs_sd) then - call rrfs_sd_data%allocate_data(Model) - call rrfs_sd_data%fill_data(Model, Sfcprop, Atm_block) - call rrfs_sd_data%register_axis(Model, Sfc_restart) - call rrfs_sd_data%register_fields(Sfc_restart) + call rrfs_sd_state%allocate_data(Model) + call rrfs_sd_state%fill_data(Model, Sfcprop, Atm_block) + call rrfs_sd_state%register_axis(Model, Sfc_restart) + call rrfs_sd_state%register_fields(Sfc_restart) endif !--- register the 2D fields @@ -1233,7 +1126,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta endif if(Model%rrfs_sd) then - call rrfs_sd_data%copy_from_temporaries(Model,Sfcprop,Atm_block) + call rrfs_sd_state%copy_from_temporaries(Model,Sfcprop,Atm_block) end if ! write(0,*)' stype read in min,max=',minval(sfc%var2(:,:,35)),maxval(sfc%var2(:,:,35)),' sfc%name2=',sfc%name2(35) @@ -1857,7 +1750,7 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta integer, allocatable, dimension(:) :: buffer type(clm_lake_data_type), target :: clm_lake !--- temporary variables for storing rrfs_sd fields - type(rrfs_sd_state_type) :: rrfs_sd_data + type(rrfs_sd_state_type) :: rrfs_sd_state logical :: indexes_changed @@ -1968,9 +1861,9 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta endif if(Model%rrfs_sd) then - call rrfs_sd_data%allocate_data(Model) - call rrfs_sd_data%register_axis(Model,Sfc_restart) - call rrfs_sd_data%write_axis(Model,Sfc_restart) + call rrfs_sd_state%allocate_data(Model) + call rrfs_sd_state%register_axis(Model,Sfc_restart) + call rrfs_sd_state%write_axis(Model,Sfc_restart) end if if (.not. associated(sfc%name2)) then @@ -2012,7 +1905,7 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta endif if(Model%rrfs_sd) then - call rrfs_sd_data%register_fields(Sfc_restart) + call rrfs_sd_state%register_fields(Sfc_restart) endif !--- register the 2D fields @@ -2118,7 +2011,7 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta endif if(Model%rrfs_sd) then - call rrfs_sd_data%copy_to_temporaries(Model,Sfcprop,Atm_block) + call rrfs_sd_state%copy_to_temporaries(Model,Sfcprop,Atm_block) endif !$omp parallel do default(shared) private(i, j, nb, ix, nt, ii1, jj1, lsoil, k, ice) diff --git a/io/FV3GFS_rrfs_sd_io.F90 b/io/FV3GFS_rrfs_sd_io.F90 index 9da740e60..f166668e4 100644 --- a/io/FV3GFS_rrfs_sd_io.F90 +++ b/io/FV3GFS_rrfs_sd_io.F90 @@ -1,15 +1,16 @@ module rrfs_sd_io use block_control_mod, only: block_control_type 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 + 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 GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, & - GFS_data_type, kind_phys + GFS_data_type, kind_phys use GFS_restart, only: GFS_restart_type use GFS_diagnostics, only: GFS_externaldiag_type + use FV3GFS_common_io, only: get_nx_ny_from_atm implicit none @@ -20,6 +21,13 @@ module rrfs_sd_io rrfs_sd_state_copy_to_temporaries, rrfs_sd_state_copy_from_temporaries, & rrfs_sd_state_final + public :: rrfs_sd_emissions_type, rrfs_sd_emissions_final, & + rrfs_sd_emissions_register_dust12m, rrfs_sd_emissions_copy_dust12m, & + rrfs_sd_emissions_register_emi, rrfs_sd_emissions_copy_emi, & + rrfs_sd_emissions_register_fire, rrfs_sd_emissions_copy_fire + + ! -------------------------------------------------------------------- + type rrfs_sd_state_type ! The rrfs_sd_state_type stores temporary arrays used to read or ! write RRFS-SD restart and axis variables. @@ -42,8 +50,44 @@ module rrfs_sd_io final :: rrfs_sd_state_final ! Destructor; calls deallocate_data end type rrfs_sd_state_type + ! -------------------------------------------------------------------- + + type rrfs_sd_emissions_type + integer, private :: nvar_dust12m = 5 + integer, private :: nvar_emi = 1 + integer, private :: nvar_fire = 3 + + character(len=32), pointer, dimension(:), private :: dust12m_name => null() + character(len=32), pointer, dimension(:), private :: emi_name => null() + character(len=32), pointer, dimension(:), private :: fire_name => null() + + real(kind=kind_phys), pointer, dimension(:,:,:,:), private :: dust12m_var => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), private :: emi_var => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), private :: fire_var => null() + + contains + + procedure, public :: register_dust12m => rrfs_sd_emissions_register_dust12m + procedure, public :: copy_dust12m => rrfs_sd_emissions_copy_dust12m + + procedure, public :: register_emi => rrfs_sd_emissions_register_emi + procedure, public :: copy_emi => rrfs_sd_emissions_copy_emi + + procedure, public :: register_fire => rrfs_sd_emissions_register_fire + procedure, public :: copy_fire => rrfs_sd_emissions_copy_fire + + final :: rrfs_sd_emissions_final + end type rrfs_sd_emissions_type + + ! -------------------------------------------------------------------- + contains + + ! -------------------------------------------------------------------- + ! -- RRFS_SD_STATE IMPLEMENTATION ------------------------------------ + ! -------------------------------------------------------------------- + subroutine rrfs_sd_state_register_axis(data,Model,Sfc_restart) implicit none class(rrfs_sd_state_type) :: data @@ -53,6 +97,8 @@ subroutine rrfs_sd_state_register_axis(data,Model,Sfc_restart) dimension_length=Model%fire_aux_data_levels) end subroutine rrfs_sd_state_register_axis + ! -------------------------------------------------------------------- + subroutine rrfs_sd_state_write_axis(data,Model,Sfc_restart) implicit none class(rrfs_sd_state_type) :: data @@ -71,6 +117,8 @@ subroutine rrfs_sd_state_write_axis(data,Model,Sfc_restart) call write_data(Sfc_restart, 'fire_aux_data_levels', fire_aux_data_levels) end subroutine rrfs_sd_state_write_axis + ! -------------------------------------------------------------------- + subroutine rrfs_sd_state_allocate_data(data,Model) implicit none class(rrfs_sd_state_type) :: data @@ -92,6 +140,8 @@ subroutine rrfs_sd_state_allocate_data(data,Model) end subroutine rrfs_sd_state_allocate_data + ! -------------------------------------------------------------------- + subroutine rrfs_sd_state_fill_data(data, Model, Sfcprop, Atm_block) ! Fills all temporary variables with default values. ! Terrible things will happen if you don't call data%allocate_data first. @@ -108,7 +158,7 @@ subroutine rrfs_sd_state_fill_data(data, Model, Sfcprop, Atm_block) isc = Model%isc jsc = Model%jsc -!$omp parallel do default(shared) private(i, j, nb, ix) + !$omp parallel do default(shared) private(i, j, nb, ix) do nb = 1, Atm_block%nblks do ix = 1, Atm_block%blksz(nb) i = Atm_block%index(nb)%ii(ix) - isc + 1 @@ -125,6 +175,8 @@ subroutine rrfs_sd_state_fill_data(data, Model, Sfcprop, Atm_block) end do end subroutine rrfs_sd_state_fill_data + ! -------------------------------------------------------------------- + subroutine rrfs_sd_state_register_fields(data,Sfc_restart) ! Registers all restart fields needed by the RRFS-SD ! Terrible things will happen if you don't call data%allocate_data @@ -148,10 +200,12 @@ subroutine rrfs_sd_state_register_fields(data,Sfc_restart) ! Register 3D field call register_restart_field(Sfc_restart, 'fire_in', data%fire_in, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'fire_aux_data_levels', 'Time '/), & + 'fire_aux_data_levels', 'Time '/), & is_optional=.true.) end subroutine rrfs_sd_state_register_fields + ! -------------------------------------------------------------------- + subroutine rrfs_sd_state_final(data) ! Final routine for rrfs_sd_state_type, called automatically when ! an object of that type goes out of scope. This is a wrapper @@ -162,6 +216,8 @@ subroutine rrfs_sd_state_final(data) call rrfs_sd_state_deallocate_data(data) end subroutine rrfs_sd_state_final + ! -------------------------------------------------------------------- + subroutine rrfs_sd_state_deallocate_data(data) ! Deallocates all data used, and nullifies the pointers. The data ! object can safely be used again after this call. This is also @@ -188,6 +244,8 @@ subroutine rrfs_sd_state_deallocate_data(data) #undef IF_ASSOC_DEALLOC_NULL end subroutine rrfs_sd_state_deallocate_data + ! -------------------------------------------------------------------- + subroutine rrfs_sd_state_copy_from_temporaries(data, Model, Sfcprop, Atm_block) implicit none class(rrfs_sd_state_type) :: data @@ -195,16 +253,13 @@ subroutine rrfs_sd_state_copy_from_temporaries(data, Model, Sfcprop, Atm_block) type(GFS_control_type), intent(in) :: Model type(block_control_type), intent(in) :: Atm_block - integer :: nb, ix, isc, jsc, i, j - - isc = Model%isc - jsc = Model%jsc + integer :: nb, ix, i, j -!$omp parallel do default(shared) private(i, j, nb, ix) + !$omp parallel do default(shared) private(i, j, nb, ix) do nb = 1, Atm_block%nblks 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 + i = Atm_block%index(nb)%ii(ix) - Atm_block%isc + 1 + j = Atm_block%index(nb)%jj(ix) - Atm_block%jsc + 1 Sfcprop(nb)%emdust(ix) = data%emdust(i,j) Sfcprop(nb)%emseas(ix) = data%emseas(i,j) @@ -217,6 +272,8 @@ subroutine rrfs_sd_state_copy_from_temporaries(data, Model, Sfcprop, Atm_block) enddo end subroutine rrfs_sd_state_copy_from_temporaries + ! -------------------------------------------------------------------- + subroutine rrfs_sd_state_copy_to_temporaries(data, Model, Sfcprop, Atm_block) implicit none class(rrfs_sd_state_type) :: data @@ -224,16 +281,13 @@ subroutine rrfs_sd_state_copy_to_temporaries(data, Model, Sfcprop, Atm_block) type(GFS_control_type), intent(in) :: Model type(block_control_type), intent(in) :: Atm_block - integer :: nb, ix, isc, jsc, i, j - - isc = Model%isc - jsc = Model%jsc + integer :: nb, ix, i, j -!$omp parallel do default(shared) private(i, j, nb, ix) + !$omp parallel do default(shared) private(i, j, nb, ix) do nb = 1, Atm_block%nblks 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 + i = Atm_block%index(nb)%ii(ix) - Atm_block%isc + 1 + j = Atm_block%index(nb)%jj(ix) - Atm_block%jsc + 1 data%emdust(i,j) = Sfcprop(nb)%emdust(ix) data%emseas(i,j) = Sfcprop(nb)%emseas(ix) @@ -246,4 +300,246 @@ subroutine rrfs_sd_state_copy_to_temporaries(data, Model, Sfcprop, Atm_block) enddo end subroutine rrfs_sd_state_copy_to_temporaries + ! -------------------------------------------------------------------- + ! -- RRFS_SD_EMISSIONS IMPLEMENTATION -------------------------------- + ! -------------------------------------------------------------------- + + subroutine rrfs_sd_emissions_register_dust12m(data, restart, Atm_block) + implicit none + class(rrfs_sd_emissions_type) :: data + type(FmsNetcdfDomainFile_t) :: restart + type(block_control_type), intent(in) :: Atm_block + + real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p2 => NULL() + integer :: num, nx, ny + + if(associated(data%dust12m_name)) then + deallocate(data%dust12m_name) + nullify(data%dust12m_name) + endif + if(associated(data%dust12m_var)) then + deallocate(data%dust12m_var) + nullify(data%dust12m_var) + endif + + call get_nx_ny_from_atm(Atm_block, nx, ny) + allocate(data%dust12m_name(data%nvar_dust12m)) + allocate(data%dust12m_var(nx,ny,12,data%nvar_dust12m)) + + data%dust12m_name(1) = 'clay' + data%dust12m_name(2) = 'rdrag' + data%dust12m_name(3) = 'sand' + data%dust12m_name(4) = 'ssm' + data%dust12m_name(5) = 'uthr' + + !--- register axis + call register_axis(restart, 'lon', 'X') + call register_axis(restart, 'lat', 'Y') + call register_axis(restart, 'time', 12) + !--- register the 3D fields + do num = 1,data%nvar_dust12m + var3_p2 => data%dust12m_var(:,:,:,num) + call register_restart_field(restart, data%dust12m_name(num), var3_p2, dimensions=(/'time', 'lat ', 'lon '/),& + &is_optional=.true.) + ! That was "is_optional=.not.mand" in the original, but mand was never initialized. + enddo + end subroutine rrfs_sd_emissions_register_dust12m + + ! -------------------------------------------------------------------- + + subroutine rrfs_sd_emissions_copy_dust12m(data, Sfcprop, Atm_block) + implicit none + type(GFS_sfcprop_type), intent(inout) :: Sfcprop(:) + class(rrfs_sd_emissions_type) :: data + type(block_control_type), intent(in) :: Atm_block + + integer :: num, nb, i, j, ix, k + + if(.not.associated(data%dust12m_name) .or. .not.associated(data%dust12m_var)) then + write(0,*) 'ERROR: Called copy_dust12m before register_dust12m' + return + endif + + !$omp parallel do default(shared) private(i, j, nb, ix, k) + do nb = 1, Atm_block%nblks + !--- 3D variables + do ix = 1, Atm_block%blksz(nb) + i = Atm_block%index(nb)%ii(ix) - Atm_block%isc + 1 + j = Atm_block%index(nb)%jj(ix) - Atm_block%jsc + 1 + do k = 1, 12 + Sfcprop(nb)%dust12m_in(ix,k,1) = data%dust12m_var(i,j,k,1) + Sfcprop(nb)%dust12m_in(ix,k,2) = data%dust12m_var(i,j,k,2) + Sfcprop(nb)%dust12m_in(ix,k,3) = data%dust12m_var(i,j,k,3) + Sfcprop(nb)%dust12m_in(ix,k,4) = data%dust12m_var(i,j,k,4) + Sfcprop(nb)%dust12m_in(ix,k,5) = data%dust12m_var(i,j,k,5) + enddo + enddo + enddo + + deallocate(data%dust12m_name) + nullify(data%dust12m_name) + deallocate(data%dust12m_var) + nullify(data%dust12m_var) + end subroutine rrfs_sd_emissions_copy_dust12m + + ! -------------------------------------------------------------------- + + subroutine rrfs_sd_emissions_register_emi(data, restart, Atm_block) + implicit none + class(rrfs_sd_emissions_type) :: data + type(FmsNetcdfDomainFile_t) :: restart + type(block_control_type), intent(in) :: Atm_block + + real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p2 => NULL() + integer :: num, nx, ny + + if(associated(data%emi_name)) then + deallocate(data%emi_name) + nullify(data%emi_name) + endif + + if(associated(data%emi_var)) then + deallocate(data%emi_var) + nullify(data%emi_var) + endif + + call get_nx_ny_from_atm(Atm_block, nx, ny) + allocate(data%emi_name(data%nvar_emi)) + allocate(data%emi_var(nx,ny,1,data%nvar_emi)) + + data%emi_name(1) = 'e_oc' + !--- register axis + call register_axis( restart, 'time', 1) ! only read first time level, even if multiple are present + call register_axis( restart, "grid_xt", 'X' ) + call register_axis( restart, "grid_yt", 'Y' ) + !--- register the 2D fields + do num = 1,data%nvar_emi + var3_p2 => data%emi_var(:,:,:,num) + call register_restart_field(restart, data%emi_name(num), var3_p2, dimensions=(/'time ','grid_yt','grid_xt'/)) + enddo + end subroutine rrfs_sd_emissions_register_emi + + ! -------------------------------------------------------------------- + + subroutine rrfs_sd_emissions_copy_emi(data, Sfcprop, Atm_block) + implicit none + type(GFS_sfcprop_type), intent(inout) :: Sfcprop(:) + class(rrfs_sd_emissions_type) :: data + type(block_control_type), intent(in) :: Atm_block + + integer :: num, nb, i, j, ix + + if(.not.associated(data%emi_name) .or. .not.associated(data%emi_var)) then + write(0,*) 'ERROR: Called copy_emi before register_emi' + return + endif + + do num=1,data%nvar_emi + !$omp parallel do default(shared) private(i, j, nb, ix) + do nb = 1, Atm_block%nblks + !--- 2D variables + do ix = 1, Atm_block%blksz(nb) + i = Atm_block%index(nb)%ii(ix) - Atm_block%isc + 1 + j = Atm_block%index(nb)%jj(ix) - Atm_block%jsc + 1 + Sfcprop(nb)%emi_in(ix,num) = data%emi_var(i,j,1,num) + enddo + enddo + enddo + + deallocate(data%emi_name) + nullify(data%emi_name) + deallocate(data%emi_var) + nullify(data%emi_var) + end subroutine rrfs_sd_emissions_copy_emi + + ! -------------------------------------------------------------------- + + subroutine rrfs_sd_emissions_register_fire(data, restart, Atm_block) + implicit none + class(rrfs_sd_emissions_type) :: data + type(FmsNetcdfDomainFile_t) :: restart + type(block_control_type), intent(in) :: Atm_block + + real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p2 => NULL() + integer :: num, nx, ny + + if(associated(data%fire_name)) then + deallocate(data%fire_name) + nullify(data%fire_name) + endif + + if(associated(data%fire_var)) then + deallocate(data%fire_var) + nullify(data%fire_var) + endif + + !--- allocate the various containers needed for rrfssd fire data + call get_nx_ny_from_atm(Atm_block, nx, ny) + allocate(data%fire_name(data%nvar_fire)) + allocate(data%fire_var(nx,ny,24,data%nvar_fire)) + + data%fire_name(1) = 'ebb_smoke_hr' + data%fire_name(2) = 'frp_avg_hr' + data%fire_name(3) = 'frp_std_hr' + + !--- register axis + call register_axis(restart, 'lon', 'X') + call register_axis(restart, 'lat', 'Y') + call register_axis(restart, 't', 24) + !--- register the 3D fields + do num = 1,data%nvar_fire + var3_p2 => data%fire_var(:,:,:,num) + call register_restart_field(restart, data%fire_name(num), var3_p2, dimensions=(/'t ', 'lat', 'lon'/), is_optional=.true.) + enddo + + end subroutine rrfs_sd_emissions_register_fire + + ! -------------------------------------------------------------------- + + subroutine rrfs_sd_emissions_copy_fire(data, Sfcprop, Atm_block) + implicit none + class(rrfs_sd_emissions_type) :: data + type(GFS_sfcprop_type), intent(inout) :: Sfcprop(:) + type(block_control_type), intent(in) :: Atm_block + + integer :: nb, ix, k, i, j + + !$omp parallel do default(shared) private(i, j, nb, ix, k) + do nb = 1, Atm_block%nblks + !--- 3D variables + do ix = 1, Atm_block%blksz(nb) + i = Atm_block%index(nb)%ii(ix) - Atm_block%isc + 1 + j = Atm_block%index(nb)%jj(ix) - Atm_block%jsc + 1 + !--- assign hprime(1:10) and hprime(15:24) with new oro stat data + do k = 1, 24 + Sfcprop(nb)%smoke_RRFS(ix,k,1) = data%fire_var(i,j,k,1) + Sfcprop(nb)%smoke_RRFS(ix,k,2) = data%fire_var(i,j,k,2) + Sfcprop(nb)%smoke_RRFS(ix,k,3) = data%fire_var(i,j,k,3) + enddo + enddo + enddo + end subroutine rrfs_sd_emissions_copy_fire + + subroutine rrfs_sd_emissions_final(data) + implicit none + type(rrfs_sd_emissions_type) :: data + + ! This #define reduces code length by a lot +#define IF_ASSOC_DEALLOC_NULL(var) \ + if(associated(data%var)) then ; \ + deallocate(data%var) ; \ + nullify(data%var) ; \ + endif + + IF_ASSOC_DEALLOC_NULL(dust12m_name) + IF_ASSOC_DEALLOC_NULL(emi_name) + IF_ASSOC_DEALLOC_NULL(fire_name) + IF_ASSOC_DEALLOC_NULL(dust12m_var) + IF_ASSOC_DEALLOC_NULL(emi_var) + IF_ASSOC_DEALLOC_NULL(fire_var) + + ! Undefine this to avoid cluttering the cpp scope: +#undef IF_ASSOC_DEALLOC_NULL + end subroutine rrfs_sd_emissions_final + end module rrfs_sd_io From 3c91b6af33789eed25d2cefbccfe678c13d3da65 Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Sat, 6 May 2023 15:34:04 +0000 Subject: [PATCH 05/27] allocate sfc arrays in FV3GFS_sfc_io.F90 --- io/FV3GFS_io.F90 | 92 +++----------------------------------------- io/FV3GFS_sfc_io.F90 | 69 ++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 89 deletions(-) diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index 5fe3718fc..637bce2ba 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -522,17 +522,6 @@ end subroutine FV3GFS_GFS_checksum ! !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - subroutine fill_Sfcprop_names(Model,nvar_s2m,warm_start) - implicit none - type(GFS_control_type), intent(in) :: Model - integer, intent(in) :: nvar_s2m - logical, intent(in) :: warm_start - integer :: nt - - sfc%nvar2m = nvar_s2m - call sfc%fill_2d_names(Model,warm_start) - end subroutine fill_Sfcprop_names - !---------------------------------------------------------------------- ! sfc_prop_restart_read !---------------------------------------------------------------------- @@ -582,14 +571,10 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta logical :: amiopen logical :: is_lsoil - logical :: indexes_changed - type(clm_lake_data_type) :: clm_lake type(rrfs_sd_state_type) :: rrfs_sd_state type(rrfs_sd_emissions_type) :: rrfs_sd_emis - indexes_changed = sfc%calculate_indices(Model, .false., warm_start) - nvar_o2 = 19 nvar_oro_ls_ss = 10 @@ -902,36 +887,8 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta 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)) - if (.not. associated(sfc%name2)) then - !--- allocate the various containers needed for restarts - allocate(sfc%name2(sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp+sfc%nvar2r+sfc%nvar2l)) - allocate(sfc%name3(0:sfc%nvar3+sfc%nvar3mp)) - allocate(sfc%var2(nx,ny,sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp+sfc%nvar2r+sfc%nvar2l)) - ! Note that this may cause problems with RUC LSM for coldstart runs from GFS data - ! if the initial conditions do contain this variable, because Model%kice is 9 for - ! RUC LSM, but tiice in the initial conditions will only have two vertical layers - allocate(sfc%var3ice(nx,ny,Model%kice)) - - if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. (.not.warm_start)) then - allocate(sfc%var3(nx,ny,Model%lsoil,sfc%nvar3)) - else if (Model%lsm == Model%lsm_ruc) then - allocate(sfc%var3(nx,ny,Model%lsoil_lsm,sfc%nvar3)) - end if - - sfc%var2 = -9999.0_r8 - sfc%var3 = -9999.0_r8 - sfc%var3ice= -9999.0_r8 -! - if (Model%lsm == Model%lsm_noahmp) then - allocate(sfc%var3sn(nx,ny,-2:0,4:6)) - allocate(sfc%var3eq(nx,ny,1:4,7:7)) - allocate(sfc%var3zn(nx,ny,-2:4,8:8)) - sfc%var3sn = -9999.0_r8 - sfc%var3eq = -9999.0_r8 - sfc%var3zn = -9999.0_r8 - end if - - call fill_Sfcprop_names(Model,sfc%nvar2m,warm_start) + if(sfc%allocate_arrays(Model, Atm_block, .false., warm_start)) then + call sfc%fill_2d_names(Model, warm_start) is_lsoil=.false. if ( .not. warm_start ) then @@ -1752,12 +1709,8 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta !--- temporary variables for storing rrfs_sd fields type(rrfs_sd_state_type) :: rrfs_sd_state - logical :: indexes_changed - print *,sfc%nvar_before_lake - indexes_changed = sfc%calculate_indices(Model, .true., .true.) - isc = Atm_block%isc iec = Atm_block%iec jsc = Atm_block%jsc @@ -1766,21 +1719,6 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta nx = (iec - isc + 1) ny = (jec - jsc + 1) - if (Model%lsm == Model%lsm_ruc) then - if (associated(sfc%name2)) then - ! Re-allocate if one or more of the dimensions don't match - if (size(sfc%name2).ne.sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp+sfc%nvar2r+sfc%nvar2l .or. & - size(sfc%name3).ne.sfc%nvar3+sfc%nvar3mp .or. & - size(sfc%var3,dim=3).ne.Model%lsoil_lsm) then - !--- deallocate containers and free restart container - deallocate(sfc%name2) - deallocate(sfc%name3) - deallocate(sfc%var2) - deallocate(sfc%var3) - 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) @@ -1866,29 +1804,9 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta call rrfs_sd_state%write_axis(Model,Sfc_restart) end if - if (.not. associated(sfc%name2)) then - !--- allocate the various containers needed for restarts - allocate(sfc%name2(sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp+sfc%nvar2r+sfc%nvar2l)) - allocate(sfc%name3(0:sfc%nvar3+sfc%nvar3mp)) - allocate(sfc%var2(nx,ny,sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp+sfc%nvar2r+sfc%nvar2l)) - if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp) then - allocate(sfc%var3(nx,ny,Model%lsoil,sfc%nvar3)) - elseif (Model%lsm == Model%lsm_ruc) then - allocate(sfc%var3(nx,ny,Model%lsoil_lsm,sfc%nvar3)) - endif - sfc%var2 = -9999.0_r8 - sfc%var3 = -9999.0_r8 - if (Model%lsm == Model%lsm_noahmp) then - allocate(sfc%var3sn(nx,ny,-2:0,4:6)) - allocate(sfc%var3eq(nx,ny,1:4,7:7)) - allocate(sfc%var3zn(nx,ny,-2:4,8:8)) - - sfc%var3sn = -9999.0_r8 - sfc%var3eq = -9999.0_r8 - sfc%var3zn = -9999.0_r8 - endif - call fill_Sfcprop_names(Model,sfc%nvar2m,.true.) - end if + if (sfc%allocate_arrays(Model, Atm_block, .true., .true.)) then + call sfc%fill_2d_names(Model,.true.) + end if if(Model%lkm>0) then if(Model%iopt_lake==Model%iopt_lake_flake ) then diff --git a/io/FV3GFS_sfc_io.F90 b/io/FV3GFS_sfc_io.F90 index d13c54782..1af54d3bd 100644 --- a/io/FV3GFS_sfc_io.F90 +++ b/io/FV3GFS_sfc_io.F90 @@ -17,7 +17,7 @@ module FV3GFS_sfc_io private public :: Sfc_io_data_type - public :: Sfc_io_fill_2d_names, Sfc_io_fill_3d_names, Sfc_io_calculate_indices, Sfc_io_final + public :: Sfc_io_fill_2d_names, Sfc_io_fill_3d_names, Sfc_io_allocate_arrays, Sfc_io_final type Sfc_io_data_type integer, public :: nvar2o = 0 @@ -53,9 +53,13 @@ module FV3GFS_sfc_io character(len=32), pointer, dimension(:), public :: name3 => null() contains + + procedure, public :: allocate_arrays => Sfc_io_allocate_arrays procedure, public :: fill_2d_names => Sfc_io_fill_2d_names procedure, public :: fill_3d_names => Sfc_io_fill_3d_names - procedure, public :: calculate_indices => Sfc_io_calculate_indices + + procedure, private :: calculate_indices => Sfc_io_calculate_indices + final :: Sfc_io_final end type Sfc_io_data_type @@ -138,6 +142,67 @@ function Sfc_io_calculate_indices(sfc, Model, for_write, warm_start) end function Sfc_io_calculate_indices + function Sfc_io_allocate_arrays(sfc, Model, Atm_block, for_write, warm_start) + implicit none + class(Sfc_io_data_type) :: sfc + type(block_control_type), intent(in) :: Atm_block + type(GFS_control_type), intent(in) :: Model + logical :: Sfc_io_allocate_arrays + logical, intent(in) :: for_write, warm_start + + integer :: isc, iec, jsc, jec, npz, nx, ny + + isc = Atm_block%isc + iec = Atm_block%iec + jsc = Atm_block%jsc + jec = Atm_block%jec + npz = Atm_block%npz + nx = (iec - isc + 1) + ny = (jec - jsc + 1) + + Sfc_io_allocate_arrays = sfc%calculate_indices(Model, for_write, warm_start) + Sfc_io_allocate_arrays = Sfc_io_allocate_arrays .or. .not. associated(sfc%name2) + + if(Sfc_io_allocate_arrays) then + !--- allocate the various containers needed for restarts + allocate(sfc%name2(sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp+sfc%nvar2r+sfc%nvar2l)) + allocate(sfc%name3(0:sfc%nvar3+sfc%nvar3mp)) + allocate(sfc%var2(nx,ny,sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp+sfc%nvar2r+sfc%nvar2l)) + + ! Note that this may cause problems with RUC LSM for coldstart runs from GFS data + ! if the initial conditions do contain this variable, because Model%kice is 9 for + ! RUC LSM, but tiice in the initial conditions will only have two vertical layers + allocate(sfc%var3ice(nx,ny,Model%kice)) + + if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. (.not.warm_start)) then + allocate(sfc%var3(nx,ny,Model%lsoil,sfc%nvar3)) + elseif (Model%lsm == Model%lsm_ruc) then + allocate(sfc%var3(nx,ny,Model%lsoil_lsm,sfc%nvar3)) + endif + + sfc%var2 = -9999.0_kind_phys + sfc%var3 = -9999.0_kind_phys + sfc%var3ice= -9999.0_kind_phys + + if (Model%lsm == Model%lsm_noahmp) then + allocate(sfc%var3sn(nx,ny,-2:0,4:6)) + allocate(sfc%var3eq(nx,ny,1:4,7:7)) + allocate(sfc%var3zn(nx,ny,-2:4,8:8)) + + sfc%var3sn = -9999.0_kind_phys + sfc%var3eq = -9999.0_kind_phys + sfc%var3zn = -9999.0_kind_phys + endif + endif + + if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_flake .and. Model%me==0) then + if(size(sfc%name2)/=sfc%nvar_before_lake+10) then +3814 format("ERROR: size mismatch size(sfc%name2)=",I0," /= nvar_before_lake+10=",I0) + write(0,3814) size(sfc%name2),sfc%nvar_before_lake+10 + endif + endif + end function Sfc_io_allocate_arrays + subroutine Sfc_io_fill_3d_names(sfc,Model,warm_start) implicit none class(Sfc_io_data_type) :: sfc From a6971dc32a142705936a8bab34e05d4f99a0a3af Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Sat, 6 May 2023 17:07:58 +0000 Subject: [PATCH 06/27] define and write axes in FV3GFS_sfc_io.F90 --- io/FV3GFS_io.F90 | 95 ++---------------------------------- io/FV3GFS_sfc_io.F90 | 114 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 92 deletions(-) diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index 637bce2ba..da110fb36 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -889,36 +889,8 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta if(sfc%allocate_arrays(Model, Atm_block, .false., warm_start)) then call sfc%fill_2d_names(Model, warm_start) - - 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) 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 + call sfc%register_axes(Model, Sfc_restart, .false., warm_start) + is_lsoil = sfc%is_lsoil ! Tell CLM Lake to allocate data, and register its axes and fields if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then @@ -1726,67 +1698,8 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta !--- register axis amiopen=open_file(Sfc_restart, trim(infile), 'overwrite', domain=fv_domain, is_restart=.true., dont_add_res_to_filename=.true.) if_amiopen: 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) 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) + call sfc%register_axes(Model, Sfc_restart, .true., .true.) + call sfc%write_axes(Model, Sfc_restart) else call mpp_error(FATAL, 'Error in opening file'//trim(infile) ) end if if_amiopen diff --git a/io/FV3GFS_sfc_io.F90 b/io/FV3GFS_sfc_io.F90 index 1af54d3bd..b694fb89d 100644 --- a/io/FV3GFS_sfc_io.F90 +++ b/io/FV3GFS_sfc_io.F90 @@ -17,7 +17,8 @@ module FV3GFS_sfc_io private public :: Sfc_io_data_type - public :: Sfc_io_fill_2d_names, Sfc_io_fill_3d_names, Sfc_io_allocate_arrays, Sfc_io_final + public :: Sfc_io_fill_2d_names, Sfc_io_fill_3d_names, Sfc_io_allocate_arrays, & + Sfc_io_register_axes, Sfc_io_write_axes, Sfc_io_final type Sfc_io_data_type integer, public :: nvar2o = 0 @@ -55,6 +56,8 @@ module FV3GFS_sfc_io contains procedure, public :: allocate_arrays => Sfc_io_allocate_arrays + procedure, public :: register_axes => Sfc_io_register_axes + procedure, public :: write_axes => Sfc_io_write_axes procedure, public :: fill_2d_names => Sfc_io_fill_2d_names procedure, public :: fill_3d_names => Sfc_io_fill_3d_names @@ -203,6 +206,115 @@ function Sfc_io_allocate_arrays(sfc, Model, Atm_block, for_write, warm_start) endif end function Sfc_io_allocate_arrays + subroutine Sfc_io_register_axes(sfc, Model, Sfc_restart, for_write, warm_start) + implicit none + class(Sfc_io_data_type) :: sfc + type(GFS_control_type), intent(in) :: Model + type(FmsNetcdfDomainFile_t) :: Sfc_restart + logical, intent(in) :: for_write, warm_start + + if(.not.for_write) then + sfc%is_lsoil = .false. + endif + + if(.not.warm_start .and. .not.for_write) then + if( variable_exists(Sfc_restart,"lsoil") ) then + if(.not.for_write) then + sfc%is_lsoil=.true. + endif + 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) then + call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil) + else if(Model%lsm == Model%lsm_ruc .and. .not.for_write) then + ! Possible bug. The lsm_ruc only reads zaxis_2, never writes it. + call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil_lsm) + endif + 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) + endif + end subroutine Sfc_io_register_axes + + subroutine Sfc_io_write_axes(sfc, Model, Sfc_restart) + implicit none + class(Sfc_io_data_type) :: sfc + type(GFS_control_type), intent(in) :: Model + type(FmsNetcdfDomainFile_t) :: Sfc_restart + + integer, allocatable :: buffer(:) + integer :: i, is, ie + logical :: mand + + 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_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_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) then + 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_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_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_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) + end subroutine Sfc_io_write_axes + subroutine Sfc_io_fill_3d_names(sfc,Model,warm_start) implicit none class(Sfc_io_data_type) :: sfc From 507fb73ae0cc715e10dbad543f441f2a00fddaa1 Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Mon, 8 May 2023 19:44:59 +0000 Subject: [PATCH 07/27] register sfc fields in FV3GFS_sfc_io.F90 --- io/FV3GFS_io.F90 | 236 ++----------------------------------------- io/FV3GFS_sfc_io.F90 | 196 ++++++++++++++++++++++++++++++++++- 2 files changed, 203 insertions(+), 229 deletions(-) diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index da110fb36..58accf4b3 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -907,142 +907,12 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta call rrfs_sd_state%register_fields(Sfc_restart) endif - !--- register the 2D fields - do num = 1,sfc%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)) == 'snodi' .or. trim(sfc%name2(num)) == 'weasdi' & - .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' .or. trim(sfc%name2(num)) == 'emis_ice' & - .or. trim(sfc%name2(num)) == 'sncovr_ice') 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 - 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 - - if (Model%nstf_name(1) > 0) then - mand = .false. - if (Model%nstf_name(2) == 0) mand = .true. - do num = sfc%nvar2m+1,sfc%nvar2m+sfc%nvar2o - 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 ! sfc%nvar2mp = 0 - do num = sfc%nvar2m+sfc%nvar2o+1, sfc%nvar2m+sfc%nvar2o+sfc%nvar2r - 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 (sfc%nvar2mp > 0) then - mand = .false. - do num = sfc%nvar2m+sfc%nvar2o+1,sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp - 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 - -! Flake - if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then - mand = .false. - do num = sfc%nvar_before_lake+1,sfc%nvar_before_lake+sfc%nvar2l - 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 - - nullify(var2_p) + call sfc%register_2d_fields(Model,Sfc_restart,.false.,warm_start) endif ! if not allocated call sfc%fill_3d_names(Model,warm_start) - - !--- register the 3D fields - var3_p => sfc%var3ice(:,:,:) - 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,sfc%nvar3 - 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 = sfc%nvar3+1,sfc%nvar3+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) - 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) - 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) - -!--- Noah MP define arbitrary value (number layers of snow) to indicate -!coldstart(sfcfile doesn't include noah mp fields) or not - - if (Model%lsm == Model%lsm_noahmp) then - sfc%var2(1,1,sfc%nvar2m+19) = -66666.0_r8 - endif + call sfc%register_3d_fields(Model,Sfc_restart,.false.,warm_start) + call sfc%init_fields(Model) !--- read the surface restart/data call mpp_error(NOTE,'reading surface properties data from INPUT/sfc_data.tile*.nc') @@ -1739,102 +1609,14 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta call rrfs_sd_state%register_fields(Sfc_restart) endif - !--- register the 2D fields - do num = 1,sfc%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)) == 'snodi' .or. trim(sfc%name2(num)) == 'weasdi' & - .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' .or. trim(sfc%name2(num)) == 'emis_ice' & - .or. trim(sfc%name2(num)) == 'sncovr_ice' ) 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 = sfc%nvar2m+1,sfc%nvar2m+sfc%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 2D surface property fields (except lake, smoke, and dust) + call sfc%register_2d_fields(Model, Sfc_restart, .true., .true.) - if (Model%lsm == Model%lsm_ruc) then ! sfc%nvar2mp =0 - do num = sfc%nvar2m+sfc%nvar2o+1, sfc%nvar2m+sfc%nvar2o+sfc%nvar2r - var2_p => sfc%var2(:,:,num) - call register_restart_field(Sfc_restart, sfc%name2(num), var2_p, dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/)) - enddo - else if (Model%lsm == Model%lsm_noahmp) then ! sfc%nvar2r =0 - mand = .true. ! actually should be true since it is after cold start - do num = sfc%nvar2m+sfc%nvar2o+1,sfc%nvar2m+sfc%nvar2o+sfc%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) - - call sfc%fill_3d_names(Model,.true.) + ! Determine list of 3D surface property fields names: + call sfc%fill_3d_names(Model, .true.) - !--- register the 3D fields - ! if (Model%frac_grid) then - 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,sfc%nvar3 - 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,sfc%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 = sfc%nvar3+1,sfc%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 - - 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 - - !Flake - if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then - mand = .false. - do num = sfc%nvar_before_lake+1,sfc%nvar_before_lake+sfc%nvar2l - 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 3D surface property fields (except lake, smoke, and dust) + call sfc%register_3d_fields(Model, Sfc_restart, .true., .true.) ! Tell clm_lake to copy Sfcprop data to its internal temporary arrays. if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then diff --git a/io/FV3GFS_sfc_io.F90 b/io/FV3GFS_sfc_io.F90 index b694fb89d..353ff7d78 100644 --- a/io/FV3GFS_sfc_io.F90 +++ b/io/FV3GFS_sfc_io.F90 @@ -18,7 +18,9 @@ module FV3GFS_sfc_io public :: Sfc_io_data_type public :: Sfc_io_fill_2d_names, Sfc_io_fill_3d_names, Sfc_io_allocate_arrays, & - Sfc_io_register_axes, Sfc_io_write_axes, Sfc_io_final + Sfc_io_register_axes, Sfc_io_write_axes, & + Sfc_io_register_2d_fields, Sfc_io_register_3d_fields, & + Sfc_io_final type Sfc_io_data_type integer, public :: nvar2o = 0 @@ -58,8 +60,11 @@ module FV3GFS_sfc_io procedure, public :: allocate_arrays => Sfc_io_allocate_arrays procedure, public :: register_axes => Sfc_io_register_axes procedure, public :: write_axes => Sfc_io_write_axes + procedure, public :: register_2d_fields => Sfc_io_register_2d_fields + procedure, public :: register_3d_fields => Sfc_io_register_3d_fields procedure, public :: fill_2d_names => Sfc_io_fill_2d_names procedure, public :: fill_3d_names => Sfc_io_fill_3d_names + procedure, public :: init_fields => Sfc_io_init_fields procedure, private :: calculate_indices => Sfc_io_calculate_indices @@ -238,7 +243,7 @@ subroutine Sfc_io_register_axes(sfc, Model, Sfc_restart, for_write, warm_start) if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp) then call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil) else if(Model%lsm == Model%lsm_ruc .and. .not.for_write) then - ! Possible bug. The lsm_ruc only reads zaxis_2, never writes it. + ! Possible bug. This is only defined on read, not write. call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil_lsm) endif if(Model%lsm == Model%lsm_noahmp) then @@ -505,6 +510,193 @@ subroutine Sfc_io_fill_2d_names(sfc,Model,warm_start) endif end subroutine Sfc_io_fill_2d_names + subroutine Sfc_io_register_2d_fields(sfc,Model,Sfc_restart,for_write,warm_start) + implicit none + class(Sfc_io_data_type) :: sfc + type(GFS_control_type), intent(in) :: Model + type(FmsNetcdfDomainFile_t) :: Sfc_restart + logical, intent(in) :: for_write, warm_start + + real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() + real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() + 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() + integer :: num + logical :: mand + + character(len=7) :: time2d(3) + + if(for_write) then + time2d=(/'xaxis_1','yaxis_1','Time '/) + else + time2d=(/'Time ','yaxis_1','xaxis_1'/) + endif + + !--- register the 2D fields + do num = 1,sfc%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)) == 'snodi' .or. trim(sfc%name2(num)) == 'weasdi' & + .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' .or. trim(sfc%name2(num)) == 'emis_ice' & + .or. trim(sfc%name2(num)) == 'sncovr_ice') then + if(.not.for_write .and. sfc%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=time2d,& + &is_optional=.true.) + end if + else + if(.not.for_write .and. sfc%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=time2d) + end if + endif + enddo + + if (Model%nstf_name(1) > 0) then + mand = .false. + if (Model%nstf_name(2) == 0) mand = .true. + do num = sfc%nvar2m+1,sfc%nvar2m+sfc%nvar2o + var2_p => sfc%var2(:,:,num) + if(sfc%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=time2d, is_optional=.not.mand) + endif + enddo + endif + + if (Model%lsm == Model%lsm_ruc) then ! sfc%nvar2mp = 0 + do num = sfc%nvar2m+sfc%nvar2o+1, sfc%nvar2m+sfc%nvar2o+sfc%nvar2r + var2_p => sfc%var2(:,:,num) + if(sfc%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=time2d) + end if + enddo + endif ! mp/ruc + + ! Noah MP register only necessary only lsm = 2, not necessary has values + if ( (for_write .and. Model%lsm == Model%lsm_noahmp) & + .or. (.not. for_write .and. sfc%nvar2mp > 0) ) then + mand = for_write + do num = sfc%nvar2m+sfc%nvar2o+1,sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp + var2_p => sfc%var2(:,:,num) + if(sfc%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=time2d, is_optional=.not.mand) + end if + enddo + endif ! noahmp + + ! Flake + if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then + mand = for_write + do num = sfc%nvar_before_lake+1,sfc%nvar_before_lake+sfc%nvar2l + var2_p => sfc%var2(:,:,num) + if(sfc%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=time2d, is_optional=.not.mand) + endif + enddo + endif + + end subroutine Sfc_io_register_2d_fields + + subroutine Sfc_io_register_3d_fields(sfc,Model,Sfc_restart,for_write,warm_start) + implicit none + class(Sfc_io_data_type) :: sfc + type(GFS_control_type), intent(in) :: Model + type(FmsNetcdfDomainFile_t) :: Sfc_restart + logical, intent(in) :: for_write, warm_start + + real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() + 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() + real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_fr => NULL() + integer :: num + logical :: mand + + character(len=7), parameter :: xyz1_time(4) = (/'xaxis_1', 'yaxis_1', 'zaxis_1', 'Time '/) + character(len=7), parameter :: xyz2_time(4) = (/'xaxis_1', 'yaxis_1', 'zaxis_2', 'Time '/) + character(len=7), parameter :: xyz3_time(4) = (/'xaxis_1', 'yaxis_1', 'zaxis_3', 'Time '/) + character(len=7), parameter :: xyz4_time(4) = (/'xaxis_1', 'yaxis_1', 'zaxis_4', 'Time '/) + + !--- register the 3D fields + var3_p => sfc%var3ice(:,:,:) + call register_restart_field(Sfc_restart, sfc%name3(0), var3_p, dimensions=xyz1_time, is_optional=.true.) + + if(.not. for_write) then + do num = 1,sfc%nvar3 + 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(sfc%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=xyz2_time,& + &is_optional=.true.) + end if + end if + enddo + elseif(Model%lsm == Model%lsm_ruc) then + do num = 1,sfc%nvar3 + var3_p => sfc%var3(:,:,:,num) + call register_restart_field(Sfc_restart, sfc%name3(num), var3_p, dimensions=xyz1_time) + enddo + nullify(var3_p) + else ! writing something other than ruc + do num = 1,sfc%nvar3 + var3_p => sfc%var3(:,:,:,num) + call register_restart_field(Sfc_restart, sfc%name3(num), var3_p, dimensions=xyz2_time) + enddo + nullify(var3_p) + endif + + if (Model%lsm == Model%lsm_noahmp) then + mand = for_write + do num = sfc%nvar3+1,sfc%nvar3+3 + var3_p1 => sfc%var3sn(:,:,:,num) + call register_restart_field(Sfc_restart, sfc%name3(num), var3_p1, dimensions=xyz3_time, is_optional=.not.mand) + enddo + + var3_p2 => sfc%var3eq(:,:,:,7) + call register_restart_field(Sfc_restart, sfc%name3(7), var3_p2, dimensions=xyz2_time, is_optional=.not.mand) + + var3_p3 => sfc%var3zn(:,:,:,8) + call register_restart_field(Sfc_restart, sfc%name3(8), var3_p3, dimensions=xyz4_time, is_optional=.not.mand) + endif !mp + + end subroutine Sfc_io_register_3d_fields + + subroutine Sfc_io_init_fields(sfc,Model) + implicit none + class(Sfc_io_data_type) :: sfc + type(GFS_control_type), intent(in) :: Model + + !--- Noah MP define arbitrary value (number layers of snow) to indicate + !coldstart(sfcfile doesn't include noah mp fields) or not + + if (Model%lsm == Model%lsm_noahmp) then + sfc%var2(1,1,sfc%nvar2m+19) = -66666.0_kind_phys + endif + end subroutine Sfc_io_init_fields + subroutine Sfc_io_final(sfc) implicit none type(Sfc_io_data_type) :: sfc From 200ef3c0c115a9e8cfc3467b111216c73fd80dd6 Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Mon, 8 May 2023 23:32:22 +0000 Subject: [PATCH 08/27] move sfc read loop to FV3GFS_sfc_io.F90 --- io/FV3GFS_io.F90 | 363 +-------------------------------------- io/FV3GFS_sfc_io.F90 | 400 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 403 insertions(+), 360 deletions(-) diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index 58accf4b3..18f24ae68 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -101,7 +101,6 @@ module FV3GFS_io_mod real, parameter:: stndrd_atmos_ps = 101325.0_r8 real, parameter:: stndrd_atmos_lapse = 0.0065_r8 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 type(Sfc_io_data_type) :: sfc @@ -570,6 +569,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta !--- fms2_io file open logic logical :: amiopen logical :: is_lsoil + logical :: override_frac_grid type(clm_lake_data_type) :: clm_lake type(rrfs_sd_state_type) :: rrfs_sd_state @@ -933,365 +933,10 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta ! write(0,*)' sfc%var2=',sfc%var2(:,:,12) !--- place the data into the block GFS containers + override_frac_grid=Model%frac_grid + call sfc%copy_to_grid(Model, Atm_block, Sfcprop, warm_start, override_frac_grid) + Model%frac_grid=override_frac_grid -!$omp parallel do default(shared) private(i, j, nb, ix, nt, ii1, jj1, lsoil) - block_loop: do nb = 1, Atm_block%nblks - allocate(ii1(Atm_block%blksz(nb))) - allocate(jj1(Atm_block%blksz(nb))) - ii1=Atm_block%index(nb)%ii - isc + 1 - jj1=Atm_block%index(nb)%jj - jsc + 1 - - nt=0 - -!--- 2D variables -! ------------ - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slmsk) !--- slmsk - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tg3) !--- tg3 - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorl) !--- zorl composite - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvsf) !--- alvsf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvwf) !--- alvwf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnsf) !--- alnsf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnwf) !--- alnwf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facsf) !--- facsf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facwf) !--- facwf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vfrac) !--- vfrac - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canopy) !--- canopy - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%f10m) !--- f10m - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t2m) !--- t2m - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%q2m) !--- q2m - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vtype) !--- vtype - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stype) !--- stype - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%uustar) !--- uustar - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffmm) !--- ffmm - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffhh) !--- ffhh - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%hice) !--- hice - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fice) !--- fice - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tisfc) !--- tisfc - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tprcp) !--- tprcp - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%srflag) !--- srflag - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmin) !--- shdmin - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmax) !--- shdmax - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slope) !--- slope - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snoalb) !--- snoalb - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr) !--- sncovr - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfc) !--- tsfc composite - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlw) !--- zorlw (zorl on water portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice portion of a cell) - if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_ice) -! call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) - endif - if(Model%cplwav) then - !tgs - the following line is a bug. It should be nt = nt - !nt = sfc%nvar2m-1 ! Next item will be at sfc%nvar2m - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlwav) !--- (zorl from wave model) - else - Sfcprop(nb)%zorlwav = Sfcprop(nb)%zorlw - endif - - do_lsi_fractions: do ix = 1, Atm_block%blksz(nb) - if (Sfcprop(nb)%stype(ix) == 14 .or. Sfcprop(nb)%stype(ix) <= 0) then - Sfcprop(nb)%landfrac(ix) = zero - Sfcprop(nb)%stype(ix) = 0 - if (Sfcprop(nb)%lakefrac(ix) > zero) then - Sfcprop(nb)%lakefrac(ix) = one - endif - endif - - if_frac_grid: if (Model%frac_grid) then - if (Sfcprop(nb)%landfrac(ix) > -999.0_r8) then - Sfcprop(nb)%slmsk(ix) = ceiling(Sfcprop(nb)%landfrac(ix)-1.0e-6) - if (Sfcprop(nb)%slmsk(ix) == 1 .and. Sfcprop(nb)%stype(ix) == 14) & - Sfcprop(nb)%slmsk(ix) = 0 - if (Sfcprop(nb)%lakefrac(ix) > zero) then - Sfcprop(nb)%oceanfrac(ix) = zero ! lake & ocean don't coexist in a cell - if (nint(Sfcprop(nb)%slmsk(ix)) /= 1) then - if(Sfcprop(nb)%fice(ix) >= Model%min_lakeice) then - Sfcprop(nb)%slmsk(ix) = 2 - else - Sfcprop(nb)%slmsk(ix) = 0 - endif - endif - else - Sfcprop(nb)%lakefrac(ix) = zero - Sfcprop(nb)%oceanfrac(ix) = one - Sfcprop(nb)%landfrac(ix) - if (nint(Sfcprop(nb)%slmsk(ix)) /= 1) then - if (Sfcprop(nb)%fice(ix) >= Model%min_seaice) then - Sfcprop(nb)%slmsk(ix) = 2 - else - Sfcprop(nb)%slmsk(ix) = 0 - endif - endif - endif - else - Model%frac_grid = .false. - if (nint(Sfcprop(nb)%slmsk(ix)) == 1) then - Sfcprop(nb)%landfrac(ix) = one - Sfcprop(nb)%lakefrac(ix) = zero - Sfcprop(nb)%oceanfrac(ix) = zero - else - if (Sfcprop(nb)%slmsk(ix) < 0.1_r8 .or. Sfcprop(nb)%slmsk(ix) > 1.9_r8) then - Sfcprop(nb)%landfrac(ix) = zero - if (Sfcprop(nb)%oro_uf(ix) > min_lake_orog) then ! lakes - Sfcprop(nb)%lakefrac(ix) = one - Sfcprop(nb)%oceanfrac(ix) = zero - else ! ocean - Sfcprop(nb)%lakefrac(ix) = zero - Sfcprop(nb)%oceanfrac(ix) = one - endif - endif - endif - endif - else ! not a fractional grid - if (Sfcprop(nb)%landfrac(ix) > -999.0_r8) then - if (Sfcprop(nb)%lakefrac(ix) > zero) then - Sfcprop(nb)%oceanfrac(ix) = zero - Sfcprop(nb)%landfrac(ix) = zero - Sfcprop(nb)%lakefrac(ix) = one - Sfcprop(nb)%slmsk(ix) = zero - if (Sfcprop(nb)%fice(ix) >= Model%min_lakeice) Sfcprop(nb)%slmsk(ix) = 2.0 - else - Sfcprop(nb)%slmsk(ix) = nint(Sfcprop(nb)%landfrac(ix)) - if (Sfcprop(nb)%stype(ix) <= 0 .or. Sfcprop(nb)%stype(ix) == 14) & - Sfcprop(nb)%slmsk(ix) = zero - if (nint(Sfcprop(nb)%slmsk(ix)) == 0) then - Sfcprop(nb)%oceanfrac(ix) = one - Sfcprop(nb)%landfrac(ix) = zero - Sfcprop(nb)%lakefrac(ix) = zero - if (Sfcprop(nb)%fice(ix) >= Model%min_seaice) Sfcprop(nb)%slmsk(ix) = 2.0 - else - Sfcprop(nb)%landfrac(ix) = one - Sfcprop(nb)%lakefrac(ix) = zero - Sfcprop(nb)%oceanfrac(ix) = zero - endif - endif - else - if (nint(Sfcprop(nb)%slmsk(ix)) == 1 .and. Sfcprop(nb)%stype(ix) > 0 & - .and. Sfcprop(nb)%stype(ix) /= 14) then - Sfcprop(nb)%landfrac(ix) = one - Sfcprop(nb)%lakefrac(ix) = zero - Sfcprop(nb)%oceanfrac(ix) = zero - else - Sfcprop(nb)%slmsk(ix) = zero - Sfcprop(nb)%landfrac(ix) = zero - if (Sfcprop(nb)%oro_uf(ix) > min_lake_orog) then ! lakes - Sfcprop(nb)%lakefrac(ix) = one - Sfcprop(nb)%oceanfrac(ix) = zero - if (Sfcprop(nb)%fice(ix) > Model%min_lakeice) Sfcprop(nb)%slmsk(ix) = 2.0 - else ! ocean - Sfcprop(nb)%lakefrac(ix) = zero - Sfcprop(nb)%oceanfrac(ix) = one - if (Sfcprop(nb)%fice(ix) > Model%min_seaice) Sfcprop(nb)%slmsk(ix) = 2.0 - endif - endif - endif - endif if_frac_grid - enddo do_lsi_fractions - - if (warm_start .and. Model%kdt > 1) then - do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%slmsk(ix) = sfc%var2(ii1(ix),jj1(ix),1) !--- slmsk - enddo - endif - - ! - !--- NSSTM variables - !tgs - the following line is a bug that will show if(Model%cplwav) = true - !nt = sfc%nvar2m - if (Model%nstf_name(1) > 0) then - if (Model%nstf_name(2) == 1) then ! nsst spinup - !--- nsstm tref - nt = nt + 18 - Sfcprop(nb)%tref = Sfcprop(nb)%tsfco - Sfcprop(nb)%z_c = zero - Sfcprop(nb)%c_0 = zero - Sfcprop(nb)%c_d = zero - Sfcprop(nb)%w_0 = zero - Sfcprop(nb)%w_d = zero - Sfcprop(nb)%xt = zero - Sfcprop(nb)%xs = zero - Sfcprop(nb)%xu = zero - Sfcprop(nb)%xv = zero - Sfcprop(nb)%xz = 20.0_r8 - Sfcprop(nb)%zm = zero - Sfcprop(nb)%xtts = zero - Sfcprop(nb)%xzts = zero - Sfcprop(nb)%d_conv = zero - Sfcprop(nb)%ifd = zero - Sfcprop(nb)%dt_cool = zero - Sfcprop(nb)%qrain = zero - elseif (Model%nstf_name(2) == 0) then ! nsst restart - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tref) !--- nsstm tref - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%z_c) !--- nsstm z_c - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_0) !--- nsstm c_0 - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_d) !--- nsstm c_d - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_0) !--- nsstm w_0 - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_d) !--- nsstm w_d - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xt) !--- nsstm xt - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xs) !--- nsstm xs - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xu) !--- nsstm xu - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xv) !--- nsstm xv - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xz) !--- nsstm xz - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zm) !--- nsstm zm - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xtts) !--- nsstm xtts - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xzts) !--- nsstm xzts - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ifd) !--- nsstm ifd - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%dt_cool) !--- nsstm dt_cool - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qrain) !--- nsstm qrain - endif - endif - - if (Model%lsm == Model%lsm_ruc .and. warm_start) then - !--- Extra RUC variables - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wetness) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_land) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_land) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_land) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_land) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd_bck) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) - if (Model%rdlai) then - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) - endif - else if (Model%lsm == Model%lsm_ruc) then - ! Initialize RUC snow cover on ice from snow cover - Sfcprop(nb)%sncovr_ice = Sfcprop(nb)%sncovr - if (Model%rdlai) then - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) - end if - elseif (Model%lsm == Model%lsm_noahmp) then - !--- Extra Noah MP variables - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tvxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tgxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canicexy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canliqxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%eahxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tahxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%cmxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%chxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fwetxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sneqvoxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alboldxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qsnowxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wslakexy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zwtxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%waxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wtxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%lfmassxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rtmassxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stmassxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%woodxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stblcpxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fastcpxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xsaixy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%taussxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%smcwtdxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%deeprechxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rechxy) - endif - if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_snow) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_ML) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_ML) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_mnw) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_talb) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_talb) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot1) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot2) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_t) - endif - if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. (.not.warm_start)) then - !--- 3D variables - nt=0 - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc%var3,Sfcprop(nb)%stc) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc%var3,Sfcprop(nb)%smc) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc%var3,Sfcprop(nb)%slc) - - if (Model%lsm == Model%lsm_noahmp) then - ! These use weird indexing which is lost during a Fortran subroutine call, so we use loops instead: - nt=nt+1 - do lsoil = -2, 0 - do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%snicexy(ix,lsoil) = sfc%var3sn(ii1(ix),jj1(ix),lsoil,nt) - enddo - enddo - - nt=nt+1 - do lsoil = -2, 0 - do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%snliqxy(ix,lsoil) = sfc%var3sn(ii1(ix),jj1(ix),lsoil,nt) - enddo - enddo - - nt=nt+1 - do lsoil = -2, 0 - do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%tsnoxy(ix,lsoil) = sfc%var3sn(ii1(ix),jj1(ix),lsoil,nt) - enddo - enddo - - nt=nt+1 - do lsoil = 1, 4 - do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%smoiseq(ix,lsoil) = sfc%var3eq(ii1(ix),jj1(ix),lsoil,nt) - enddo - enddo - - nt=nt+1 - do lsoil = -2, 4 - do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%zsnsoxy(ix,lsoil) = sfc%var3zn(ii1(ix),jj1(ix),lsoil,nt) - enddo - enddo - endif - - else if (Model%lsm == Model%lsm_ruc) then - !--- 3D variables - nt=0 - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%tslb) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%smois) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%sh2o) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%keepsmfr) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%flag_frsoil) - endif - - do k = 1,Model%kice - do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%tiice(ix,k) = sfc%var3ice(ii1(ix),jj1(ix),k) !--- internal ice temp - enddo - enddo - - deallocate(ii1,jj1) - - end do block_loop call mpp_error(NOTE, 'gfs_driver:: - after put to container ') ! so far: At cold start everything is 9999.0, warm start snowxy has values diff --git a/io/FV3GFS_sfc_io.F90 b/io/FV3GFS_sfc_io.F90 index 353ff7d78..cdf92c177 100644 --- a/io/FV3GFS_sfc_io.F90 +++ b/io/FV3GFS_sfc_io.F90 @@ -20,7 +20,10 @@ module FV3GFS_sfc_io public :: Sfc_io_fill_2d_names, Sfc_io_fill_3d_names, Sfc_io_allocate_arrays, & Sfc_io_register_axes, Sfc_io_write_axes, & Sfc_io_register_2d_fields, Sfc_io_register_3d_fields, & - Sfc_io_final + Sfc_io_copy_to_grid, Sfc_io_final + + real(kind_phys), parameter:: min_lake_orog = 200.0_kind_phys + real(kind_phys), parameter:: zero = 0, one = 1 type Sfc_io_data_type integer, public :: nvar2o = 0 @@ -65,6 +68,7 @@ module FV3GFS_sfc_io procedure, public :: fill_2d_names => Sfc_io_fill_2d_names procedure, public :: fill_3d_names => Sfc_io_fill_3d_names procedure, public :: init_fields => Sfc_io_init_fields + procedure, public :: copy_to_grid => Sfc_io_copy_to_grid procedure, private :: calculate_indices => Sfc_io_calculate_indices @@ -697,6 +701,400 @@ subroutine Sfc_io_init_fields(sfc,Model) endif end subroutine Sfc_io_init_fields + subroutine Sfc_io_copy_to_grid(sfc, Model, Atm_block, Sfcprop, warm_start, override_frac_grid) + !--- interface variable definitions + implicit none + + class(Sfc_io_data_type) :: sfc + type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) + type(block_control_type), intent(in) :: Atm_block + type(GFS_control_type), intent(in) :: Model + logical, intent(in) :: warm_start + logical, intent(out), optional :: override_frac_grid + + integer :: i, j, k, nb, ix, lsoil, num, nt + integer :: isc, iec, jsc, jec, npz, nx, ny + integer, allocatable :: ii1(:), jj1(:) + real(kind_phys) :: ice + + isc = Atm_block%isc + iec = Atm_block%iec + jsc = Atm_block%jsc + jec = Atm_block%jec + npz = Atm_block%npz + nx = (iec - isc + 1) + ny = (jec - jsc + 1) + +! 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)) +! write(0,*)' sfc_var2=',sfc_var2(:,:,12) + + !$omp parallel do default(shared) private(i, j, nb, ix, nt, ii1, jj1, lsoil) + block_loop: do nb = 1, Atm_block%nblks + allocate(ii1(Atm_block%blksz(nb))) + allocate(jj1(Atm_block%blksz(nb))) + ii1=Atm_block%index(nb)%ii - isc + 1 + jj1=Atm_block%index(nb)%jj - jsc + 1 + + nt=0 + + !--- 2D variables + ! ------------ + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slmsk) !--- slmsk + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tg3) !--- tg3 + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorl) !--- zorl composite + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvsf) !--- alvsf + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvwf) !--- alvwf + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnsf) !--- alnsf + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnwf) !--- alnwf + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facsf) !--- facsf + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facwf) !--- facwf + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vfrac) !--- vfrac + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canopy) !--- canopy + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%f10m) !--- f10m + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t2m) !--- t2m + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%q2m) !--- q2m + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vtype) !--- vtype + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stype) !--- stype + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%uustar) !--- uustar + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffmm) !--- ffmm + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffhh) !--- ffhh + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%hice) !--- hice + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fice) !--- fice + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tisfc) !--- tisfc + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tprcp) !--- tprcp + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%srflag) !--- srflag + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmin) !--- shdmin + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmax) !--- shdmax + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slope) !--- slope + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snoalb) !--- snoalb + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr) !--- sncovr + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfc) !--- tsfc composite + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlw) !--- zorlw (zorl on water portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_lnd) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_lnd) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_lnd) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_lnd) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_lnd) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice portion of a cell) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice portion of a cell) + if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_ice) + ! call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) + endif + if(Model%cplwav) then + !tgs - the following line is a bug. It should be nt = nt + !nt = sfc%nvar2m-1 ! Next item will be at sfc%nvar2m + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlwav) !--- (zorl from wave model) + else + Sfcprop(nb)%zorlwav = Sfcprop(nb)%zorlw + endif + + if(present(override_frac_grid)) then + override_frac_grid=Model%frac_grid + endif + + do_lsi_fractions: do ix = 1, Atm_block%blksz(nb) + if (Sfcprop(nb)%stype(ix) == 14 .or. Sfcprop(nb)%stype(ix) <= 0) then + Sfcprop(nb)%landfrac(ix) = zero + Sfcprop(nb)%stype(ix) = 0 + if (Sfcprop(nb)%lakefrac(ix) > zero) then + Sfcprop(nb)%lakefrac(ix) = one + endif + endif + + if_frac_grid: if (Model%frac_grid) then + if (Sfcprop(nb)%landfrac(ix) > -999.0_kind_phys) then + Sfcprop(nb)%slmsk(ix) = ceiling(Sfcprop(nb)%landfrac(ix)-1.0e-6) + if (Sfcprop(nb)%slmsk(ix) == 1 .and. Sfcprop(nb)%stype(ix) == 14) & + Sfcprop(nb)%slmsk(ix) = 0 + if (Sfcprop(nb)%lakefrac(ix) > zero) then + Sfcprop(nb)%oceanfrac(ix) = zero ! lake & ocean don't coexist in a cell + if (nint(Sfcprop(nb)%slmsk(ix)) /= 1) then + if(Sfcprop(nb)%fice(ix) >= Model%min_lakeice) then + Sfcprop(nb)%slmsk(ix) = 2 + else + Sfcprop(nb)%slmsk(ix) = 0 + endif + endif + else + Sfcprop(nb)%lakefrac(ix) = zero + Sfcprop(nb)%oceanfrac(ix) = one - Sfcprop(nb)%landfrac(ix) + if (nint(Sfcprop(nb)%slmsk(ix)) /= 1) then + if (Sfcprop(nb)%fice(ix) >= Model%min_seaice) then + Sfcprop(nb)%slmsk(ix) = 2 + else + Sfcprop(nb)%slmsk(ix) = 0 + endif + endif + endif + else + if(present(override_frac_grid)) then + override_frac_grid = .false. + endif + if (nint(Sfcprop(nb)%slmsk(ix)) == 1) then + Sfcprop(nb)%landfrac(ix) = one + Sfcprop(nb)%lakefrac(ix) = zero + Sfcprop(nb)%oceanfrac(ix) = zero + else + if (Sfcprop(nb)%slmsk(ix) < 0.1_kind_phys .or. Sfcprop(nb)%slmsk(ix) > 1.9_kind_phys) then + Sfcprop(nb)%landfrac(ix) = zero + if (Sfcprop(nb)%oro_uf(ix) > min_lake_orog) then ! lakes + Sfcprop(nb)%lakefrac(ix) = one + Sfcprop(nb)%oceanfrac(ix) = zero + else ! ocean + Sfcprop(nb)%lakefrac(ix) = zero + Sfcprop(nb)%oceanfrac(ix) = one + endif + endif + endif + endif + else ! not a fractional grid + if (Sfcprop(nb)%landfrac(ix) > -999.0_kind_phys) then + if (Sfcprop(nb)%lakefrac(ix) > zero) then + Sfcprop(nb)%oceanfrac(ix) = zero + Sfcprop(nb)%landfrac(ix) = zero + Sfcprop(nb)%lakefrac(ix) = one + Sfcprop(nb)%slmsk(ix) = zero + if (Sfcprop(nb)%fice(ix) >= Model%min_lakeice) Sfcprop(nb)%slmsk(ix) = 2.0 + else + Sfcprop(nb)%slmsk(ix) = nint(Sfcprop(nb)%landfrac(ix)) + if (Sfcprop(nb)%stype(ix) <= 0 .or. Sfcprop(nb)%stype(ix) == 14) & + Sfcprop(nb)%slmsk(ix) = zero + if (nint(Sfcprop(nb)%slmsk(ix)) == 0) then + Sfcprop(nb)%oceanfrac(ix) = one + Sfcprop(nb)%landfrac(ix) = zero + Sfcprop(nb)%lakefrac(ix) = zero + if (Sfcprop(nb)%fice(ix) >= Model%min_seaice) Sfcprop(nb)%slmsk(ix) = 2.0 + else + Sfcprop(nb)%landfrac(ix) = one + Sfcprop(nb)%lakefrac(ix) = zero + Sfcprop(nb)%oceanfrac(ix) = zero + endif + endif + else + if (nint(Sfcprop(nb)%slmsk(ix)) == 1 .and. Sfcprop(nb)%stype(ix) > 0 & + .and. Sfcprop(nb)%stype(ix) /= 14) then + Sfcprop(nb)%landfrac(ix) = one + Sfcprop(nb)%lakefrac(ix) = zero + Sfcprop(nb)%oceanfrac(ix) = zero + else + Sfcprop(nb)%slmsk(ix) = zero + Sfcprop(nb)%landfrac(ix) = zero + if (Sfcprop(nb)%oro_uf(ix) > min_lake_orog) then ! lakes + Sfcprop(nb)%lakefrac(ix) = one + Sfcprop(nb)%oceanfrac(ix) = zero + if (Sfcprop(nb)%fice(ix) > Model%min_lakeice) Sfcprop(nb)%slmsk(ix) = 2.0 + else ! ocean + Sfcprop(nb)%lakefrac(ix) = zero + Sfcprop(nb)%oceanfrac(ix) = one + if (Sfcprop(nb)%fice(ix) > Model%min_seaice) Sfcprop(nb)%slmsk(ix) = 2.0 + endif + endif + endif + endif if_frac_grid + enddo do_lsi_fractions + + if (warm_start .and. Model%kdt > 1) then + do ix = 1, Atm_block%blksz(nb) + Sfcprop(nb)%slmsk(ix) = sfc%var2(ii1(ix),jj1(ix),1) !--- slmsk + enddo + endif + + ! + !--- NSSTM variables + !tgs - the following line is a bug that will show if(Model%cplwav) = true + !nt = sfc%nvar2m + if (Model%nstf_name(1) > 0) then + if (Model%nstf_name(2) == 1) then ! nsst spinup + !--- nsstm tref + nt = nt + 18 + Sfcprop(nb)%tref = Sfcprop(nb)%tsfco + Sfcprop(nb)%z_c = zero + Sfcprop(nb)%c_0 = zero + Sfcprop(nb)%c_d = zero + Sfcprop(nb)%w_0 = zero + Sfcprop(nb)%w_d = zero + Sfcprop(nb)%xt = zero + Sfcprop(nb)%xs = zero + Sfcprop(nb)%xu = zero + Sfcprop(nb)%xv = zero + Sfcprop(nb)%xz = 20.0_kind_phys + Sfcprop(nb)%zm = zero + Sfcprop(nb)%xtts = zero + Sfcprop(nb)%xzts = zero + Sfcprop(nb)%d_conv = zero + Sfcprop(nb)%ifd = zero + Sfcprop(nb)%dt_cool = zero + Sfcprop(nb)%qrain = zero + elseif (Model%nstf_name(2) == 0) then ! nsst restart + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tref) !--- nsstm tref + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%z_c) !--- nsstm z_c + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_0) !--- nsstm c_0 + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_d) !--- nsstm c_d + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_0) !--- nsstm w_0 + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_d) !--- nsstm w_d + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xt) !--- nsstm xt + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xs) !--- nsstm xs + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xu) !--- nsstm xu + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xv) !--- nsstm xv + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xz) !--- nsstm xz + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zm) !--- nsstm zm + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xtts) !--- nsstm xtts + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xzts) !--- nsstm xzts + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ifd) !--- nsstm ifd + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%dt_cool) !--- nsstm dt_cool + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qrain) !--- nsstm qrain + endif + endif + + if (Model%lsm == Model%lsm_ruc .and. warm_start) then + !--- Extra RUC variables + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wetness) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_land) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_land) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_land) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_land) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd_bck) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) + if (Model%rdlai) then + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) + endif + else if (Model%lsm == Model%lsm_ruc) then + ! Initialize RUC snow cover on ice from snow cover + Sfcprop(nb)%sncovr_ice = Sfcprop(nb)%sncovr + if (Model%rdlai) then + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) + end if + elseif (Model%lsm == Model%lsm_noahmp) then + !--- Extra Noah MP variables + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tvxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tgxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canicexy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canliqxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%eahxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tahxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%cmxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%chxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fwetxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sneqvoxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alboldxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qsnowxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wslakexy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zwtxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%waxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wtxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%lfmassxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rtmassxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stmassxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%woodxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stblcpxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fastcpxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xsaixy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%taussxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%smcwtdxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%deeprechxy) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rechxy) + endif + if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_snow) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_ice) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_ML) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_ML) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_mnw) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_talb) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_talb) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot1) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot2) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_t) + endif + if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. (.not.warm_start)) then + !--- 3D variables + nt=0 + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc%var3,Sfcprop(nb)%stc) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc%var3,Sfcprop(nb)%smc) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc%var3,Sfcprop(nb)%slc) + + if (Model%lsm == Model%lsm_noahmp) then + ! These use weird indexing which is lost during a Fortran subroutine call, so we use loops instead: + nt=nt+1 + do lsoil = -2, 0 + do ix = 1, Atm_block%blksz(nb) + Sfcprop(nb)%snicexy(ix,lsoil) = sfc%var3sn(ii1(ix),jj1(ix),lsoil,nt) + enddo + enddo + + nt=nt+1 + do lsoil = -2, 0 + do ix = 1, Atm_block%blksz(nb) + Sfcprop(nb)%snliqxy(ix,lsoil) = sfc%var3sn(ii1(ix),jj1(ix),lsoil,nt) + enddo + enddo + + nt=nt+1 + do lsoil = -2, 0 + do ix = 1, Atm_block%blksz(nb) + Sfcprop(nb)%tsnoxy(ix,lsoil) = sfc%var3sn(ii1(ix),jj1(ix),lsoil,nt) + enddo + enddo + + nt=nt+1 + do lsoil = 1, 4 + do ix = 1, Atm_block%blksz(nb) + Sfcprop(nb)%smoiseq(ix,lsoil) = sfc%var3eq(ii1(ix),jj1(ix),lsoil,nt) + enddo + enddo + + nt=nt+1 + do lsoil = -2, 4 + do ix = 1, Atm_block%blksz(nb) + Sfcprop(nb)%zsnsoxy(ix,lsoil) = sfc%var3zn(ii1(ix),jj1(ix),lsoil,nt) + enddo + enddo + endif + + else if (Model%lsm == Model%lsm_ruc) then + !--- 3D variables + nt=0 + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%tslb) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%smois) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%sh2o) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%keepsmfr) + call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,1,Model%lsoil_lsm,sfc%var3,Sfcprop(nb)%flag_frsoil) + endif + + do k = 1,Model%kice + do ix = 1, Atm_block%blksz(nb) + Sfcprop(nb)%tiice(ix,k) = sfc%var3ice(ii1(ix),jj1(ix),k) !--- internal ice temp + enddo + enddo + + deallocate(ii1,jj1) + + end do block_loop + end subroutine Sfc_io_copy_to_grid + subroutine Sfc_io_final(sfc) implicit none type(Sfc_io_data_type) :: sfc From ce0ba006fc32bbf520ee24f57f3eafff66647f02 Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Wed, 10 May 2023 01:54:24 +0000 Subject: [PATCH 09/27] Put post-read safeguards in FV3GFS_sfc_io.F90 --- io/FV3GFS_io.F90 | 209 +------------------------------------ io/FV3GFS_sfc_io.F90 | 241 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 238 insertions(+), 212 deletions(-) diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index 18f24ae68..5d0a6dbf2 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -101,7 +101,6 @@ module FV3GFS_io_mod real, parameter:: stndrd_atmos_ps = 101325.0_r8 real, parameter:: stndrd_atmos_lapse = 0.0065_r8 real, parameter:: drythresh = 1.e-4_r8, zero = 0.0_r8, one = 1.0_r8 - real(kind=kind_phys), parameter :: timin = 173.0_r8 ! minimum temperature allowed for snow/ice type(Sfc_io_data_type) :: sfc @@ -939,213 +938,7 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta call mpp_error(NOTE, 'gfs_driver:: - after put to container ') -! so far: At cold start everything is 9999.0, warm start snowxy has values -! but the 3D of snow fields are not available because not allocated yet. -! ix,nb loops may be consolidate with the Noah MP isnowxy init -! restore traditional vars first,we need some of them to init snow fields -! snow depth to actual snow layers; so we can allocate and register -! note zsnsoxy is from -2:4 - isnowxy is from 0:-2, but we need -! exact snow layers to pass 3D fields correctly, snow layers are -! different fro grid to grid, we have to init point by point/grid. -! It has to be done after the weasd is available -! sfc%var2(1,1,32) is the first; we need this to allocate snow related fields - - i = Atm_block%index(1)%ii(1) - isc + 1 - j = Atm_block%index(1)%jj(1) - jsc + 1 - - if (sfc%var2(i,j,33) < -9990.0_r8) then - if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing snodl') -!$omp parallel do default(shared) private(nb, ix, tem) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - if (Sfcprop(nb)%landfrac(ix) > zero) then - tem = one / (Sfcprop(nb)%fice(ix)*(one-Sfcprop(nb)%landfrac(ix))+Sfcprop(nb)%landfrac(ix)) - Sfcprop(nb)%snodl(ix) = Sfcprop(nb)%snowd(ix) * tem - else - Sfcprop(nb)%snodl(ix) = zero - endif - enddo - enddo - endif - - if (sfc%var2(i,j,34) < -9990.0_r8) then - if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing weasdl') -!$omp parallel do default(shared) private(nb, ix, tem) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - if (Sfcprop(nb)%landfrac(ix) > zero) then - tem = one / (Sfcprop(nb)%fice(ix)*(one-Sfcprop(nb)%landfrac(ix))+Sfcprop(nb)%landfrac(ix)) - Sfcprop(nb)%weasdl(ix) = Sfcprop(nb)%weasd(ix) * tem - else - Sfcprop(nb)%weasdl(ix) = zero - endif - enddo - enddo - endif - - if (sfc%var2(i,j,36) < -9990.0_r8) then - if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing tsfcl') -!$omp parallel do default(shared) private(nb, ix) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%tsfcl(ix) = Sfcprop(nb)%tsfco(ix) !--- compute tsfcl from existing variables - enddo - enddo - endif - - if (sfc%var2(i,j,37) < -9990.0_r8) then - if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing zorlw') -!$omp parallel do default(shared) private(nb, ix) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - if (Sfcprop(nb)%landfrac(ix) < one .and. Sfcprop(nb)%fice(ix) < one) then - Sfcprop(nb)%zorlw(ix) = min(Sfcprop(nb)%zorl(ix), 0.317) - endif - enddo - enddo - endif - - if (sfc%var2(i,j,38) < -9990.0_r8) then - if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing zorll') -!$omp parallel do default(shared) private(nb, ix) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%zorll(ix) = Sfcprop(nb)%zorl(ix) !--- compute zorll from existing variables - enddo - enddo - endif - - if (sfc%var2(i,j,39) < -9990.0_r8) then - if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing zorli') -!$omp parallel do default(shared) private(nb, ix) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - if (Sfcprop(nb)%fice(ix)*(one-Sfcprop(nb)%landfrac(ix)) > zero) then - Sfcprop(nb)%zorli(ix) = one - endif - enddo - enddo - endif - - if (sfc%var2(i,j,45) < -9990.0_r8) then - if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing emis_ice') -!$omp parallel do default(shared) private(nb, ix) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%emis_ice(ix) = 0.96 - enddo - enddo - endif - - if (sfc%var2(i,j,46) < -9990.0_r8 .and. Model%lsm /= Model%lsm_ruc) then - if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing sncovr_ice') -!$omp parallel do default(shared) private(nb, ix) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) -! Sfcprop(nb)%sncovr_ice(ix) = Sfcprop(nb)%sncovr(ix) - Sfcprop(nb)%sncovr_ice(ix) = zero - enddo - enddo - endif - - if (sfc%var2(i,j,47) < -9990.0_r8) then - if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing snodi') -!$omp parallel do default(shared) private(nb, ix, tem) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - if (Sfcprop(nb)%fice(ix) > zero) then - tem = one / (Sfcprop(nb)%fice(ix)*(one-Sfcprop(nb)%landfrac(ix))+Sfcprop(nb)%landfrac(ix)) - Sfcprop(nb)%snodi(ix) = min(Sfcprop(nb)%snowd(ix) * tem, 3.0) - else - Sfcprop(nb)%snodi(ix) = zero - endif - enddo - enddo - endif - - if (sfc%var2(i,j,48) < -9990.0_r8) then - if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing weasdi') -!$omp parallel do default(shared) private(nb, ix, tem) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - if (Sfcprop(nb)%fice(ix) > zero) then - tem = one / (Sfcprop(nb)%fice(ix)*(one-Sfcprop(nb)%landfrac(ix))+Sfcprop(nb)%landfrac(ix)) - Sfcprop(nb)%weasdi(ix) = Sfcprop(nb)%weasd(ix)*tem - else - Sfcprop(nb)%weasdi(ix) = zero - endif - enddo - enddo - endif - - if (Model%use_cice_alb) then - if (sfc%var2(i,j,49) < -9990.0_r8) then -!$omp parallel do default(shared) private(nb, ix) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - if (Sfcprop(nb)%oceanfrac(ix) > zero .and. & - Sfcprop(nb)%fice(ix) >= Model%min_seaice) then - Sfcprop(nb)%albdirvis_ice(ix) = 0.6_kind_phys - Sfcprop(nb)%albdifvis_ice(ix) = 0.6_kind_phys - Sfcprop(nb)%albdirnir_ice(ix) = 0.6_kind_phys - Sfcprop(nb)%albdifnir_ice(ix) = 0.6_kind_phys - endif - enddo - enddo - endif - - endif - - ! Fill in composite tsfc for coldstart runs - must happen after tsfcl is computed - compute_tsfc_for_colstart: if (sfc%var2(i,j,35) < -9990.0_r8) then - if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing composite tsfc') - if(Model%frac_grid) then ! 3-way composite -!$omp parallel do default(shared) private(nb, ix, tem, tem1) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%tsfco(ix) = max(con_tice, Sfcprop(nb)%tsfco(ix)) ! this may break restart reproducibility - tem1 = one - Sfcprop(nb)%landfrac(ix) - tem = tem1 * Sfcprop(nb)%fice(ix) ! tem = ice fraction wrt whole cell - Sfcprop(nb)%tsfc(ix) = Sfcprop(nb)%tsfcl(ix) * Sfcprop(nb)%landfrac(ix) & - + Sfcprop(nb)%tisfc(ix) * tem & - + Sfcprop(nb)%tsfco(ix) * (tem1-tem) - enddo - enddo - else -!$omp parallel do default(shared) private(nb, ix, tem) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - if (Sfcprop(nb)%slmsk(ix) == 1) then - Sfcprop(nb)%tsfc(ix) = Sfcprop(nb)%tsfcl(ix) - else - tem = one - Sfcprop(nb)%fice(ix) - Sfcprop(nb)%tsfc(ix) = Sfcprop(nb)%tisfc(ix) * Sfcprop(nb)%fice(ix) & - + Sfcprop(nb)%tsfco(ix) * tem - endif - enddo - enddo - endif - endif compute_tsfc_for_colstart - - if (sfc%var2(i,j,sfc%nvar2m) < -9990.0_r8) then - if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing zorlwav') -!$omp parallel do default(shared) private(nb, ix) - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%zorlwav(ix) = Sfcprop(nb)%zorl(ix) !--- compute zorlwav from existing variables - enddo - enddo - endif - - if (nint(sfc%var3ice(1,1,1)) == -9999) then !--- initialize internal ice temp from layer 1 and 2 soil temp - if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing tiice') - do nb = 1, Atm_block%nblks - do ix = 1, Atm_block%blksz(nb) - Sfcprop(nb)%tiice(ix,1) = max(timin, min(con_tice, Sfcprop(nb)%stc(ix,1))) - Sfcprop(nb)%tiice(ix,2) = max(timin, min(con_tice, Sfcprop(nb)%stc(ix,2))) - enddo - enddo - endif + call sfc%apply_safeguards(Model, Atm_block, Sfcprop) ! A standard-compliant Fortran 2003 compiler will call clm_lake_final and rrfs_sd_final here. diff --git a/io/FV3GFS_sfc_io.F90 b/io/FV3GFS_sfc_io.F90 index cdf92c177..ebab3f0e6 100644 --- a/io/FV3GFS_sfc_io.F90 +++ b/io/FV3GFS_sfc_io.F90 @@ -20,8 +20,9 @@ module FV3GFS_sfc_io public :: Sfc_io_fill_2d_names, Sfc_io_fill_3d_names, Sfc_io_allocate_arrays, & Sfc_io_register_axes, Sfc_io_write_axes, & Sfc_io_register_2d_fields, Sfc_io_register_3d_fields, & - Sfc_io_copy_to_grid, Sfc_io_final + Sfc_io_copy_to_grid, Sfc_io_apply_safeguards, Sfc_io_final + real(kind=kind_phys), parameter :: timin = 173.0_kind_phys ! minimum temperature allowed for snow/ice real(kind_phys), parameter:: min_lake_orog = 200.0_kind_phys real(kind_phys), parameter:: zero = 0, one = 1 @@ -69,6 +70,7 @@ module FV3GFS_sfc_io procedure, public :: fill_3d_names => Sfc_io_fill_3d_names procedure, public :: init_fields => Sfc_io_init_fields procedure, public :: copy_to_grid => Sfc_io_copy_to_grid + procedure, public :: apply_safeguards => Sfc_io_apply_safeguards procedure, private :: calculate_indices => Sfc_io_calculate_indices @@ -725,9 +727,9 @@ subroutine Sfc_io_copy_to_grid(sfc, Model, Atm_block, Sfcprop, warm_start, overr nx = (iec - isc + 1) ny = (jec - jsc + 1) -! 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)) -! write(0,*)' sfc_var2=',sfc_var2(:,:,12) + ! 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)) + ! write(0,*)' sfc_var2=',sfc_var2(:,:,12) !$omp parallel do default(shared) private(i, j, nb, ix, nt, ii1, jj1, lsoil) block_loop: do nb = 1, Atm_block%nblks @@ -1095,6 +1097,237 @@ subroutine Sfc_io_copy_to_grid(sfc, Model, Atm_block, Sfcprop, warm_start, overr end do block_loop end subroutine Sfc_io_copy_to_grid + subroutine Sfc_io_apply_safeguards(sfc, Model, Atm_block, Sfcprop) + !--- interface variable definitions + implicit none + + class(Sfc_io_data_type) :: sfc + type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) + type(block_control_type), intent(in) :: Atm_block + type(GFS_control_type), intent(in) :: Model + + integer :: i, j, k, nb, ix, lsoil, num, nt + integer :: isc, iec, jsc, jec, npz, nx, ny + real(kind_phys) :: ice, tem, tem1 + + isc = Atm_block%isc + iec = Atm_block%iec + jsc = Atm_block%jsc + jec = Atm_block%jec + npz = Atm_block%npz + nx = (iec - isc + 1) + ny = (jec - jsc + 1) + + ! so far: At cold start everything is 9999.0, warm start snowxy has values + ! but the 3D of snow fields are not available because not allocated yet. + ! ix,nb loops may be consolidate with the Noah MP isnowxy init + ! restore traditional vars first,we need some of them to init snow fields + ! snow depth to actual snow layers; so we can allocate and register + ! note zsnsoxy is from -2:4 - isnowxy is from 0:-2, but we need + ! exact snow layers to pass 3D fields correctly, snow layers are + ! different fro grid to grid, we have to init point by point/grid. + ! It has to be done after the weasd is available + ! sfc%var2(1,1,32) is the first; we need this to allocate snow related fields + + i = Atm_block%index(1)%ii(1) - isc + 1 + j = Atm_block%index(1)%jj(1) - jsc + 1 + + if (sfc%var2(i,j,33) < -9990.0_kind_phys) then + if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing snodl') + !$omp parallel do default(shared) private(nb, ix, tem) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + if (Sfcprop(nb)%landfrac(ix) > zero) then + tem = one / (Sfcprop(nb)%fice(ix)*(one-Sfcprop(nb)%landfrac(ix))+Sfcprop(nb)%landfrac(ix)) + Sfcprop(nb)%snodl(ix) = Sfcprop(nb)%snowd(ix) * tem + else + Sfcprop(nb)%snodl(ix) = zero + endif + enddo + enddo + endif + + if (sfc%var2(i,j,34) < -9990.0_kind_phys) then + if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing weasdl') + !$omp parallel do default(shared) private(nb, ix, tem) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + if (Sfcprop(nb)%landfrac(ix) > zero) then + tem = one / (Sfcprop(nb)%fice(ix)*(one-Sfcprop(nb)%landfrac(ix))+Sfcprop(nb)%landfrac(ix)) + Sfcprop(nb)%weasdl(ix) = Sfcprop(nb)%weasd(ix) * tem + else + Sfcprop(nb)%weasdl(ix) = zero + endif + enddo + enddo + endif + + if (sfc%var2(i,j,36) < -9990.0_kind_phys) then + if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing tsfcl') + !$omp parallel do default(shared) private(nb, ix) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + Sfcprop(nb)%tsfcl(ix) = Sfcprop(nb)%tsfco(ix) !--- compute tsfcl from existing variables + enddo + enddo + endif + + if (sfc%var2(i,j,37) < -9990.0_kind_phys) then + if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing zorlw') + !$omp parallel do default(shared) private(nb, ix) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + if (Sfcprop(nb)%landfrac(ix) < one .and. Sfcprop(nb)%fice(ix) < one) then + Sfcprop(nb)%zorlw(ix) = min(Sfcprop(nb)%zorl(ix), 0.317) + endif + enddo + enddo + endif + + if (sfc%var2(i,j,38) < -9990.0_kind_phys) then + if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing zorll') + !$omp parallel do default(shared) private(nb, ix) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + Sfcprop(nb)%zorll(ix) = Sfcprop(nb)%zorl(ix) !--- compute zorll from existing variables + enddo + enddo + endif + + if (sfc%var2(i,j,39) < -9990.0_kind_phys) then + if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing zorli') + !$omp parallel do default(shared) private(nb, ix) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + if (Sfcprop(nb)%fice(ix)*(one-Sfcprop(nb)%landfrac(ix)) > zero) then + Sfcprop(nb)%zorli(ix) = one + endif + enddo + enddo + endif + + if (sfc%var2(i,j,45) < -9990.0_kind_phys) then + if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing emis_ice') + !$omp parallel do default(shared) private(nb, ix) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + Sfcprop(nb)%emis_ice(ix) = 0.96 + enddo + enddo + endif + + if (sfc%var2(i,j,46) < -9990.0_kind_phys .and. Model%lsm /= Model%lsm_ruc) then + if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing sncovr_ice') + !$omp parallel do default(shared) private(nb, ix) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + ! Sfcprop(nb)%sncovr_ice(ix) = Sfcprop(nb)%sncovr(ix) + Sfcprop(nb)%sncovr_ice(ix) = zero + enddo + enddo + endif + + if (sfc%var2(i,j,47) < -9990.0_kind_phys) then + if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing snodi') + !$omp parallel do default(shared) private(nb, ix, tem) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + if (Sfcprop(nb)%fice(ix) > zero) then + tem = one / (Sfcprop(nb)%fice(ix)*(one-Sfcprop(nb)%landfrac(ix))+Sfcprop(nb)%landfrac(ix)) + Sfcprop(nb)%snodi(ix) = min(Sfcprop(nb)%snowd(ix) * tem, 3.0) + else + Sfcprop(nb)%snodi(ix) = zero + endif + enddo + enddo + endif + + if (sfc%var2(i,j,48) < -9990.0_kind_phys) then + if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing weasdi') + !$omp parallel do default(shared) private(nb, ix, tem) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + if (Sfcprop(nb)%fice(ix) > zero) then + tem = one / (Sfcprop(nb)%fice(ix)*(one-Sfcprop(nb)%landfrac(ix))+Sfcprop(nb)%landfrac(ix)) + Sfcprop(nb)%weasdi(ix) = Sfcprop(nb)%weasd(ix)*tem + else + Sfcprop(nb)%weasdi(ix) = zero + endif + enddo + enddo + endif + + if (Model%use_cice_alb) then + if (sfc%var2(i,j,49) < -9990.0_kind_phys) then + !$omp parallel do default(shared) private(nb, ix) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + if (Sfcprop(nb)%oceanfrac(ix) > zero .and. & + Sfcprop(nb)%fice(ix) >= Model%min_seaice) then + Sfcprop(nb)%albdirvis_ice(ix) = 0.6_kind_phys + Sfcprop(nb)%albdifvis_ice(ix) = 0.6_kind_phys + Sfcprop(nb)%albdirnir_ice(ix) = 0.6_kind_phys + Sfcprop(nb)%albdifnir_ice(ix) = 0.6_kind_phys + endif + enddo + enddo + endif + + endif + + ! Fill in composite tsfc for coldstart runs - must happen after tsfcl is computed + compute_tsfc_for_colstart: if (sfc%var2(i,j,35) < -9990.0_kind_phys) then + if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing composite tsfc') + if(Model%frac_grid) then ! 3-way composite + !$omp parallel do default(shared) private(nb, ix, tem, tem1) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + Sfcprop(nb)%tsfco(ix) = max(con_tice, Sfcprop(nb)%tsfco(ix)) ! this may break restart reproducibility + tem1 = one - Sfcprop(nb)%landfrac(ix) + tem = tem1 * Sfcprop(nb)%fice(ix) ! tem = ice fraction wrt whole cell + Sfcprop(nb)%tsfc(ix) = Sfcprop(nb)%tsfcl(ix) * Sfcprop(nb)%landfrac(ix) & + + Sfcprop(nb)%tisfc(ix) * tem & + + Sfcprop(nb)%tsfco(ix) * (tem1-tem) + enddo + enddo + else + !$omp parallel do default(shared) private(nb, ix, tem) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + if (Sfcprop(nb)%slmsk(ix) == 1) then + Sfcprop(nb)%tsfc(ix) = Sfcprop(nb)%tsfcl(ix) + else + tem = one - Sfcprop(nb)%fice(ix) + Sfcprop(nb)%tsfc(ix) = Sfcprop(nb)%tisfc(ix) * Sfcprop(nb)%fice(ix) & + + Sfcprop(nb)%tsfco(ix) * tem + endif + enddo + enddo + endif + endif compute_tsfc_for_colstart + + if (sfc%var2(i,j,sfc%nvar2m) < -9990.0_kind_phys) then + if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing zorlwav') + !$omp parallel do default(shared) private(nb, ix) + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + Sfcprop(nb)%zorlwav(ix) = Sfcprop(nb)%zorl(ix) !--- compute zorlwav from existing variables + enddo + enddo + endif + + if (nint(sfc%var3ice(1,1,1)) == -9999) then !--- initialize internal ice temp from layer 1 and 2 soil temp + if (Model%me == Model%master ) call mpp_error(NOTE, 'gfs_driver::surface_props_input - computing tiice') + do nb = 1, Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + Sfcprop(nb)%tiice(ix,1) = max(timin, min(con_tice, Sfcprop(nb)%stc(ix,1))) + Sfcprop(nb)%tiice(ix,2) = max(timin, min(con_tice, Sfcprop(nb)%stc(ix,2))) + enddo + enddo + endif + + end subroutine Sfc_io_apply_safeguards + subroutine Sfc_io_final(sfc) implicit none type(Sfc_io_data_type) :: sfc From b656b73b8ce3db14ca02eaffc967b683ef240631 Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Wed, 10 May 2023 17:53:10 +0000 Subject: [PATCH 10/27] copy to grid in FV3GFS_sfc_io.F90 and make things private --- io/FV3GFS_io.F90 | 238 +---------------------------------- io/FV3GFS_sfc_io.F90 | 290 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 272 insertions(+), 256 deletions(-) diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index 5d0a6dbf2..84818b0e2 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -567,7 +567,6 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta character(37) :: infile !--- fms2_io file open logic logical :: amiopen - logical :: is_lsoil logical :: override_frac_grid type(clm_lake_data_type) :: clm_lake @@ -889,7 +888,6 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta if(sfc%allocate_arrays(Model, Atm_block, .false., warm_start)) then call sfc%fill_2d_names(Model, warm_start) call sfc%register_axes(Model, Sfc_restart, .false., warm_start) - is_lsoil = sfc%is_lsoil ! Tell CLM Lake to allocate data, and register its axes and fields if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then @@ -989,8 +987,6 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta !--- temporary variables for storing rrfs_sd fields type(rrfs_sd_state_type) :: rrfs_sd_state - print *,sfc%nvar_before_lake - isc = Atm_block%isc iec = Atm_block%iec jsc = Atm_block%jsc @@ -1029,18 +1025,9 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta call sfc%fill_2d_names(Model,.true.) end if - if(Model%lkm>0) then - if(Model%iopt_lake==Model%iopt_lake_flake ) then - if(Model%me==0) then - if(size(sfc%name2)/=sfc%nvar_before_lake+10) then -3814 format("ERROR: size mismatch size(sfc%name2)=",I0," /= sfc%nvar_before_lake+10=",I0) - write(0,3814) size(sfc%name2),sfc%nvar_before_lake+10 - endif - endif - else if(Model%iopt_lake==Model%iopt_lake_clm) then + if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then ! Tell clm_lake to register all of its fields call clm_lake%register_fields(Sfc_restart) - endif endif if(Model%rrfs_sd) then @@ -1065,228 +1052,7 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta call rrfs_sd_state%copy_to_temporaries(Model,Sfcprop,Atm_block) endif -!$omp parallel do default(shared) private(i, j, nb, ix, nt, ii1, jj1, lsoil, k, ice) - block_loop: do nb = 1, Atm_block%nblks - allocate(ii1(Atm_block%blksz(nb))) - allocate(jj1(Atm_block%blksz(nb))) - ii1=Atm_block%index(nb)%ii - isc + 1 - jj1=Atm_block%index(nb)%jj - jsc + 1 - - nt=0 - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slmsk) !--- slmsk - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tg3) !--- tg3 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorl) !--- zorl - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvsf) !--- alvsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvwf) !--- alvwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnsf) !--- alnsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnwf) !--- alnwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facsf) !--- facsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facwf) !--- facwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vfrac) !--- vfrac - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canopy)!--- canopy - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%f10m) !--- f10m - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t2m) !--- t2m - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%q2m) !--- q2m - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vtype) !--- vtype - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stype) !--- stype - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%uustar)!--- uustar - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffmm) !--- ffmm - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffhh) !--- ffhh - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%hice) !--- hice - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fice) !--- fice - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tisfc) !--- tisfc - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tprcp) !--- tprcp - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%srflag)!--- srflag - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmin)!--- shdmin - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmax)!--- shdmax - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slope) !--- slope - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snoalb)!--- snoalb - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr) !--- sncovr - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfc) !--- tsfc composite - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlw) !--- zorl (zorl on water) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice) - if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_ice) -! sfc%var2(i,j,53) = Sfcprop(nb)%sfalb_ice(ix) - endif - if (Model%cplwav) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlwav) !--- zorlwav (zorl from wav) - endif - !--- NSSTM variables - if (Model%nstf_name(1) > 0) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tref) !--- nsstm tref - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%z_c) !--- nsstm z_c - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_0) !--- nsstm c_0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_d) !--- nsstm c_d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_0) !--- nsstm w_0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_d) !--- nsstm w_d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xt) !--- nsstm xt - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xs) !--- nsstm xs - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xu) !--- nsstm xu - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xv) !--- nsstm xv - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xz) !--- nsstm xz - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zm) !--- nsstm zm - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xtts) !--- nsstm xtts - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xzts) !--- nsstm xzts - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ifd) !--- nsstm ifd - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%dt_cool)!--- nsstm dt_cool - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qrain) !--- nsstm qrain - endif - - if (Model%lsm == Model%lsm_ruc) then - !--- Extra RUC variables - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wetness) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd_bck) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) - if (Model%rdlai) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) - endif - else if (Model%lsm == Model%lsm_noahmp) then - !--- Extra Noah MP variables - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tvxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tgxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canicexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canliqxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%eahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%cmxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%chxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fwetxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sneqvoxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alboldxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qsnowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wslakexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zwtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%waxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%lfmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rtmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%woodxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stblcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fastcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xsaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%taussxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%smcwtdxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%deeprechxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rechxy) - endif -! Flake - if(Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_snow) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_ML) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_ML) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_mnw) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_talb) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_talb) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot1) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot2) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_t) - endif - do k = 1,Model%kice - do ix = 1, Atm_block%blksz(nb) - ice=Sfcprop(nb)%tiice(ix,k) - if(ice null() - real(kind=kind_phys), pointer, dimension(:,:,:), public :: var3ice => null() - real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3 => null() - real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3sn => null() - real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3eq => null() - real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3zn => null() + real(kind=kind_phys), pointer, dimension(:,:,:), private :: var2 => null() + real(kind=kind_phys), pointer, dimension(:,:,:), private :: var3ice => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), private :: var3 => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), private :: var3sn => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), private :: var3eq => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), private :: var3zn => null() - character(len=32), pointer, dimension(:), public :: name2 => null() + character(len=32), pointer, dimension(:), private :: name2 => null() + character(len=32), pointer, dimension(:), private :: name3 => null() - character(len=32), pointer, dimension(:), public :: name3 => null() contains procedure, public :: allocate_arrays => Sfc_io_allocate_arrays @@ -70,6 +70,7 @@ module FV3GFS_sfc_io procedure, public :: fill_3d_names => Sfc_io_fill_3d_names procedure, public :: init_fields => Sfc_io_init_fields procedure, public :: copy_to_grid => Sfc_io_copy_to_grid + procedure, public :: copy_from_grid => Sfc_io_copy_from_grid procedure, public :: apply_safeguards => Sfc_io_apply_safeguards procedure, private :: calculate_indices => Sfc_io_calculate_indices @@ -1097,6 +1098,255 @@ subroutine Sfc_io_copy_to_grid(sfc, Model, Atm_block, Sfcprop, warm_start, overr end do block_loop end subroutine Sfc_io_copy_to_grid + subroutine Sfc_io_copy_from_grid(sfc, Model, Atm_block, Sfcprop) + !--- interface variable definitions + implicit none + + class(Sfc_io_data_type) :: sfc + type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) + type(block_control_type), intent(in) :: Atm_block + type(GFS_control_type), intent(in) :: Model + + integer :: i, j, k, nb, ix, lsoil, num, nt + integer :: isc, iec, jsc, jec, npz, nx, ny + integer, allocatable :: ii1(:), jj1(:) + real(kind_phys) :: ice + + isc = Atm_block%isc + iec = Atm_block%iec + jsc = Atm_block%jsc + jec = Atm_block%jec + npz = Atm_block%npz + nx = (iec - isc + 1) + ny = (jec - jsc + 1) + + !$omp parallel do default(shared) private(i, j, nb, ix, nt, ii1, jj1, lsoil, k, ice) + block_loop: do nb = 1, Atm_block%nblks + allocate(ii1(Atm_block%blksz(nb))) + allocate(jj1(Atm_block%blksz(nb))) + ii1=Atm_block%index(nb)%ii - isc + 1 + jj1=Atm_block%index(nb)%jj - jsc + 1 + + nt=0 + + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slmsk) !--- slmsk + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tg3) !--- tg3 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorl) !--- zorl + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvsf) !--- alvsf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvwf) !--- alvwf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnsf) !--- alnsf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnwf) !--- alnwf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facsf) !--- facsf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facwf) !--- facwf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vfrac) !--- vfrac + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canopy)!--- canopy + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%f10m) !--- f10m + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t2m) !--- t2m + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%q2m) !--- q2m + + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vtype) !--- vtype + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stype) !--- stype + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%uustar)!--- uustar + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffmm) !--- ffmm + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffhh) !--- ffhh + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%hice) !--- hice + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fice) !--- fice + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tisfc) !--- tisfc + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tprcp) !--- tprcp + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%srflag)!--- srflag + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmin)!--- shdmin + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmax)!--- shdmax + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slope) !--- slope + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snoalb)!--- snoalb + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr) !--- sncovr + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfc) !--- tsfc composite + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlw) !--- zorl (zorl on water) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice) + if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_ice) + ! sfc%var2(i,j,53) = Sfcprop(nb)%sfalb_ice(ix) + endif + if (Model%cplwav) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlwav) !--- zorlwav (zorl from wav) + endif + !--- NSSTM variables + if (Model%nstf_name(1) > 0) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tref) !--- nsstm tref + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%z_c) !--- nsstm z_c + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_0) !--- nsstm c_0 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_d) !--- nsstm c_d + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_0) !--- nsstm w_0 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_d) !--- nsstm w_d + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xt) !--- nsstm xt + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xs) !--- nsstm xs + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xu) !--- nsstm xu + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xv) !--- nsstm xv + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xz) !--- nsstm xz + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zm) !--- nsstm zm + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xtts) !--- nsstm xtts + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xzts) !--- nsstm xzts + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ifd) !--- nsstm ifd + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%dt_cool)!--- nsstm dt_cool + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qrain) !--- nsstm qrain + + ! FIXME convert negative zero (-0.0) to zero (0.0) + do j=1,ny + do i=1,nx + if(sfc%var2(i,j,nt) == 0.0) sfc%var2(i,j,nt) = 0.0 + end do + end do + endif + + if (Model%lsm == Model%lsm_ruc) then + !--- Extra RUC variables + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wetness) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd_bck) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) + if (Model%rdlai) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) + endif + else if (Model%lsm == Model%lsm_noahmp) then + !--- Extra Noah MP variables + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tvxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tgxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canicexy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canliqxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%eahxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tahxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%cmxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%chxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fwetxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sneqvoxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alboldxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qsnowxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wslakexy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zwtxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%waxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wtxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%lfmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rtmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%woodxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stblcpxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fastcpxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xsaixy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%taussxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%smcwtdxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%deeprechxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rechxy) + endif + + do k = 1,Model%kice + do ix = 1, Atm_block%blksz(nb) + ice=Sfcprop(nb)%tiice(ix,k) + if(ice Date: Wed, 10 May 2023 20:55:44 +0000 Subject: [PATCH 11/27] fix discrepancies in copying from grid --- io/FV3GFS_sfc_io.F90 | 420 +++++++++++++++++++++---------------------- 1 file changed, 209 insertions(+), 211 deletions(-) diff --git a/io/FV3GFS_sfc_io.F90 b/io/FV3GFS_sfc_io.F90 index 210f070be..8be70aa6d 100644 --- a/io/FV3GFS_sfc_io.F90 +++ b/io/FV3GFS_sfc_io.F90 @@ -1120,229 +1120,227 @@ subroutine Sfc_io_copy_from_grid(sfc, Model, Atm_block, Sfcprop) nx = (iec - isc + 1) ny = (jec - jsc + 1) - !$omp parallel do default(shared) private(i, j, nb, ix, nt, ii1, jj1, lsoil, k, ice) +!$omp parallel do default(shared) private(i, j, nb, ix, nt, ii1, jj1, lsoil, k, ice) block_loop: do nb = 1, Atm_block%nblks - allocate(ii1(Atm_block%blksz(nb))) - allocate(jj1(Atm_block%blksz(nb))) - ii1=Atm_block%index(nb)%ii - isc + 1 - jj1=Atm_block%index(nb)%jj - jsc + 1 - - nt=0 - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slmsk) !--- slmsk - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tg3) !--- tg3 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorl) !--- zorl - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvsf) !--- alvsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvwf) !--- alvwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnsf) !--- alnsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnwf) !--- alnwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facsf) !--- facsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facwf) !--- facwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vfrac) !--- vfrac - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canopy)!--- canopy - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%f10m) !--- f10m - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t2m) !--- t2m - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%q2m) !--- q2m - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vtype) !--- vtype - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stype) !--- stype - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%uustar)!--- uustar - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffmm) !--- ffmm - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffhh) !--- ffhh - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%hice) !--- hice - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fice) !--- fice - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tisfc) !--- tisfc - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tprcp) !--- tprcp - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%srflag)!--- srflag - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmin)!--- shdmin - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmax)!--- shdmax - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slope) !--- slope - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snoalb)!--- snoalb - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr) !--- sncovr - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfc) !--- tsfc composite - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlw) !--- zorl (zorl on water) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice) - if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_ice) - ! sfc%var2(i,j,53) = Sfcprop(nb)%sfalb_ice(ix) - endif - if (Model%cplwav) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlwav) !--- zorlwav (zorl from wav) - endif - !--- NSSTM variables - if (Model%nstf_name(1) > 0) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tref) !--- nsstm tref - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%z_c) !--- nsstm z_c - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_0) !--- nsstm c_0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_d) !--- nsstm c_d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_0) !--- nsstm w_0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_d) !--- nsstm w_d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xt) !--- nsstm xt - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xs) !--- nsstm xs - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xu) !--- nsstm xu - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xv) !--- nsstm xv - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xz) !--- nsstm xz - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zm) !--- nsstm zm - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xtts) !--- nsstm xtts - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xzts) !--- nsstm xzts - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ifd) !--- nsstm ifd - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%dt_cool)!--- nsstm dt_cool - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qrain) !--- nsstm qrain - - ! FIXME convert negative zero (-0.0) to zero (0.0) - do j=1,ny - do i=1,nx - if(sfc%var2(i,j,nt) == 0.0) sfc%var2(i,j,nt) = 0.0 - end do - end do - endif - - if (Model%lsm == Model%lsm_ruc) then - !--- Extra RUC variables - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wetness) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd_bck) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) - if (Model%rdlai) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) - endif - else if (Model%lsm == Model%lsm_noahmp) then - !--- Extra Noah MP variables - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tvxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tgxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canicexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canliqxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%eahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%cmxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%chxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fwetxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sneqvoxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alboldxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qsnowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wslakexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zwtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%waxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%lfmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rtmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%woodxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stblcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fastcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xsaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%taussxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%smcwtdxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%deeprechxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rechxy) - endif - - do k = 1,Model%kice - do ix = 1, Atm_block%blksz(nb) - ice=Sfcprop(nb)%tiice(ix,k) - if(ice 0) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tref) !--- nsstm tref + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%z_c) !--- nsstm z_c + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_0) !--- nsstm c_0 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_d) !--- nsstm c_d + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_0) !--- nsstm w_0 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_d) !--- nsstm w_d + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xt) !--- nsstm xt + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xs) !--- nsstm xs + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xu) !--- nsstm xu + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xv) !--- nsstm xv + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xz) !--- nsstm xz + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zm) !--- nsstm zm + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xtts) !--- nsstm xtts + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xzts) !--- nsstm xzts + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ifd) !--- nsstm ifd + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%dt_cool)!--- nsstm dt_cool + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qrain) !--- nsstm qrain + endif + + if (Model%lsm == Model%lsm_ruc) then + !--- Extra RUC variables + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wetness) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd_bck) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) + if (Model%rdlai) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) + endif + else if (Model%lsm == Model%lsm_noahmp) then + !--- Extra Noah MP variables + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tvxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tgxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canicexy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canliqxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%eahxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tahxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%cmxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%chxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fwetxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sneqvoxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alboldxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qsnowxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wslakexy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zwtxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%waxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wtxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%lfmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rtmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%woodxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stblcpxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fastcpxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xsaixy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%taussxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%smcwtdxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%deeprechxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rechxy) + endif +! Flake + if(Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_snow) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_ML) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_ML) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_mnw) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_talb) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_talb) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot1) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot2) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_t) + endif + do k = 1,Model%kice + do ix = 1, Atm_block%blksz(nb) + ice=Sfcprop(nb)%tiice(ix,k) + if(ice Date: Wed, 17 May 2023 00:18:47 +0000 Subject: [PATCH 12/27] combine sfc read & write into one routine --- io/FV3GFS_common_io.F90 | 146 ++++++- io/FV3GFS_io.F90 | 16 +- io/FV3GFS_sfc_io.F90 | 853 ++++++++++++++++------------------------ 3 files changed, 502 insertions(+), 513 deletions(-) diff --git a/io/FV3GFS_common_io.F90 b/io/FV3GFS_common_io.F90 index 8d3f23df4..ce0fc60f6 100644 --- a/io/FV3GFS_common_io.F90 +++ b/io/FV3GFS_common_io.F90 @@ -12,6 +12,14 @@ module FV3GFS_common_io copy_to_GFS_Data_2d_phys2phys, copy_to_GFS_Data_3d_phys2phys, & copy_to_GFS_Data_2d_int2phys, copy_to_GFS_Data_3d_int2phys + public :: GFS_data_transfer + public :: GFS_data_transfer_2d_phys2phys, & + GFS_data_transfer_3d_phys2phys, & + GFS_data_transfer_2d_int2phys, & + GFS_data_transfer_3d_int2phys, & + GFS_data_transfer_3d_slice_phys2phys, & + GFS_data_transfer_2d_stack_phys2phys + public :: create_2d_field_and_add_to_bundle public :: create_3d_field_and_add_to_bundle public :: add_zaxis_to_field @@ -21,6 +29,7 @@ module FV3GFS_common_io copy_from_GFS_Data_3d_phys2phys, & copy_from_GFS_Data_2d_int2phys, & copy_from_GFS_Data_3d_int2phys, & + copy_from_GFS_Data_3d_slice_phys2phys, & copy_from_GFS_Data_2d_stack_phys2phys end interface @@ -29,9 +38,19 @@ module FV3GFS_common_io copy_to_GFS_Data_3d_phys2phys, & copy_to_GFS_Data_2d_int2phys, & copy_to_GFS_Data_3d_int2phys, & - copy_to_GFS_Data_3d_slice_phys2phys + copy_to_GFS_Data_3d_slice_phys2phys, & + copy_to_GFS_Data_2d_stack_phys2phys end interface copy_to_GFS_Data + interface GFS_data_transfer + module procedure GFS_data_transfer_2d_phys2phys, & + GFS_data_transfer_3d_phys2phys, & + GFS_data_transfer_2d_int2phys, & + GFS_data_transfer_3d_int2phys, & + GFS_data_transfer_3d_slice_phys2phys, & + GFS_data_transfer_2d_stack_phys2phys + end interface GFS_data_transfer + public :: get_nx_ny_from_atm contains @@ -128,6 +147,22 @@ pure subroutine copy_from_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_bloc enddo end subroutine copy_from_GFS_Data_3d_int2phys + pure subroutine copy_from_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc, k1, k2 + integer, intent(inout) :: nt + real(kind=kind_phys), intent(in) :: var_block(:,:) + real(kind=kind_phys), intent(out) :: var3d(:,:,:,:) + integer ix, k + + nt=nt+1 + do k=k1,k2 + do ix=1,size(var_block,1) + var3d(ii1(ix),jj1(ix),k,nt) = var_block(ix,k) + enddo + enddo + end subroutine copy_from_GFS_Data_3d_slice_phys2phys + pure subroutine copy_to_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) implicit none integer, intent(in) :: ii1(:), jj1(:), isc, jsc @@ -158,6 +193,23 @@ pure subroutine copy_to_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block enddo end subroutine copy_to_GFS_Data_3d_phys2phys + pure subroutine copy_to_GFS_Data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + ! For copying phy_f2d and phy_fctd + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(out) :: var_block(:,:) + real(kind=kind_phys), intent(in) :: var3d(:,:,:) + integer ix, k + + nt=nt+1 + do k=lbound(var_block,2),ubound(var_block,2) + do ix=1,size(var_block,1) + var_block(ix,k) = var3d(ii1(ix),jj1(ix),nt) + enddo + enddo + end subroutine copy_to_GFS_Data_2d_stack_phys2phys + pure subroutine copy_to_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) implicit none integer, intent(in) :: ii1(:), jj1(:), isc, jsc, k1, k2 @@ -202,6 +254,98 @@ pure subroutine copy_to_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) enddo end subroutine copy_to_GFS_Data_3d_int2phys + pure subroutine GFS_data_transfer_2d_phys2phys(to,ii1,jj1,isc,jsc,nt,var2d,var_block) + implicit none + logical, intent(in) :: to + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(inout) :: var_block(:) + real(kind=kind_phys), intent(inout) :: var2d(:,:,:) + + if(to) then + call copy_to_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + else + call copy_from_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + end if + end subroutine GFS_data_transfer_2d_phys2phys + + pure subroutine GFS_data_transfer_3d_phys2phys(to,ii1,jj1,isc,jsc,nt,var3d,var_block) + implicit none + logical, intent(in) :: to + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(inout) :: var_block(:,:) + real(kind=kind_phys), intent(inout) :: var3d(:,:,:,:) + + if(to) then + call copy_to_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + else + call copy_from_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + endif + end subroutine GFS_data_transfer_3d_phys2phys + + pure subroutine GFS_data_transfer_3d_slice_phys2phys(to,ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) + implicit none + logical, intent(in) :: to + integer, intent(in) :: ii1(:), jj1(:), isc, jsc, k1, k2 + integer, intent(inout) :: nt + real(kind=kind_phys), intent(inout) :: var_block(:,:) + real(kind=kind_phys), intent(inout) :: var3d(:,:,:,:) + + if(to) then + call copy_to_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) + else + call copy_from_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) + endif + end subroutine GFS_data_transfer_3d_slice_phys2phys + + pure subroutine GFS_data_transfer_2d_int2phys(to,ii1,jj1,isc,jsc,nt,var2d,var_block) + implicit none + logical, intent(in) :: to + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + integer, intent(inout) :: var_block(:) + real(kind=kind_phys), intent(inout) :: var2d(:,:,:) + + if(to) then + call copy_to_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + else + call copy_from_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + endif + end subroutine GFS_data_transfer_2d_int2phys + + pure subroutine GFS_data_transfer_3d_int2phys(to,ii1,jj1,isc,jsc,nt,var3d,var_block) + implicit none + logical, intent(in) :: to + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + integer, intent(inout) :: var_block(:,:) + real(kind=kind_phys), intent(inout) :: var3d(:,:,:,:) + + if(to) then + call copy_to_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + else + call copy_from_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + endif + end subroutine GFS_data_transfer_3d_int2phys + + pure subroutine GFS_Data_transfer_2d_stack_phys2phys(to,ii1,jj1,isc,jsc,nt,var3d,var_block) + ! For copying phy_f2d and phy_fctd + implicit none + logical, intent(in) :: to + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(inout) :: var_block(:,:) + real(kind=kind_phys), intent(inout) :: var3d(:,:,:) + integer ix, k + + if(to) then + call copy_to_GFS_data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + else + call copy_from_GFS_data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + end if + end subroutine GFS_Data_transfer_2d_stack_phys2phys + subroutine create_2d_field_and_add_to_bundle(temp_r2d, field_name, outputfile, grid, bundle) use esmf diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index 84818b0e2..bb57bfb4a 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -885,9 +885,9 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta 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)) - if(sfc%allocate_arrays(Model, Atm_block, .false., warm_start)) then + if(sfc%allocate_arrays(Model, Atm_block, .true., warm_start)) then call sfc%fill_2d_names(Model, warm_start) - call sfc%register_axes(Model, Sfc_restart, .false., warm_start) + call sfc%register_axes(Model, Sfc_restart, .true., warm_start) ! Tell CLM Lake to allocate data, and register its axes and fields if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then @@ -904,11 +904,11 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta call rrfs_sd_state%register_fields(Sfc_restart) endif - call sfc%register_2d_fields(Model,Sfc_restart,.false.,warm_start) + call sfc%register_2d_fields(Model,Sfc_restart,.true.,warm_start) endif ! if not allocated call sfc%fill_3d_names(Model,warm_start) - call sfc%register_3d_fields(Model,Sfc_restart,.false.,warm_start) + call sfc%register_3d_fields(Model,Sfc_restart,.true.,warm_start) call sfc%init_fields(Model) !--- read the surface restart/data @@ -1002,7 +1002,7 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta !--- register axis amiopen=open_file(Sfc_restart, trim(infile), 'overwrite', domain=fv_domain, is_restart=.true., dont_add_res_to_filename=.true.) if_amiopen: if( amiopen ) then - call sfc%register_axes(Model, Sfc_restart, .true., .true.) + call sfc%register_axes(Model, Sfc_restart, .false., .true.) call sfc%write_axes(Model, Sfc_restart) else call mpp_error(FATAL, 'Error in opening file'//trim(infile) ) @@ -1021,7 +1021,7 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta call rrfs_sd_state%write_axis(Model,Sfc_restart) end if - if (sfc%allocate_arrays(Model, Atm_block, .true., .true.)) then + if (sfc%allocate_arrays(Model, Atm_block, .false., .true.)) then call sfc%fill_2d_names(Model,.true.) end if @@ -1035,13 +1035,13 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta endif ! Register 2D surface property fields (except lake, smoke, and dust) - call sfc%register_2d_fields(Model, Sfc_restart, .true., .true.) + call sfc%register_2d_fields(Model, Sfc_restart, .false., .true.) ! Determine list of 3D surface property fields names: call sfc%fill_3d_names(Model, .true.) ! Register 3D surface property fields (except lake, smoke, and dust) - call sfc%register_3d_fields(Model, Sfc_restart, .true., .true.) + call sfc%register_3d_fields(Model, Sfc_restart, .false., .true.) ! Tell clm_lake to copy Sfcprop data to its internal temporary arrays. if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then diff --git a/io/FV3GFS_sfc_io.F90 b/io/FV3GFS_sfc_io.F90 index 8be70aa6d..0d9c64032 100644 --- a/io/FV3GFS_sfc_io.F90 +++ b/io/FV3GFS_sfc_io.F90 @@ -6,7 +6,7 @@ module FV3GFS_sfc_io register_variable_attribute, register_field, & read_restart, write_restart, write_data, & get_global_io_domain_indices, variable_exists - use FV3GFS_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data + use FV3GFS_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data, GFS_Data_transfer use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys use GFS_restart, only: GFS_restart_type use mpp_mod, only: mpp_error, mpp_pe, mpp_root_pe, & @@ -20,7 +20,7 @@ module FV3GFS_sfc_io public :: Sfc_io_fill_2d_names, Sfc_io_fill_3d_names, Sfc_io_allocate_arrays, & Sfc_io_register_axes, Sfc_io_write_axes, Sfc_io_register_2d_fields, & Sfc_io_register_3d_fields, Sfc_io_copy_to_grid, Sfc_io_copy_from_grid, & - Sfc_io_apply_safeguards, Sfc_io_final + Sfc_io_apply_safeguards, Sfc_io_transfer, Sfc_io_final real(kind=kind_phys), parameter :: timin = 173.0_kind_phys ! minimum temperature allowed for snow/ice real(kind_phys), parameter:: min_lake_orog = 200.0_kind_phys @@ -69,6 +69,7 @@ module FV3GFS_sfc_io procedure, public :: fill_2d_names => Sfc_io_fill_2d_names procedure, public :: fill_3d_names => Sfc_io_fill_3d_names procedure, public :: init_fields => Sfc_io_init_fields + procedure, public :: transfer => Sfc_io_transfer procedure, public :: copy_to_grid => Sfc_io_copy_to_grid procedure, public :: copy_from_grid => Sfc_io_copy_from_grid procedure, public :: apply_safeguards => Sfc_io_apply_safeguards @@ -80,12 +81,12 @@ module FV3GFS_sfc_io contains - function Sfc_io_calculate_indices(sfc, Model, for_write, warm_start) + function Sfc_io_calculate_indices(sfc, Model, reading, warm_start) implicit none class(Sfc_io_data_type) :: sfc type(GFS_control_type), intent(in) :: Model logical :: Sfc_io_calculate_indices - logical, intent(in) :: for_write, warm_start + logical, intent(in) :: reading, warm_start integer :: nvar2m, nvar2o, nvar3, nvar2r, nvar2mp, nvar3mp, nvar2l integer :: nvar_before_lake @@ -111,7 +112,7 @@ function Sfc_io_calculate_indices(sfc, Model, for_write, warm_start) endif nvar3 = 5 else - if(for_write .and. Model%rdlai) then + if(.not.reading .and. Model%rdlai) then nvar2r = 1 else nvar2r = 0 @@ -157,13 +158,13 @@ function Sfc_io_calculate_indices(sfc, Model, for_write, warm_start) end function Sfc_io_calculate_indices - function Sfc_io_allocate_arrays(sfc, Model, Atm_block, for_write, warm_start) + function Sfc_io_allocate_arrays(sfc, Model, Atm_block, reading, warm_start) implicit none class(Sfc_io_data_type) :: sfc type(block_control_type), intent(in) :: Atm_block type(GFS_control_type), intent(in) :: Model logical :: Sfc_io_allocate_arrays - logical, intent(in) :: for_write, warm_start + logical, intent(in) :: reading, warm_start integer :: isc, iec, jsc, jec, npz, nx, ny @@ -175,7 +176,7 @@ function Sfc_io_allocate_arrays(sfc, Model, Atm_block, for_write, warm_start) nx = (iec - isc + 1) ny = (jec - jsc + 1) - Sfc_io_allocate_arrays = sfc%calculate_indices(Model, for_write, warm_start) + Sfc_io_allocate_arrays = sfc%calculate_indices(Model, reading, warm_start) Sfc_io_allocate_arrays = Sfc_io_allocate_arrays .or. .not. associated(sfc%name2) if(Sfc_io_allocate_arrays) then @@ -218,20 +219,20 @@ function Sfc_io_allocate_arrays(sfc, Model, Atm_block, for_write, warm_start) endif end function Sfc_io_allocate_arrays - subroutine Sfc_io_register_axes(sfc, Model, Sfc_restart, for_write, warm_start) + subroutine Sfc_io_register_axes(sfc, Model, Sfc_restart, reading, warm_start) implicit none class(Sfc_io_data_type) :: sfc type(GFS_control_type), intent(in) :: Model type(FmsNetcdfDomainFile_t) :: Sfc_restart - logical, intent(in) :: for_write, warm_start + logical, intent(in) :: reading, warm_start - if(.not.for_write) then + if(reading) then sfc%is_lsoil = .false. endif - if(.not.warm_start .and. .not.for_write) then + if(.not.warm_start .and. reading) then if( variable_exists(Sfc_restart,"lsoil") ) then - if(.not.for_write) then + if(reading) then sfc%is_lsoil=.true. endif call register_axis(Sfc_restart, 'lon', 'X') @@ -249,7 +250,7 @@ subroutine Sfc_io_register_axes(sfc, Model, Sfc_restart, for_write, warm_start) call register_axis(Sfc_restart, 'zaxis_1', dimension_length=Model%kice) if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp) then call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil) - else if(Model%lsm == Model%lsm_ruc .and. .not.for_write) then + else if(Model%lsm == Model%lsm_ruc .and. reading) then ! Possible bug. This is only defined on read, not write. call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil_lsm) endif @@ -517,12 +518,12 @@ subroutine Sfc_io_fill_2d_names(sfc,Model,warm_start) endif end subroutine Sfc_io_fill_2d_names - subroutine Sfc_io_register_2d_fields(sfc,Model,Sfc_restart,for_write,warm_start) + subroutine Sfc_io_register_2d_fields(sfc,Model,Sfc_restart,reading,warm_start) implicit none class(Sfc_io_data_type) :: sfc type(GFS_control_type), intent(in) :: Model type(FmsNetcdfDomainFile_t) :: Sfc_restart - logical, intent(in) :: for_write, warm_start + logical, intent(in) :: reading, warm_start real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() @@ -534,7 +535,7 @@ subroutine Sfc_io_register_2d_fields(sfc,Model,Sfc_restart,for_write,warm_start) character(len=7) :: time2d(3) - if(for_write) then + if(.not.reading) then time2d=(/'xaxis_1','yaxis_1','Time '/) else time2d=(/'Time ','yaxis_1','xaxis_1'/) @@ -554,14 +555,14 @@ subroutine Sfc_io_register_2d_fields(sfc,Model,Sfc_restart,for_write,warm_start) .or. trim(sfc%name2(num)) == 'albdifvis_ice' .or. trim(sfc%name2(num)) == 'albdifnir_ice' & .or. trim(sfc%name2(num)) == 'emis_lnd' .or. trim(sfc%name2(num)) == 'emis_ice' & .or. trim(sfc%name2(num)) == 'sncovr_ice') then - if(.not.for_write .and. sfc%is_lsoil) then + if(reading .and. sfc%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=time2d,& &is_optional=.true.) end if else - if(.not.for_write .and. sfc%is_lsoil) then + if(reading .and. sfc%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=time2d) @@ -594,9 +595,9 @@ subroutine Sfc_io_register_2d_fields(sfc,Model,Sfc_restart,for_write,warm_start) endif ! mp/ruc ! Noah MP register only necessary only lsm = 2, not necessary has values - if ( (for_write .and. Model%lsm == Model%lsm_noahmp) & - .or. (.not. for_write .and. sfc%nvar2mp > 0) ) then - mand = for_write + if ( (.not.reading .and. Model%lsm == Model%lsm_noahmp) & + .or. (reading .and. sfc%nvar2mp > 0) ) then + mand = .not.reading do num = sfc%nvar2m+sfc%nvar2o+1,sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp var2_p => sfc%var2(:,:,num) if(sfc%is_lsoil) then @@ -609,7 +610,7 @@ subroutine Sfc_io_register_2d_fields(sfc,Model,Sfc_restart,for_write,warm_start) ! Flake if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then - mand = for_write + mand = .not.reading do num = sfc%nvar_before_lake+1,sfc%nvar_before_lake+sfc%nvar2l var2_p => sfc%var2(:,:,num) if(sfc%is_lsoil) then @@ -622,12 +623,12 @@ subroutine Sfc_io_register_2d_fields(sfc,Model,Sfc_restart,for_write,warm_start) end subroutine Sfc_io_register_2d_fields - subroutine Sfc_io_register_3d_fields(sfc,Model,Sfc_restart,for_write,warm_start) + subroutine Sfc_io_register_3d_fields(sfc,Model,Sfc_restart,reading,warm_start) implicit none class(Sfc_io_data_type) :: sfc type(GFS_control_type), intent(in) :: Model type(FmsNetcdfDomainFile_t) :: Sfc_restart - logical, intent(in) :: for_write, warm_start + logical, intent(in) :: reading, warm_start real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p1 => NULL() @@ -646,7 +647,7 @@ subroutine Sfc_io_register_3d_fields(sfc,Model,Sfc_restart,for_write,warm_start) var3_p => sfc%var3ice(:,:,:) call register_restart_field(Sfc_restart, sfc%name3(0), var3_p, dimensions=xyz1_time, is_optional=.true.) - if(.not. for_write) then + if(reading) then do num = 1,sfc%nvar3 var3_p => sfc%var3(:,:,:,num) if ( warm_start ) then @@ -676,7 +677,7 @@ subroutine Sfc_io_register_3d_fields(sfc,Model,Sfc_restart,for_write,warm_start) endif if (Model%lsm == Model%lsm_noahmp) then - mand = for_write + mand = .not.reading do num = sfc%nvar3+1,sfc%nvar3+3 var3_p1 => sfc%var3sn(:,:,:,num) call register_restart_field(Sfc_restart, sfc%name3(num), var3_p1, dimensions=xyz3_time, is_optional=.not.mand) @@ -704,12 +705,13 @@ subroutine Sfc_io_init_fields(sfc,Model) endif end subroutine Sfc_io_init_fields - subroutine Sfc_io_copy_to_grid(sfc, Model, Atm_block, Sfcprop, warm_start, override_frac_grid) + subroutine Sfc_io_transfer(sfc, reading, Model, Atm_block, Sfcprop, warm_start, override_frac_grid) !--- interface variable definitions implicit none - class(Sfc_io_data_type) :: sfc - type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) + class(Sfc_io_data_type) :: sfc + logical, intent(in) :: reading + type(GFS_sfcprop_type) :: Sfcprop(:) type(block_control_type), intent(in) :: Atm_block type(GFS_control_type), intent(in) :: Model logical, intent(in) :: warm_start @@ -720,6 +722,10 @@ subroutine Sfc_io_copy_to_grid(sfc, Model, Atm_block, Sfcprop, warm_start, overr integer, allocatable :: ii1(:), jj1(:) real(kind_phys) :: ice + ! "To" variable: + ! to=.TRUE. means transfer sfc data TO Sfcprop grid + ! to=.FALSE. means transfer into sfc data FROM Sfcprop grid + isc = Atm_block%isc iec = Atm_block%iec jsc = Atm_block%jsc @@ -743,66 +749,66 @@ subroutine Sfc_io_copy_to_grid(sfc, Model, Atm_block, Sfcprop, warm_start, overr !--- 2D variables ! ------------ - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slmsk) !--- slmsk - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tg3) !--- tg3 - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorl) !--- zorl composite - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvsf) !--- alvsf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvwf) !--- alvwf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnsf) !--- alnsf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnwf) !--- alnwf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facsf) !--- facsf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facwf) !--- facwf - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vfrac) !--- vfrac - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canopy) !--- canopy - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%f10m) !--- f10m - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t2m) !--- t2m - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%q2m) !--- q2m - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vtype) !--- vtype - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stype) !--- stype - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%uustar) !--- uustar - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffmm) !--- ffmm - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffhh) !--- ffhh - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%hice) !--- hice - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fice) !--- fice - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tisfc) !--- tisfc - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tprcp) !--- tprcp - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%srflag) !--- srflag - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmin) !--- shdmin - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmax) !--- shdmax - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slope) !--- slope - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snoalb) !--- snoalb - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr) !--- sncovr - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfc) !--- tsfc composite - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlw) !--- zorlw (zorl on water portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice portion of a cell) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice portion of a cell) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slmsk) !--- slmsk + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tg3) !--- tg3 + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorl) !--- zorl composite + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvsf) !--- alvsf + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvwf) !--- alvwf + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnsf) !--- alnsf + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnwf) !--- alnwf + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facsf) !--- facsf + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facwf) !--- facwf + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vfrac) !--- vfrac + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canopy) !--- canopy + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%f10m) !--- f10m + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t2m) !--- t2m + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%q2m) !--- q2m + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vtype) !--- vtype + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stype) !--- stype + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%uustar) !--- uustar + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffmm) !--- ffmm + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffhh) !--- ffhh + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%hice) !--- hice + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fice) !--- fice + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tisfc) !--- tisfc + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tprcp) !--- tprcp + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%srflag) !--- srflag + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmin) !--- shdmin + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmax) !--- shdmax + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slope) !--- slope + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snoalb) !--- snoalb + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr) !--- sncovr + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land portion of a cell) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land portion of a cell) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfc) !--- tsfc composite + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land portion of a cell) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlw) !--- zorlw (zorl on water portion of a cell) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land portion of a cell) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice portion of a cell) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_lnd) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_lnd) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_lnd) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_lnd) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_lnd) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_ice) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr_ice) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice portion of a cell) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice portion of a cell) if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_ice) - ! call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_ice) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_ice) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_ice) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_ice) + ! call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) endif if(Model%cplwav) then !tgs - the following line is a bug. It should be nt = nt !nt = sfc%nvar2m-1 ! Next item will be at sfc%nvar2m - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlwav) !--- (zorl from wave model) - else + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlwav) !--- (zorl from wave model) + else if(reading) then Sfcprop(nb)%zorlwav = Sfcprop(nb)%zorlw endif @@ -810,108 +816,110 @@ subroutine Sfc_io_copy_to_grid(sfc, Model, Atm_block, Sfcprop, warm_start, overr override_frac_grid=Model%frac_grid endif - do_lsi_fractions: do ix = 1, Atm_block%blksz(nb) - if (Sfcprop(nb)%stype(ix) == 14 .or. Sfcprop(nb)%stype(ix) <= 0) then - Sfcprop(nb)%landfrac(ix) = zero - Sfcprop(nb)%stype(ix) = 0 - if (Sfcprop(nb)%lakefrac(ix) > zero) then - Sfcprop(nb)%lakefrac(ix) = one + if(reading) then + do_lsi_fractions: do ix = 1, Atm_block%blksz(nb) + if (Sfcprop(nb)%stype(ix) == 14 .or. Sfcprop(nb)%stype(ix) <= 0) then + Sfcprop(nb)%landfrac(ix) = zero + Sfcprop(nb)%stype(ix) = 0 + if (Sfcprop(nb)%lakefrac(ix) > zero) then + Sfcprop(nb)%lakefrac(ix) = one + endif endif - endif - if_frac_grid: if (Model%frac_grid) then - if (Sfcprop(nb)%landfrac(ix) > -999.0_kind_phys) then - Sfcprop(nb)%slmsk(ix) = ceiling(Sfcprop(nb)%landfrac(ix)-1.0e-6) - if (Sfcprop(nb)%slmsk(ix) == 1 .and. Sfcprop(nb)%stype(ix) == 14) & - Sfcprop(nb)%slmsk(ix) = 0 - if (Sfcprop(nb)%lakefrac(ix) > zero) then - Sfcprop(nb)%oceanfrac(ix) = zero ! lake & ocean don't coexist in a cell - if (nint(Sfcprop(nb)%slmsk(ix)) /= 1) then - if(Sfcprop(nb)%fice(ix) >= Model%min_lakeice) then - Sfcprop(nb)%slmsk(ix) = 2 - else - Sfcprop(nb)%slmsk(ix) = 0 + if_frac_grid: if (Model%frac_grid) then + if (Sfcprop(nb)%landfrac(ix) > -999.0_kind_phys) then + Sfcprop(nb)%slmsk(ix) = ceiling(Sfcprop(nb)%landfrac(ix)-1.0e-6) + if (Sfcprop(nb)%slmsk(ix) == 1 .and. Sfcprop(nb)%stype(ix) == 14) & + Sfcprop(nb)%slmsk(ix) = 0 + if (Sfcprop(nb)%lakefrac(ix) > zero) then + Sfcprop(nb)%oceanfrac(ix) = zero ! lake & ocean don't coexist in a cell + if (nint(Sfcprop(nb)%slmsk(ix)) /= 1) then + if(Sfcprop(nb)%fice(ix) >= Model%min_lakeice) then + Sfcprop(nb)%slmsk(ix) = 2 + else + Sfcprop(nb)%slmsk(ix) = 0 + endif + endif + else + Sfcprop(nb)%lakefrac(ix) = zero + Sfcprop(nb)%oceanfrac(ix) = one - Sfcprop(nb)%landfrac(ix) + if (nint(Sfcprop(nb)%slmsk(ix)) /= 1) then + if (Sfcprop(nb)%fice(ix) >= Model%min_seaice) then + Sfcprop(nb)%slmsk(ix) = 2 + else + Sfcprop(nb)%slmsk(ix) = 0 + endif endif endif else - Sfcprop(nb)%lakefrac(ix) = zero - Sfcprop(nb)%oceanfrac(ix) = one - Sfcprop(nb)%landfrac(ix) - if (nint(Sfcprop(nb)%slmsk(ix)) /= 1) then - if (Sfcprop(nb)%fice(ix) >= Model%min_seaice) then - Sfcprop(nb)%slmsk(ix) = 2 - else - Sfcprop(nb)%slmsk(ix) = 0 + if(present(override_frac_grid)) then + override_frac_grid = .false. + endif + if (nint(Sfcprop(nb)%slmsk(ix)) == 1) then + Sfcprop(nb)%landfrac(ix) = one + Sfcprop(nb)%lakefrac(ix) = zero + Sfcprop(nb)%oceanfrac(ix) = zero + else + if (Sfcprop(nb)%slmsk(ix) < 0.1_kind_phys .or. Sfcprop(nb)%slmsk(ix) > 1.9_kind_phys) then + Sfcprop(nb)%landfrac(ix) = zero + if (Sfcprop(nb)%oro_uf(ix) > min_lake_orog) then ! lakes + Sfcprop(nb)%lakefrac(ix) = one + Sfcprop(nb)%oceanfrac(ix) = zero + else ! ocean + Sfcprop(nb)%lakefrac(ix) = zero + Sfcprop(nb)%oceanfrac(ix) = one + endif endif endif endif - else - if(present(override_frac_grid)) then - override_frac_grid = .false. - endif - if (nint(Sfcprop(nb)%slmsk(ix)) == 1) then - Sfcprop(nb)%landfrac(ix) = one - Sfcprop(nb)%lakefrac(ix) = zero - Sfcprop(nb)%oceanfrac(ix) = zero - else - if (Sfcprop(nb)%slmsk(ix) < 0.1_kind_phys .or. Sfcprop(nb)%slmsk(ix) > 1.9_kind_phys) then - Sfcprop(nb)%landfrac(ix) = zero - if (Sfcprop(nb)%oro_uf(ix) > min_lake_orog) then ! lakes - Sfcprop(nb)%lakefrac(ix) = one - Sfcprop(nb)%oceanfrac(ix) = zero - else ! ocean - Sfcprop(nb)%lakefrac(ix) = zero + else ! not a fractional grid + if (Sfcprop(nb)%landfrac(ix) > -999.0_kind_phys) then + if (Sfcprop(nb)%lakefrac(ix) > zero) then + Sfcprop(nb)%oceanfrac(ix) = zero + Sfcprop(nb)%landfrac(ix) = zero + Sfcprop(nb)%lakefrac(ix) = one + Sfcprop(nb)%slmsk(ix) = zero + if (Sfcprop(nb)%fice(ix) >= Model%min_lakeice) Sfcprop(nb)%slmsk(ix) = 2.0 + else + Sfcprop(nb)%slmsk(ix) = nint(Sfcprop(nb)%landfrac(ix)) + if (Sfcprop(nb)%stype(ix) <= 0 .or. Sfcprop(nb)%stype(ix) == 14) & + Sfcprop(nb)%slmsk(ix) = zero + if (nint(Sfcprop(nb)%slmsk(ix)) == 0) then Sfcprop(nb)%oceanfrac(ix) = one + Sfcprop(nb)%landfrac(ix) = zero + Sfcprop(nb)%lakefrac(ix) = zero + if (Sfcprop(nb)%fice(ix) >= Model%min_seaice) Sfcprop(nb)%slmsk(ix) = 2.0 + else + Sfcprop(nb)%landfrac(ix) = one + Sfcprop(nb)%lakefrac(ix) = zero + Sfcprop(nb)%oceanfrac(ix) = zero endif endif - endif - endif - else ! not a fractional grid - if (Sfcprop(nb)%landfrac(ix) > -999.0_kind_phys) then - if (Sfcprop(nb)%lakefrac(ix) > zero) then - Sfcprop(nb)%oceanfrac(ix) = zero - Sfcprop(nb)%landfrac(ix) = zero - Sfcprop(nb)%lakefrac(ix) = one - Sfcprop(nb)%slmsk(ix) = zero - if (Sfcprop(nb)%fice(ix) >= Model%min_lakeice) Sfcprop(nb)%slmsk(ix) = 2.0 else - Sfcprop(nb)%slmsk(ix) = nint(Sfcprop(nb)%landfrac(ix)) - if (Sfcprop(nb)%stype(ix) <= 0 .or. Sfcprop(nb)%stype(ix) == 14) & - Sfcprop(nb)%slmsk(ix) = zero - if (nint(Sfcprop(nb)%slmsk(ix)) == 0) then - Sfcprop(nb)%oceanfrac(ix) = one - Sfcprop(nb)%landfrac(ix) = zero - Sfcprop(nb)%lakefrac(ix) = zero - if (Sfcprop(nb)%fice(ix) >= Model%min_seaice) Sfcprop(nb)%slmsk(ix) = 2.0 - else + if (nint(Sfcprop(nb)%slmsk(ix)) == 1 .and. Sfcprop(nb)%stype(ix) > 0 & + .and. Sfcprop(nb)%stype(ix) /= 14) then Sfcprop(nb)%landfrac(ix) = one Sfcprop(nb)%lakefrac(ix) = zero Sfcprop(nb)%oceanfrac(ix) = zero + else + Sfcprop(nb)%slmsk(ix) = zero + Sfcprop(nb)%landfrac(ix) = zero + if (Sfcprop(nb)%oro_uf(ix) > min_lake_orog) then ! lakes + Sfcprop(nb)%lakefrac(ix) = one + Sfcprop(nb)%oceanfrac(ix) = zero + if (Sfcprop(nb)%fice(ix) > Model%min_lakeice) Sfcprop(nb)%slmsk(ix) = 2.0 + else ! ocean + Sfcprop(nb)%lakefrac(ix) = zero + Sfcprop(nb)%oceanfrac(ix) = one + if (Sfcprop(nb)%fice(ix) > Model%min_seaice) Sfcprop(nb)%slmsk(ix) = 2.0 + endif endif endif - else - if (nint(Sfcprop(nb)%slmsk(ix)) == 1 .and. Sfcprop(nb)%stype(ix) > 0 & - .and. Sfcprop(nb)%stype(ix) /= 14) then - Sfcprop(nb)%landfrac(ix) = one - Sfcprop(nb)%lakefrac(ix) = zero - Sfcprop(nb)%oceanfrac(ix) = zero - else - Sfcprop(nb)%slmsk(ix) = zero - Sfcprop(nb)%landfrac(ix) = zero - if (Sfcprop(nb)%oro_uf(ix) > min_lake_orog) then ! lakes - Sfcprop(nb)%lakefrac(ix) = one - Sfcprop(nb)%oceanfrac(ix) = zero - if (Sfcprop(nb)%fice(ix) > Model%min_lakeice) Sfcprop(nb)%slmsk(ix) = 2.0 - else ! ocean - Sfcprop(nb)%lakefrac(ix) = zero - Sfcprop(nb)%oceanfrac(ix) = one - if (Sfcprop(nb)%fice(ix) > Model%min_seaice) Sfcprop(nb)%slmsk(ix) = 2.0 - endif - endif - endif - endif if_frac_grid - enddo do_lsi_fractions + endif if_frac_grid + enddo do_lsi_fractions + endif - if (warm_start .and. Model%kdt > 1) then + if (reading .and. warm_start .and. Model%kdt > 1) then do ix = 1, Atm_block%blksz(nb) Sfcprop(nb)%slmsk(ix) = sfc%var2(ii1(ix),jj1(ix),1) !--- slmsk enddo @@ -922,7 +930,7 @@ subroutine Sfc_io_copy_to_grid(sfc, Model, Atm_block, Sfcprop, warm_start, overr !tgs - the following line is a bug that will show if(Model%cplwav) = true !nt = sfc%nvar2m if (Model%nstf_name(1) > 0) then - if (Model%nstf_name(2) == 1) then ! nsst spinup + if (reading .and. Model%nstf_name(2) == 1) then ! nsst spinup !--- nsstm tref nt = nt + 18 Sfcprop(nb)%tref = Sfcprop(nb)%tsfco @@ -943,356 +951,157 @@ subroutine Sfc_io_copy_to_grid(sfc, Model, Atm_block, Sfcprop, warm_start, overr Sfcprop(nb)%ifd = zero Sfcprop(nb)%dt_cool = zero Sfcprop(nb)%qrain = zero - elseif (Model%nstf_name(2) == 0) then ! nsst restart - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tref) !--- nsstm tref - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%z_c) !--- nsstm z_c - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_0) !--- nsstm c_0 - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_d) !--- nsstm c_d - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_0) !--- nsstm w_0 - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_d) !--- nsstm w_d - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xt) !--- nsstm xt - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xs) !--- nsstm xs - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xu) !--- nsstm xu - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xv) !--- nsstm xv - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xz) !--- nsstm xz - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zm) !--- nsstm zm - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xtts) !--- nsstm xtts - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xzts) !--- nsstm xzts - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ifd) !--- nsstm ifd - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%dt_cool) !--- nsstm dt_cool - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qrain) !--- nsstm qrain + elseif (.not.reading .or. Model%nstf_name(2) == 0) then ! nsst restart + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tref) !--- nsstm tref + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%z_c) !--- nsstm z_c + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_0) !--- nsstm c_0 + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_d) !--- nsstm c_d + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_0) !--- nsstm w_0 + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_d) !--- nsstm w_d + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xt) !--- nsstm xt + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xs) !--- nsstm xs + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xu) !--- nsstm xu + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xv) !--- nsstm xv + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xz) !--- nsstm xz + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zm) !--- nsstm zm + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xtts) !--- nsstm xtts + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xzts) !--- nsstm xzts + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ifd) !--- nsstm ifd + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%dt_cool) !--- nsstm dt_cool + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qrain) !--- nsstm qrain endif endif - if (Model%lsm == Model%lsm_ruc .and. warm_start) then + if (Model%lsm == Model%lsm_ruc .and. (warm_start .or. .not. reading)) then !--- Extra RUC variables - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wetness) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_land) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_land) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_land) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_land) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd_bck) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wetness) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_land) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_ice) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_land) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_ice) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_land) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_ice) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_land) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_ice) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd_bck) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) if (Model%rdlai) then - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) endif - else if (Model%lsm == Model%lsm_ruc) then + else if (reading .and. Model%lsm == Model%lsm_ruc) then ! Initialize RUC snow cover on ice from snow cover Sfcprop(nb)%sncovr_ice = Sfcprop(nb)%sncovr if (Model%rdlai) then - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) end if elseif (Model%lsm == Model%lsm_noahmp) then !--- Extra Noah MP variables - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tvxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tgxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canicexy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canliqxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%eahxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tahxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%cmxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%chxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fwetxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sneqvoxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alboldxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qsnowxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wslakexy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zwtxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%waxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wtxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%lfmassxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rtmassxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stmassxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%woodxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stblcpxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fastcpxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xsaixy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%taussxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%smcwtdxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%deeprechxy) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rechxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tvxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tgxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canicexy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canliqxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%eahxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tahxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%cmxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%chxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fwetxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sneqvoxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alboldxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qsnowxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wslakexy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zwtxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%waxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wtxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%lfmassxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rtmassxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stmassxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%woodxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stblcpxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fastcpxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xsaixy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%taussxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%smcwtdxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%deeprechxy) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rechxy) endif if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_snow) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_ice) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_ML) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_ML) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_mnw) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_talb) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_talb) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot1) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot2) - call copy_to_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_t) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_snow) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_ice) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_ML) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_ML) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_mnw) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_talb) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_talb) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot1) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot2) + call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_t) endif - if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp .or. (.not.warm_start)) then + if(.not.reading) then + do k = 1,Model%kice + do ix = 1, Atm_block%blksz(nb) + ice=Sfcprop(nb)%tiice(ix,k) + if(ice 0) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tref) !--- nsstm tref - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%z_c) !--- nsstm z_c - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_0) !--- nsstm c_0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_d) !--- nsstm c_d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_0) !--- nsstm w_0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_d) !--- nsstm w_d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xt) !--- nsstm xt - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xs) !--- nsstm xs - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xu) !--- nsstm xu - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xv) !--- nsstm xv - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xz) !--- nsstm xz - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zm) !--- nsstm zm - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xtts) !--- nsstm xtts - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xzts) !--- nsstm xzts - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ifd) !--- nsstm ifd - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%dt_cool)!--- nsstm dt_cool - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qrain) !--- nsstm qrain - endif - - if (Model%lsm == Model%lsm_ruc) then - !--- Extra RUC variables - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wetness) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd_bck) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) - if (Model%rdlai) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) - endif - else if (Model%lsm == Model%lsm_noahmp) then - !--- Extra Noah MP variables - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tvxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tgxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canicexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canliqxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%eahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%cmxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%chxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fwetxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sneqvoxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alboldxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qsnowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wslakexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zwtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%waxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%lfmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rtmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%woodxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stblcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fastcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xsaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%taussxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%smcwtdxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%deeprechxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rechxy) - endif -! Flake - if(Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_snow) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%T_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_ML) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_ML) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_mnw) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%h_talb) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_talb) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot1) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t_bot2) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_t) - endif - do k = 1,Model%kice - do ix = 1, Atm_block%blksz(nb) - ice=Sfcprop(nb)%tiice(ix,k) - if(ice Date: Wed, 17 May 2023 21:37:31 +0000 Subject: [PATCH 13/27] move oro reading to FV3GFS_oro_io.F90 --- CMakeLists.txt | 1 + io/FV3GFS_io.F90 | 134 ++------------------------- io/FV3GFS_oro_io.F90 | 214 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+), 126 deletions(-) create mode 100644 io/FV3GFS_oro_io.F90 diff --git a/CMakeLists.txt b/CMakeLists.txt index bbbe9fe19..dd6d56202 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,6 +89,7 @@ add_library(fv3atm io/FV3GFS_clm_lake_io.F90 io/FV3GFS_rrfs_sd_io.F90 io/FV3GFS_sfc_io.F90 + io/FV3GFS_oro_io.F90 io/FV3GFS_io.F90 io/FV3GFS_restart_io.F90 io/module_write_netcdf.F90 diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index bb57bfb4a..8d821f86b 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -43,6 +43,7 @@ module FV3GFS_io_mod use FV3GFS_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data use FV3GFS_sfc_io + use FV3GFS_oro_io ! !----------------------------------------------------------------------- @@ -72,11 +73,11 @@ module FV3GFS_io_mod type(FmsNetcdfDomainFile_t) :: Oro_ls_restart, Oro_ss_restart !--- GFDL FMS restart containers - character(len=32), allocatable, dimension(:) :: oro_name2 - real(kind=kind_phys), allocatable, target, dimension(:,:,:) :: oro_var2, phy_var2 - character(len=32), allocatable, dimension(:) :: oro_ls_ss_name - real(kind=kind_phys), allocatable, target, dimension(:,:,:) :: oro_ls_var, oro_ss_var, oro_var3v, oro_var3s real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: phy_var3 + character(len=32), allocatable, dimension(:) :: oro_ls_ss_name + real(kind=kind_phys), allocatable, target, dimension(:,:,:) :: oro_ls_var, oro_ss_var + real(kind=kind_phys), allocatable, target, dimension(:,:,:) :: phy_var2 + !--- Noah MP restart containers real(kind=kind_phys) :: zhour ! @@ -103,6 +104,7 @@ module FV3GFS_io_mod real, parameter:: drythresh = 1.e-4_r8, zero = 0.0_r8, one = 1.0_r8 type(Sfc_io_data_type) :: sfc + type(Oro_io_data_type) :: oro !--- miscellaneous other variables logical :: use_wrtgridcomp_output = .FALSE. @@ -573,7 +575,6 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta type(rrfs_sd_state_type) :: rrfs_sd_state type(rrfs_sd_emissions_type) :: rrfs_sd_emis - nvar_o2 = 19 nvar_oro_ls_ss = 10 nvar_vegfr = Model%nvegcat @@ -594,134 +595,15 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta 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)) - allocate(oro_var2(nx,ny,nvar_o2)) - - allocate(oro_var3v(nx,ny,nvar_vegfr)) - allocate(oro_var3s(nx,ny,nvar_soilfr)) - - oro_var2 = -9999._kind_phys - - num = 1 ; oro_name2(num) = 'stddev' ! hprime(ix,1) - num = num + 1 ; oro_name2(num) = 'convexity' ! hprime(ix,2) - num = num + 1 ; oro_name2(num) = 'oa1' ! hprime(ix,3) - num = num + 1 ; oro_name2(num) = 'oa2' ! hprime(ix,4) - num = num + 1 ; oro_name2(num) = 'oa3' ! hprime(ix,5) - num = num + 1 ; oro_name2(num) = 'oa4' ! hprime(ix,6) - num = num + 1 ; oro_name2(num) = 'ol1' ! hprime(ix,7) - num = num + 1 ; oro_name2(num) = 'ol2' ! hprime(ix,8) - num = num + 1 ; oro_name2(num) = 'ol3' ! hprime(ix,9) - num = num + 1 ; oro_name2(num) = 'ol4' ! hprime(ix,10) - num = num + 1 ; oro_name2(num) = 'theta' ! hprime(ix,11) - num = num + 1 ; oro_name2(num) = 'gamma' ! hprime(ix,12) - num = num + 1 ; oro_name2(num) = 'sigma' ! hprime(ix,13) - num = num + 1 ; oro_name2(num) = 'elvmax' ! hprime(ix,14) - num = num + 1 ; oro_name2(num) = 'orog_filt' ! oro - num = num + 1 ; oro_name2(num) = 'orog_raw' ! oro_uf - num = num + 1 ; oro_name2(num) = 'land_frac' ! land fraction [0:1] - !--- variables below here are optional - num = num + 1 ; oro_name2(num) = 'lake_frac' ! lake fraction [0:1] - num = num + 1 ; oro_name2(num) = '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 n = 1,num - var2_p => oro_var2(:,:,n) - if (trim(oro_name2(n)) == 'lake_frac' .or. trim(oro_name2(n)) == 'lake_depth' ) then - call register_restart_field(Oro_restart, oro_name2(n), var2_p, dimensions=(/'lat','lon'/), is_optional=.true.) - else - call register_restart_field(Oro_restart, oro_name2(n), var2_p, dimensions=(/'lat','lon'/)) - endif - enddo - nullify(var2_p) - - !--- register 3D vegetation and soil fractions - var3_fr => oro_var3v(:,:,:) - call register_restart_field(Oro_restart, 'vegetation_type_pct', var3_fr, dimensions=(/'num_veg_cat','lat ','lon '/) , is_optional=.true.) - var3_fr => oro_var3s(:,:,:) - call register_restart_field(Oro_restart, 'soil_type_pct', var3_fr, dimensions=(/'num_soil_cat','lat ','lon '/) , is_optional=.true.) - nullify(var3_fr) - - endif + call oro%register(Model,Oro_restart,Atm_block) !--- read the orography restart/data call mpp_error(NOTE,'reading topographic/orographic information from INPUT/oro_data.tile*.nc') call read_restart(Oro_restart, ignore_checksum=ignore_rst_cksum) call close_file(Oro_restart) - !--- copy data into GFS containers - -!$omp parallel do default(shared) private(i, j, nb, ix, num) - do nb = 1, Atm_block%nblks - !--- 2D variables - 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 - !--- stddev -! Sfcprop(nb)%hprim(ix) = oro_var2(i,j,1) - !--- hprime(1:14) - num = 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro_var2(i,j,num) - !--- oro - num = num + 1 ; Sfcprop(nb)%oro(ix) = oro_var2(i,j,num) - num = num + 1 ; Sfcprop(nb)%oro_uf(ix) = oro_var2(i,j,num) - - Sfcprop(nb)%landfrac(ix) = -9999.0 - Sfcprop(nb)%lakefrac(ix) = -9999.0 - - num = num + 1 ; Sfcprop(nb)%landfrac(ix) = oro_var2(i,j,num) !land frac [0:1] - if (Model%lkm > 0 ) then - if(oro_var2(i,j,num+1)>Model%lakefrac_threshold .and. & - oro_var2(i,j,num+2)>Model%lakedepth_threshold) then - Sfcprop(nb)%lakefrac(ix) = oro_var2(i,j,num+1) !lake frac [0:1] - Sfcprop(nb)%lakedepth(ix) = oro_var2(i,j,num+2) !lake depth [m] !YWu - else - Sfcprop(nb)%lakefrac(ix) = 0 - Sfcprop(nb)%lakedepth(ix) = -9999 - endif - else - Sfcprop(nb)%lakefrac(ix) = oro_var2(i,j,num+1) !lake frac [0:1] - Sfcprop(nb)%lakedepth(ix) = oro_var2(i,j,num+2) !lake depth [m] !YWu - endif - num = num + 2 ! To account for lakefrac and lakedepth - - Sfcprop(nb)%vegtype_frac(ix,:) = -9999.0 - Sfcprop(nb)%soiltype_frac(ix,:) = -9999.0 - - Sfcprop(nb)%vegtype_frac(ix,:) = oro_var3v(i,j,:) ! vegetation type fractions, [0:1] - Sfcprop(nb)%soiltype_frac(ix,:) = oro_var3s(i,j,:) ! soil type fractions, [0:1] - - !do n=1,nvar_vegfr - ! if (Sfcprop(nb)%vegtype_frac(ix,n) > 0.) print *,'Sfcprop(nb)%vegtype_frac(ix,n)',Sfcprop(nb)%vegtype_frac(ix,n),n - !enddo - !do n=1,nvar_soilfr - ! if (Sfcprop(nb)%soiltype_frac(ix,n) > 0.) print *,'Sfcprop(nb)%soiltype_frac(ix,n)',Sfcprop(nb)%soiltype_frac(ix,n),n - !enddo - - enddo - enddo - - !--- deallocate containers and free restart container - deallocate(oro_name2, oro_var2) - deallocate(oro_var3v) - deallocate(oro_var3s) + call oro%copy(Model, Sfcprop, Atm_block) if_smoke: if(Model%rrfs_sd) then ! for RRFS-SD diff --git a/io/FV3GFS_oro_io.F90 b/io/FV3GFS_oro_io.F90 new file mode 100644 index 000000000..f30f45c79 --- /dev/null +++ b/io/FV3GFS_oro_io.F90 @@ -0,0 +1,214 @@ +module FV3GFS_oro_io + + use block_control_mod, only: block_control_type + use fms2_io_mod, only: FmsNetcdfDomainFile_t, unlimited, & + register_axis, register_restart_field, & + register_variable_attribute, register_field, & + read_restart, write_restart, write_data, & + get_global_io_domain_indices, variable_exists + use FV3GFS_common_io, only: get_nx_ny_from_atm + use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys + use GFS_restart, only: GFS_restart_type + use mpp_mod, only: mpp_error, mpp_pe, mpp_root_pe, & + mpp_chksum, NOTE, FATAL + use physcons, only: con_tice !saltwater freezing temp (K) + + implicit none + private + + public :: Oro_io_data_type, Oro_io_register, Oro_io_copy, Oro_io_final + + type Oro_io_data_type + character(len=32), pointer, private, dimension(:) :: name2 => null() + real(kind=kind_phys), pointer, private, dimension(:,:,:) :: var2 => null() + real(kind=kind_phys), pointer, private, dimension(:,:,:) :: var3v => null() + real(kind=kind_phys), pointer, private, dimension(:,:,:) :: var3s => null() + contains + procedure, public :: register => Oro_io_register + procedure, public :: copy => Oro_io_copy + final :: Oro_io_final + end type Oro_io_data_type + +contains + + subroutine Oro_io_register(oro, Model, Oro_restart, Atm_block) + implicit none + class(Oro_io_data_type) :: oro + type(GFS_control_type), intent(in) :: Model + type(FmsNetcdfDomainFile_t) :: Oro_restart + type(block_control_type), intent(in) :: Atm_block + + real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() + real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_fr => NULL() + integer :: nx, ny + + integer :: nvar_o2, nvar_vegfr, nvar_soilfr, n, num + + ! This #define reduces code length by a lot +#define WARN_DISASSOCIATE(name) \ + if(associated(name)) then ; \ + write(0,*) 'Internal error. Called oro%copy twice. Will try to keep going anyway.' ; \ + deallocate(name); \ + nullify(name) ; \ + endif + + call get_nx_ny_from_atm(Atm_block, nx, ny) + + WARN_DISASSOCIATE(oro%name2) + WARN_DISASSOCIATE(oro%var2) + WARN_DISASSOCIATE(oro%var3v) + WARN_DISASSOCIATE(oro%var3s) +#undef WARN_DISASSOCIATE + + nvar_o2 = 19 + nvar_vegfr = Model%nvegcat + nvar_soilfr = Model%nsoilcat + + allocate(oro%name2(nvar_o2)) + allocate(oro%var2(nx,ny,nvar_o2)) + + allocate(oro%var3v(nx,ny,nvar_vegfr)) + allocate(oro%var3s(nx,ny,nvar_soilfr)) + + oro%var2 = -9999._kind_phys + + num = 1 ; oro%name2(num) = 'stddev' ! hprime(ix,1) + num = num + 1 ; oro%name2(num) = 'convexity' ! hprime(ix,2) + num = num + 1 ; oro%name2(num) = 'oa1' ! hprime(ix,3) + num = num + 1 ; oro%name2(num) = 'oa2' ! hprime(ix,4) + num = num + 1 ; oro%name2(num) = 'oa3' ! hprime(ix,5) + num = num + 1 ; oro%name2(num) = 'oa4' ! hprime(ix,6) + num = num + 1 ; oro%name2(num) = 'ol1' ! hprime(ix,7) + num = num + 1 ; oro%name2(num) = 'ol2' ! hprime(ix,8) + num = num + 1 ; oro%name2(num) = 'ol3' ! hprime(ix,9) + num = num + 1 ; oro%name2(num) = 'ol4' ! hprime(ix,10) + num = num + 1 ; oro%name2(num) = 'theta' ! hprime(ix,11) + num = num + 1 ; oro%name2(num) = 'gamma' ! hprime(ix,12) + num = num + 1 ; oro%name2(num) = 'sigma' ! hprime(ix,13) + num = num + 1 ; oro%name2(num) = 'elvmax' ! hprime(ix,14) + num = num + 1 ; oro%name2(num) = 'orog_filt' ! oro + num = num + 1 ; oro%name2(num) = 'orog_raw' ! oro_uf + num = num + 1 ; oro%name2(num) = 'land_frac' ! land fraction [0:1] + !--- variables below here are optional + num = num + 1 ; oro%name2(num) = 'lake_frac' ! lake fraction [0:1] + num = num + 1 ; oro%name2(num) = '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 n = 1,num + var2_p => oro%var2(:,:,n) + if (trim(oro%name2(n)) == 'lake_frac' .or. trim(oro%name2(n)) == 'lake_depth' ) then + call register_restart_field(Oro_restart, oro%name2(n), var2_p, dimensions=(/'lat','lon'/), is_optional=.true.) + else + call register_restart_field(Oro_restart, oro%name2(n), var2_p, dimensions=(/'lat','lon'/)) + endif + enddo + + !--- register 3D vegetation and soil fractions + var3_fr => oro%var3v(:,:,:) + call register_restart_field(Oro_restart, 'vegetation_type_pct', var3_fr, dimensions=(/'num_veg_cat','lat ','lon '/) , is_optional=.true.) + var3_fr => oro%var3s(:,:,:) + call register_restart_field(Oro_restart, 'soil_type_pct', var3_fr, dimensions=(/'num_soil_cat','lat ','lon '/) , is_optional=.true.) + + end subroutine Oro_io_register + + subroutine Oro_io_copy(oro, Model, Sfcprop, Atm_block) + implicit none + class(Oro_io_data_type) :: oro + type(GFS_control_type), intent(in) :: Model + type(GFS_sfcprop_type) :: Sfcprop(:) + type(FmsNetcdfDomainFile_t) :: Oro_restart + type(block_control_type), intent(in) :: Atm_block + + integer :: i,j,nb,ix,num + + !$omp parallel do default(shared) private(i, j, nb, ix, num) + do nb = 1, Atm_block%nblks + !--- 2D variables + do ix = 1, Atm_block%blksz(nb) + i = Atm_block%index(nb)%ii(ix) - Atm_block%isc + 1 + j = Atm_block%index(nb)%jj(ix) - Atm_block%jsc + 1 + !--- stddev + ! Sfcprop(nb)%hprim(ix) = oro%var2(i,j,1) + !--- hprime(1:14) + num = 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%hprime(ix,num) = oro%var2(i,j,num) + !--- oro + num = num + 1 ; Sfcprop(nb)%oro(ix) = oro%var2(i,j,num) + num = num + 1 ; Sfcprop(nb)%oro_uf(ix) = oro%var2(i,j,num) + + Sfcprop(nb)%landfrac(ix) = -9999.0 + Sfcprop(nb)%lakefrac(ix) = -9999.0 + + num = num + 1 ; Sfcprop(nb)%landfrac(ix) = oro%var2(i,j,num) !land frac [0:1] + if (Model%lkm > 0 ) then + if(oro%var2(i,j,num+1)>Model%lakefrac_threshold .and. & + oro%var2(i,j,num+2)>Model%lakedepth_threshold) then + Sfcprop(nb)%lakefrac(ix) = oro%var2(i,j,num+1) !lake frac [0:1] + Sfcprop(nb)%lakedepth(ix) = oro%var2(i,j,num+2) !lake depth [m] !YWu + else + Sfcprop(nb)%lakefrac(ix) = 0 + Sfcprop(nb)%lakedepth(ix) = -9999 + endif + else + Sfcprop(nb)%lakefrac(ix) = oro%var2(i,j,num+1) !lake frac [0:1] + Sfcprop(nb)%lakedepth(ix) = oro%var2(i,j,num+2) !lake depth [m] !YWu + endif + num = num + 2 ! To account for lakefrac and lakedepth + + Sfcprop(nb)%vegtype_frac(ix,:) = -9999.0 + Sfcprop(nb)%soiltype_frac(ix,:) = -9999.0 + + Sfcprop(nb)%vegtype_frac(ix,:) = oro%var3v(i,j,:) ! vegetation type fractions, [0:1] + Sfcprop(nb)%soiltype_frac(ix,:) = oro%var3s(i,j,:) ! soil type fractions, [0:1] + + enddo + enddo + + !--- deallocate containers and free restart container + deallocate(oro%name2) + deallocate(oro%var2) + deallocate(oro%var3v) + deallocate(oro%var3s) + + nullify(oro%name2) + nullify(oro%var2) + nullify(oro%var3v) + nullify(oro%var3s) + + end subroutine Oro_io_copy + + subroutine Oro_io_final(oro) + implicit none + type(Oro_io_data_type) :: oro + + ! This #define reduces code length by a lot +#define IF_ASSOC_DEALLOC_NULL(var) \ + if(associated(oro%var)) then ; \ + deallocate(oro%var) ; \ + nullify(oro%var) ; \ + endif + + IF_ASSOC_DEALLOC_NULL(name2) + IF_ASSOC_DEALLOC_NULL(var2) + IF_ASSOC_DEALLOC_NULL(var3s) + IF_ASSOC_DEALLOC_NULL(var3v) + +#undef IF_ASSOC_DEALLOC_NULL + end subroutine Oro_io_final + +end module FV3GFS_oro_io From 3177218eb280ab134917c3dd37e52236739e2b8c Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Sat, 20 May 2023 01:18:34 +0000 Subject: [PATCH 14/27] gwd I/O in FV3GFS_oro_io.F90 --- io/FV3GFS_io.F90 | 105 ++++++++--------------------------------- io/FV3GFS_oro_io.F90 | 108 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 122 insertions(+), 91 deletions(-) diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index 8d821f86b..43db1cb04 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -574,8 +574,8 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta type(clm_lake_data_type) :: clm_lake type(rrfs_sd_state_type) :: rrfs_sd_state type(rrfs_sd_emissions_type) :: rrfs_sd_emis - - nvar_oro_ls_ss = 10 + type(Oro_scale_io_data_type) :: oro_ss + type(Oro_scale_io_data_type) :: oro_ls nvar_vegfr = Model%nvegcat nvar_soilfr = Model%nsoilcat @@ -667,98 +667,33 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta 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) ) + if ( (Model%gwd_opt==3 .or. Model%gwd_opt==33) .or. & + ( (Model%gwd_opt==2 .or. Model%gwd_opt==22) .and. & + Model%do_gsl_drag_ls_bl ) ) 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) ) + call oro_ls%register(Model,Oro_ls_restart,Atm_block) + !--- read new GSL created orography restart/data + call mpp_error(NOTE,'reading topographic/orographic information from & + &INPUT/oro_data_ls.tile*.nc') + call read_restart(Oro_ls_restart, ignore_checksum=ignore_rst_cksum) + call close_file(Oro_ls_restart) + call oro_ls%copy(Sfcprop,Atm_block,1) + endif !--- 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)) - allocate(oro_ls_var(nx,ny,nvar_oro_ls_ss)) - allocate(oro_ss_var(nx,ny,nvar_oro_ls_ss)) - - oro_ls_ss_name(1) = 'stddev' - oro_ls_ss_name(2) = 'convexity' - oro_ls_ss_name(3) = 'oa1' - oro_ls_ss_name(4) = 'oa2' - oro_ls_ss_name(5) = 'oa3' - oro_ls_ss_name(6) = 'oa4' - oro_ls_ss_name(7) = 'ol1' - oro_ls_ss_name(8) = 'ol2' - oro_ls_ss_name(9) = 'ol3' - oro_ls_ss_name(10) = 'ol4' - - 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) - 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) - call register_restart_field(Oro_ss_restart, oro_ls_ss_name(num), var2_p, dimensions=(/'lon','lat'/)) - enddo - nullify(var2_p) - 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 read_restart(Oro_ls_restart, ignore_checksum=ignore_rst_cksum) - call close_file(Oro_ls_restart) + call oro_ss%register(Model,Oro_ss_restart,Atm_block) call mpp_error(NOTE,'reading topographic/orographic information from & &INPUT/oro_data_ss.tile*.nc') call read_restart(Oro_ss_restart, ignore_checksum=ignore_rst_cksum) call close_file(Oro_ss_restart) - - - do nb = 1, Atm_block%nblks - !--- 2D variables - 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 - ! Replace hprime(1:10) with GSL oro stat data only when using GSL - ! drag suite with large scale GWD and blocking as part of unified drag - ! suite. Otherwise, original oro stat data is used. - if ( (Model%gwd_opt==3 .or. Model%gwd_opt==33) .or. & - ( (Model%gwd_opt==2 .or. Model%gwd_opt==22) .and. & - Model%do_gsl_drag_ls_bl ) ) then - !--- assign hprime(1:10) and hprime(15:24) with new oro stat data - Sfcprop(nb)%hprime(ix,1) = oro_ls_var(i,j,1) - Sfcprop(nb)%hprime(ix,2) = oro_ls_var(i,j,2) - Sfcprop(nb)%hprime(ix,3) = oro_ls_var(i,j,3) - Sfcprop(nb)%hprime(ix,4) = oro_ls_var(i,j,4) - Sfcprop(nb)%hprime(ix,5) = oro_ls_var(i,j,5) - Sfcprop(nb)%hprime(ix,6) = oro_ls_var(i,j,6) - Sfcprop(nb)%hprime(ix,7) = oro_ls_var(i,j,7) - Sfcprop(nb)%hprime(ix,8) = oro_ls_var(i,j,8) - Sfcprop(nb)%hprime(ix,9) = oro_ls_var(i,j,9) - Sfcprop(nb)%hprime(ix,10) = oro_ls_var(i,j,10) - endif - Sfcprop(nb)%hprime(ix,15) = oro_ss_var(i,j,1) - Sfcprop(nb)%hprime(ix,16) = oro_ss_var(i,j,2) - Sfcprop(nb)%hprime(ix,17) = oro_ss_var(i,j,3) - Sfcprop(nb)%hprime(ix,18) = oro_ss_var(i,j,4) - Sfcprop(nb)%hprime(ix,19) = oro_ss_var(i,j,5) - Sfcprop(nb)%hprime(ix,20) = oro_ss_var(i,j,6) - Sfcprop(nb)%hprime(ix,21) = oro_ss_var(i,j,7) - Sfcprop(nb)%hprime(ix,22) = oro_ss_var(i,j,8) - Sfcprop(nb)%hprime(ix,23) = oro_ss_var(i,j,9) - Sfcprop(nb)%hprime(ix,24) = oro_ss_var(i,j,10) - enddo - enddo - - end if + call oro_ss%copy(Sfcprop,Atm_block,15) + end if !--- SURFACE FILE diff --git a/io/FV3GFS_oro_io.F90 b/io/FV3GFS_oro_io.F90 index f30f45c79..6ab57850e 100644 --- a/io/FV3GFS_oro_io.F90 +++ b/io/FV3GFS_oro_io.F90 @@ -17,6 +17,7 @@ module FV3GFS_oro_io private public :: Oro_io_data_type, Oro_io_register, Oro_io_copy, Oro_io_final + public :: Oro_scale_io_data_type, Oro_scale_io_register, Oro_scale_io_copy, Oro_scale_io_final type Oro_io_data_type character(len=32), pointer, private, dimension(:) :: name2 => null() @@ -29,6 +30,18 @@ module FV3GFS_oro_io final :: Oro_io_final end type Oro_io_data_type + type Oro_scale_io_data_type + character(len=32), pointer, private, dimension(:) :: name => null() + real(kind=kind_phys), pointer, private, dimension(:,:,:) :: var => null() + contains + procedure, public :: register => Oro_scale_io_register + procedure, public :: copy => Oro_scale_io_copy + final :: Oro_scale_io_final + end type Oro_scale_io_data_type + + integer, parameter :: nvar_oro_scale = 10 + integer, parameter :: nvar_o2 = 19 + contains subroutine Oro_io_register(oro, Model, Oro_restart, Atm_block) @@ -42,25 +55,24 @@ subroutine Oro_io_register(oro, Model, Oro_restart, Atm_block) real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_fr => NULL() integer :: nx, ny - integer :: nvar_o2, nvar_vegfr, nvar_soilfr, n, num + integer :: nvar_vegfr, nvar_soilfr, n, num + + call get_nx_ny_from_atm(Atm_block, nx, ny) ! This #define reduces code length by a lot #define WARN_DISASSOCIATE(name) \ if(associated(name)) then ; \ - write(0,*) 'Internal error. Called oro%copy twice. Will try to keep going anyway.' ; \ + write(0,*) 'Internal error. Called oro%register twice. Will try to keep going anyway.' ; \ deallocate(name); \ nullify(name) ; \ endif - call get_nx_ny_from_atm(Atm_block, nx, ny) - WARN_DISASSOCIATE(oro%name2) WARN_DISASSOCIATE(oro%var2) WARN_DISASSOCIATE(oro%var3v) WARN_DISASSOCIATE(oro%var3s) #undef WARN_DISASSOCIATE - nvar_o2 = 19 nvar_vegfr = Model%nvegcat nvar_soilfr = Model%nsoilcat @@ -195,7 +207,7 @@ end subroutine Oro_io_copy subroutine Oro_io_final(oro) implicit none type(Oro_io_data_type) :: oro - + ! This #define reduces code length by a lot #define IF_ASSOC_DEALLOC_NULL(var) \ if(associated(oro%var)) then ; \ @@ -211,4 +223,88 @@ subroutine Oro_io_final(oro) #undef IF_ASSOC_DEALLOC_NULL end subroutine Oro_io_final + subroutine Oro_scale_io_register(oro_scale, Model, Oro_scale_restart, Atm_block) + implicit none + class(Oro_scale_io_data_type) :: oro_scale + type(GFS_control_type), intent(in) :: Model + type(FmsNetcdfDomainFile_t) :: Oro_scale_restart + type(block_control_type), intent(in) :: Atm_block + + real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() + integer :: num, nx, ny + +#define WARN_DISASSOCIATE(name) \ + if(associated(name)) then ; \ + write(0,*) 'Internal error. Called oro_scale%register twice. Will try to keep going anyway.' ; \ + deallocate(name); \ + nullify(name) ; \ + endif + + WARN_DISASSOCIATE(oro_scale%name) + WARN_DISASSOCIATE(oro_scale%var) +#undef WARN_DISASSOCIATE + + call get_nx_ny_from_atm(Atm_block, nx, ny) + + !--- allocate the various containers needed for orography data + allocate(oro_scale%name(nvar_oro_scale)) + allocate(oro_scale%var(nx,ny,nvar_oro_scale)) + + oro_scale%name(1) = 'stddev' + oro_scale%name(2) = 'convexity' + oro_scale%name(3) = 'oa1' + oro_scale%name(4) = 'oa2' + oro_scale%name(5) = 'oa3' + oro_scale%name(6) = 'oa4' + oro_scale%name(7) = 'ol1' + oro_scale%name(8) = 'ol2' + oro_scale%name(9) = 'ol3' + oro_scale%name(10) = 'ol4' + + call register_axis(Oro_scale_restart, "lon", 'X') + call register_axis(Oro_scale_restart, "lat", 'Y') + + do num = 1,nvar_oro_scale + var2_p => oro_scale%var(:,:,num) + call register_restart_field(Oro_scale_restart, oro_scale%name(num), var2_p, dimensions=(/'lon','lat'/)) + enddo + end subroutine Oro_scale_io_register + + subroutine Oro_scale_io_copy(oro_scale, Sfcprop, Atm_block, first_index) + implicit none + class(Oro_scale_io_data_type) :: oro_scale + type(GFS_sfcprop_type) :: Sfcprop(:) + type(block_control_type), intent(in) :: Atm_block + integer, intent(in) :: first_index + + integer :: i,j,nb,ix,num,v + + !$OMP PARALLEL DO PRIVATE(nb,ix,i,j,v) + do nb = 1, Atm_block%nblks + !--- 2D variables + do ix = 1, Atm_block%blksz(nb) + i = Atm_block%index(nb)%ii(ix) - Atm_block%isc + 1 + j = Atm_block%index(nb)%jj(ix) - Atm_block%jsc + 1 + do v=1,nvar_oro_scale + Sfcprop(nb)%hprime(ix,first_index-1+v) = oro_scale%var(i,j,v) + enddo + enddo + enddo + end subroutine Oro_scale_io_copy + + subroutine Oro_scale_io_final(oro_scale) + implicit none + type(Oro_scale_io_data_type) :: oro_scale + +#define IF_ASSOC_DEALLOC_NULL(vvarr) \ + if(associated(oro_scale%vvarr)) then ; \ + deallocate(oro_scale%vvarr) ; \ + nullify(oro_scale%vvarr) ; \ + endif + + IF_ASSOC_DEALLOC_NULL(name) + IF_ASSOC_DEALLOC_NULL(var) + +#undef IF_ASSOC_DEALLOC_NULL + end subroutine Oro_scale_io_final end module FV3GFS_oro_io From 1d9305fd4d3ace496888dacbf4eb42076c37704c Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Sun, 21 May 2023 22:50:17 +0000 Subject: [PATCH 15/27] store quilt restart data structures in FV3GFS_sfc_io types --- io/FV3GFS_restart_io.F90 | 644 +++++++++++---------------------------- io/FV3GFS_sfc_io.F90 | 34 +-- 2 files changed, 188 insertions(+), 490 deletions(-) diff --git a/io/FV3GFS_restart_io.F90 b/io/FV3GFS_restart_io.F90 index da641c04e..ec3cf9d4a 100644 --- a/io/FV3GFS_restart_io.F90 +++ b/io/FV3GFS_restart_io.F90 @@ -4,6 +4,8 @@ module FV3GFS_restart_io_mod use block_control_mod, only: block_control_type use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys use GFS_restart, only: GFS_restart_type + use FV3GFS_sfc_io + use FV3GFS_common_io, only: copy_from_GFS_Data implicit none private @@ -16,12 +18,7 @@ module FV3GFS_restart_io_mod real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: phy_var3 character(len=32),dimension(:),allocatable :: phy_var2_names, phy_var3_names - integer :: nvar2m, nvar2o, nvar3, nvar2r, nvar2mp, nvar3mp - real(kind=kind_phys), allocatable, target, dimension(:,:,:) :: sfc_var2 - real(kind=kind_phys), allocatable, target, dimension(:,:,:) :: sfc_var3ice - real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: sfc_var3, sfc_var3sn,sfc_var3eq,sfc_var3zn - character(len=32),allocatable,dimension(:) :: sfc_name2, sfc_name3 - + type(Sfc_io_data_type) :: sfc type(ESMF_FieldBundle) :: phy_bundle, sfc_bundle public FV3GFS_restart_register @@ -32,14 +29,6 @@ module FV3GFS_restart_io_mod public fv_sfc_restart_output public fv_sfc_restart_bundle_setup - interface copy_from_GFS_Data - module procedure copy_from_GFS_Data_2d_phys2phys, & - copy_from_GFS_Data_3d_phys2phys, & - copy_from_GFS_Data_2d_int2phys, & - copy_from_GFS_Data_3d_int2phys, & - copy_from_GFS_Data_2d_stack_phys2phys - end interface - contains subroutine FV3GFS_restart_register (Sfcprop, GFS_restart, Atm_block, Model) @@ -54,6 +43,7 @@ subroutine FV3GFS_restart_register (Sfcprop, GFS_restart, Atm_block, Model) type(block_control_type), intent(in) :: Atm_block type(GFS_control_type), intent(in) :: Model + logical was_changed integer :: isc, iec, jsc, jec, nx, ny integer :: num @@ -81,79 +71,9 @@ subroutine FV3GFS_restart_register (Sfcprop, GFS_restart, Atm_block, Model) enddo !--------------- sfc - nvar2m = 48 - if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - nvar2m = nvar2m + 4 -! nvar2m = nvar2m + 5 - endif - if (Model%cplwav) nvar2m = nvar2m + 1 - nvar2o = 18 - if (Model%lsm == Model%lsm_ruc) then - if (Model%rdlai) then - nvar2r = 13 - else - nvar2r = 12 - endif - nvar3 = 5 - else - nvar2r = 0 - nvar3 = 3 - endif - nvar2mp = 0 - nvar3mp = 0 - if (Model%lsm == Model%lsm_noahmp) then - nvar2mp = 29 - nvar3mp = 5 - endif - - !--- allocate the various containers needed for restarts - allocate(sfc_name2(nvar2m+nvar2o+nvar2mp+nvar2r)) - allocate(sfc_var2(nx,ny,nvar2m+nvar2o+nvar2mp+nvar2r)) - allocate(sfc_name3(0:nvar3+nvar3mp)) - allocate(sfc_var3ice(nx,ny,Model%kice)) - - if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp) then - allocate(sfc_var3(nx,ny,Model%lsoil,nvar3)) - elseif (Model%lsm == Model%lsm_ruc) then - allocate(sfc_var3(nx,ny,Model%lsoil_lsm,nvar3)) - endif - - sfc_var2 = -9999.0_r8 - sfc_var3 = -9999.0_r8 - sfc_var3ice= -9999.0_r8 - - if (Model%lsm == Model%lsm_noahmp) then - allocate(sfc_var3sn(nx,ny,-2:0,4:6)) - allocate(sfc_var3eq(nx,ny,1:4,7:7)) - allocate(sfc_var3zn(nx,ny,-2:4,8:8)) - - sfc_var3sn = -9999.0_r8 - sfc_var3eq = -9999.0_r8 - sfc_var3zn = -9999.0_r8 - endif - - call fill_Sfcprop_names(Model,sfc_name2,sfc_name3,nvar2m,.true.) - - sfc_name3(0) = 'tiice' - - if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp) then - 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 - sfc_name3(1) = 'tslb' - sfc_name3(2) = 'smois' - sfc_name3(3) = 'sh2o' - sfc_name3(4) = 'smfr' - sfc_name3(5) = 'flfr' - end if + was_changed = sfc%allocate_arrays(Model, Atm_block, .false., .true.) + call sfc%fill_2d_names(Model, .true.) + call sfc%fill_3d_names(Model, .true.) end subroutine FV3GFS_restart_register @@ -243,151 +163,151 @@ subroutine fv_sfc_restart_output(Sfcprop, Atm_block, Model) nt=0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%slmsk) !--- slmsk - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tg3) !--- tg3 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorl) !--- zorl - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alvsf) !--- alvsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alvwf) !--- alvwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alnsf) !--- alnsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alnwf) !--- alnwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%facsf) !--- facsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%facwf) !--- facwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%vfrac) !--- vfrac - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%canopy)!--- canopy - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%f10m) !--- f10m - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%t2m) !--- t2m - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%q2m) !--- q2m - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%vtype) !--- vtype - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%stype) !--- stype - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%uustar)!--- uustar - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%ffmm) !--- ffmm - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%ffhh) !--- ffhh - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%hice) !--- hice - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%fice) !--- fice - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tisfc) !--- tisfc - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tprcp) !--- tprcp - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%srflag)!--- srflag - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%shdmin)!--- shdmin - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%shdmax)!--- shdmax - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%slope) !--- slope - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snoalb)!--- snoalb - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sncovr) !--- sncovr - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsfc) !--- tsfc composite - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorlw) !--- zorl (zorl on water) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdirvis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdirnir_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdifvis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdifnir_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%emis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%emis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sncovr_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slmsk) !--- slmsk + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tg3) !--- tg3 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorl) !--- zorl + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvsf) !--- alvsf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvwf) !--- alvwf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnsf) !--- alnsf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnwf) !--- alnwf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facsf) !--- facsf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facwf) !--- facwf + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vfrac) !--- vfrac + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canopy)!--- canopy + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%f10m) !--- f10m + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t2m) !--- t2m + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%q2m) !--- q2m + + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vtype) !--- vtype + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stype) !--- stype + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%uustar)!--- uustar + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffmm) !--- ffmm + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffhh) !--- ffhh + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%hice) !--- hice + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fice) !--- fice + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tisfc) !--- tisfc + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tprcp) !--- tprcp + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%srflag)!--- srflag + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmin)!--- shdmin + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmax)!--- shdmax + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slope) !--- slope + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snoalb)!--- snoalb + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr) !--- sncovr + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfc) !--- tsfc composite + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlw) !--- zorl (zorl on water) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice) if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdirvis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdifvis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdirnir_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%albdifnir_ice) -! sfc_var2(i,j,53) = Sfcprop(nb)%sfalb_ice(ix) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_ice) +! sfc%var2(i,j,53) = Sfcprop(nb)%sfalb_ice(ix) endif if (Model%cplwav) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zorlwav) !--- zorlwav (zorl from wav) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlwav) !--- zorlwav (zorl from wav) endif !--- NSSTM variables if (Model%nstf_name(1) > 0) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tref) !--- nsstm tref - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%z_c) !--- nsstm z_c - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%c_0) !--- nsstm c_0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%c_d) !--- nsstm c_d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%w_0) !--- nsstm w_0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%w_d) !--- nsstm w_d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xt) !--- nsstm xt - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xs) !--- nsstm xs - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xu) !--- nsstm xu - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xv) !--- nsstm xv - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xz) !--- nsstm xz - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zm) !--- nsstm zm - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xtts) !--- nsstm xtts - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xzts) !--- nsstm xzts - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%ifd) !--- nsstm ifd - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%dt_cool)!--- nsstm dt_cool - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%qrain) !--- nsstm qrain + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tref) !--- nsstm tref + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%z_c) !--- nsstm z_c + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_0) !--- nsstm c_0 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_d) !--- nsstm c_d + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_0) !--- nsstm w_0 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_d) !--- nsstm w_d + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xt) !--- nsstm xt + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xs) !--- nsstm xs + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xu) !--- nsstm xu + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xv) !--- nsstm xv + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xz) !--- nsstm xz + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zm) !--- nsstm zm + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xtts) !--- nsstm xtts + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xzts) !--- nsstm xzts + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ifd) !--- nsstm ifd + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%dt_cool)!--- nsstm dt_cool + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qrain) !--- nsstm qrain ! FIXME convert negative zero (-0.0) to zero (0.0) do j=1,ny do i=1,nx - if(sfc_var2(i,j,nt) == 0.0) sfc_var2(i,j,nt) = 0.0 + if(sfc%var2(i,j,nt) == 0.0) sfc%var2(i,j,nt) = 0.0 end do end do endif if (Model%lsm == Model%lsm_ruc) then !--- Extra RUC variables - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%wetness) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%clw_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%clw_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%qwv_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%qwv_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsnow_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tsnow_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snowfallac_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snowfallac_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sfalb_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sfalb_lnd_bck) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sfalb_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wetness) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd_bck) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) if (Model%rdlai) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xlaixy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) endif else if (Model%lsm == Model%lsm_noahmp) then !--- Extra Noah MP variables - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%snowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tvxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tgxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%canicexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%canliqxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%eahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%tahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%cmxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%chxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%fwetxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%sneqvoxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%alboldxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%qsnowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%wslakexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%zwtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%waxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%wtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%lfmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%rtmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%stmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%woodxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%stblcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%fastcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xsaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%xlaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%taussxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%smcwtdxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%deeprechxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc_var2,Sfcprop(nb)%rechxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tvxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tgxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canicexy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canliqxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%eahxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tahxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%cmxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%chxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fwetxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sneqvoxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alboldxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qsnowxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wslakexy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zwtxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%waxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wtxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%lfmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rtmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%woodxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stblcpxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fastcpxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xsaixy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%taussxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%smcwtdxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%deeprechxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rechxy) endif do k = 1,Model%kice do ix = 1, Atm_block%blksz(nb) ice=Sfcprop(nb)%tiice(ix,k) if(ice sfc_var2(:,:,num) - call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc_name2(num)), outputfile, grid, bundle) + do num = 1,sfc%nvar2m + temp_r2d => sfc%var2(:,:,num) + call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc%name2(num)), outputfile, grid, bundle) enddo if (Model%nstf_name(1) > 0) then - do num = nvar2m+1,nvar2m+nvar2o - temp_r2d => sfc_var2(:,:,num) - call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc_name2(num)), outputfile, grid, bundle) + do num = sfc%nvar2m+1,sfc%nvar2m+sfc%nvar2o + temp_r2d => sfc%var2(:,:,num) + call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc%name2(num)), outputfile, grid, bundle) enddo endif - if (Model%lsm == Model%lsm_ruc) then ! nvar2mp =0 - do num = nvar2m+nvar2o+1, nvar2m+nvar2o+nvar2r - temp_r2d => sfc_var2(:,:,num) - call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc_name2(num)), outputfile, grid, bundle) + if (Model%lsm == Model%lsm_ruc) then ! sfc%nvar2mp =0 + do num = sfc%nvar2m+sfc%nvar2o+1, sfc%nvar2m+sfc%nvar2o+sfc%nvar2r + temp_r2d => sfc%var2(:,:,num) + call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc%name2(num)), outputfile, grid, bundle) enddo - else if (Model%lsm == Model%lsm_noahmp) then ! nvar2r =0 - do num = nvar2m+nvar2o+1,nvar2m+nvar2o+nvar2mp - temp_r2d => sfc_var2(:,:,num) - call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc_name2(num)), outputfile, grid, bundle) + else if (Model%lsm == Model%lsm_noahmp) then ! sfc%nvar2r =0 + do num = sfc%nvar2m+sfc%nvar2o+1,sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp + temp_r2d => sfc%var2(:,:,num) + call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc%name2(num)), outputfile, grid, bundle) enddo endif - temp_r3d => sfc_var3ice(:,:,:) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc_name3(0)), "zaxis_1", Model%kice, trim(outputfile), grid, bundle) + temp_r3d => sfc%var3ice(:,:,:) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(0)), "zaxis_1", Model%kice, trim(outputfile), grid, bundle) if(Model%lsm == Model%lsm_ruc) then - do num = 1,nvar3 - temp_r3d => sfc_var3(:,:,:,num) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc_name3(num)), "zaxis_1", Model%kice, trim(outputfile), grid, bundle) + do num = 1,sfc%nvar3 + temp_r3d => sfc%var3(:,:,:,num) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_1", Model%kice, trim(outputfile), grid, bundle) enddo else - do num = 1,nvar3 - temp_r3d => sfc_var3(:,:,:,num) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc_name3(num)), "zaxis_2", Model%lsoil, trim(outputfile), grid, bundle) + do num = 1,sfc%nvar3 + temp_r3d => sfc%var3(:,:,:,num) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_2", Model%lsoil, trim(outputfile), grid, bundle) enddo endif if (Model%lsm == Model%lsm_noahmp) then - do num = nvar3+1,nvar3+3 - temp_r3d => sfc_var3sn(:,:,:,num) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc_name3(num)), "zaxis_3", 3, trim(outputfile), grid, bundle) + do num = sfc%nvar3+1,sfc%nvar3+3 + temp_r3d => sfc%var3sn(:,:,:,num) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_3", 3, trim(outputfile), grid, bundle) enddo - temp_r3d => sfc_var3eq(:,:,:,7) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc_name3(7)), "zaxis_2", Model%lsoil, trim(outputfile), grid, bundle) + temp_r3d => sfc%var3eq(:,:,:,7) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(7)), "zaxis_2", Model%lsoil, trim(outputfile), grid, bundle) - temp_r3d => sfc_var3zn(:,:,:,8) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc_name3(8)), "zaxis_4", 7, trim(outputfile), grid, bundle) + temp_r3d => sfc%var3zn(:,:,:,8) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(8)), "zaxis_4", 7, trim(outputfile), grid, bundle) endif ! lsm = lsm_noahmp end subroutine fv_sfc_restart_bundle_setup @@ -695,226 +615,4 @@ subroutine add_zaxis_to_field(field, axis_name, num_levels) end subroutine add_zaxis_to_field - pure subroutine fill_Sfcprop_names(Model,sfc_name2,sfc_name3,nvar_s2m,warm_start) - implicit none - type(GFS_control_type), intent(in) :: Model - integer, intent(in) :: nvar_s2m - character(len=32),intent(out) :: sfc_name2(:), sfc_name3(:) - logical, intent(in) :: warm_start - integer :: nt - - !--- names of the 2D variables to save - nt=0 - nt=nt+1 ; sfc_name2(nt) = 'slmsk' - nt=nt+1 ; sfc_name2(nt) = 'tsea' !tsfc - nt=nt+1 ; sfc_name2(nt) = 'sheleg' !weasd - nt=nt+1 ; sfc_name2(nt) = 'tg3' - nt=nt+1 ; sfc_name2(nt) = 'zorl' - nt=nt+1 ; sfc_name2(nt) = 'alvsf' - nt=nt+1 ; sfc_name2(nt) = 'alvwf' - nt=nt+1 ; sfc_name2(nt) = 'alnsf' - nt=nt+1 ; sfc_name2(nt) = 'alnwf' - nt=nt+1 ; sfc_name2(nt) = 'facsf' - nt=nt+1 ; sfc_name2(nt) = 'facwf' - nt=nt+1 ; sfc_name2(nt) = 'vfrac' - nt=nt+1 ; sfc_name2(nt) = 'canopy' - nt=nt+1 ; sfc_name2(nt) = 'f10m' - nt=nt+1 ; sfc_name2(nt) = 't2m' - nt=nt+1 ; sfc_name2(nt) = 'q2m' - nt=nt+1 ; sfc_name2(nt) = 'vtype' - nt=nt+1 ; sfc_name2(nt) = 'stype' - nt=nt+1 ; sfc_name2(nt) = 'uustar' - nt=nt+1 ; sfc_name2(nt) = 'ffmm' - nt=nt+1 ; sfc_name2(nt) = 'ffhh' - nt=nt+1 ; sfc_name2(nt) = 'hice' - nt=nt+1 ; sfc_name2(nt) = 'fice' - nt=nt+1 ; sfc_name2(nt) = 'tisfc' - nt=nt+1 ; sfc_name2(nt) = 'tprcp' - nt=nt+1 ; sfc_name2(nt) = 'srflag' - nt=nt+1 ; sfc_name2(nt) = 'snwdph' !snowd - nt=nt+1 ; sfc_name2(nt) = 'shdmin' - nt=nt+1 ; sfc_name2(nt) = 'shdmax' - nt=nt+1 ; sfc_name2(nt) = 'slope' - nt=nt+1 ; sfc_name2(nt) = 'snoalb' - !--- variables below here are optional - nt=nt+1 ; sfc_name2(nt) = 'sncovr' - nt=nt+1 ; sfc_name2(nt) = 'snodl' !snowd on land portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'weasdl'!weasd on land portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'tsfc' !tsfc composite - nt=nt+1 ; sfc_name2(nt) = 'tsfcl' !temp on land portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'zorlw' !zorl on water portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'zorll' !zorl on land portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'zorli' !zorl on ice portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'albdirvis_lnd' - nt=nt+1 ; sfc_name2(nt) = 'albdirnir_lnd' - nt=nt+1 ; sfc_name2(nt) = 'albdifvis_lnd' - nt=nt+1 ; sfc_name2(nt) = 'albdifnir_lnd' - nt=nt+1 ; sfc_name2(nt) = 'emis_lnd' - nt=nt+1 ; sfc_name2(nt) = 'emis_ice' - nt=nt+1 ; sfc_name2(nt) = 'sncovr_ice' - nt=nt+1 ; sfc_name2(nt) = 'snodi' ! snowd on ice portion of a cell - nt=nt+1 ; sfc_name2(nt) = 'weasdi'! weasd on ice portion of a cell - - if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - nt=nt+1 ; sfc_name2(nt) = 'albdirvis_ice' - nt=nt+1 ; sfc_name2(nt) = 'albdifvis_ice' - nt=nt+1 ; sfc_name2(nt) = 'albdirnir_ice' - nt=nt+1 ; sfc_name2(nt) = 'albdifnir_ice' -! nt=nt+1 ; sfc_name2(nt) = 'sfalb_ice' - endif - - if(Model%cplwav) then - sfc_name2(nvar_s2m) = 'zorlwav' !zorl from wave component - endif - - nt = nvar_s2m ! next variable will be at nvar_s2m - - !--- NSSTM inputs only needed when (nstf_name(1) > 0) .and. (nstf_name(2)) == 0) - nt=nt+1 ; sfc_name2(nt) = 'tref' - nt=nt+1 ; sfc_name2(nt) = 'z_c' - nt=nt+1 ; sfc_name2(nt) = 'c_0' - nt=nt+1 ; sfc_name2(nt) = 'c_d' - nt=nt+1 ; sfc_name2(nt) = 'w_0' - nt=nt+1 ; sfc_name2(nt) = 'w_d' - nt=nt+1 ; sfc_name2(nt) = 'xt' - nt=nt+1 ; sfc_name2(nt) = 'xs' - nt=nt+1 ; sfc_name2(nt) = 'xu' - nt=nt+1 ; sfc_name2(nt) = 'xv' - nt=nt+1 ; sfc_name2(nt) = 'xz' - nt=nt+1 ; sfc_name2(nt) = 'zm' - nt=nt+1 ; sfc_name2(nt) = 'xtts' - nt=nt+1 ; sfc_name2(nt) = 'xzts' - nt=nt+1 ; sfc_name2(nt) = 'd_conv' - nt=nt+1 ; sfc_name2(nt) = 'ifd' - nt=nt+1 ; sfc_name2(nt) = 'dt_cool' - nt=nt+1 ; sfc_name2(nt) = 'qrain' -! -! Only needed when Noah MP LSM is used - 29 2D -! - if (Model%lsm == Model%lsm_noahmp) then - nt=nt+1 ; sfc_name2(nt) = 'snowxy' - nt=nt+1 ; sfc_name2(nt) = 'tvxy' - nt=nt+1 ; sfc_name2(nt) = 'tgxy' - nt=nt+1 ; sfc_name2(nt) = 'canicexy' - nt=nt+1 ; sfc_name2(nt) = 'canliqxy' - nt=nt+1 ; sfc_name2(nt) = 'eahxy' - nt=nt+1 ; sfc_name2(nt) = 'tahxy' - nt=nt+1 ; sfc_name2(nt) = 'cmxy' - nt=nt+1 ; sfc_name2(nt) = 'chxy' - nt=nt+1 ; sfc_name2(nt) = 'fwetxy' - nt=nt+1 ; sfc_name2(nt) = 'sneqvoxy' - nt=nt+1 ; sfc_name2(nt) = 'alboldxy' - nt=nt+1 ; sfc_name2(nt) = 'qsnowxy' - nt=nt+1 ; sfc_name2(nt) = 'wslakexy' - nt=nt+1 ; sfc_name2(nt) = 'zwtxy' - nt=nt+1 ; sfc_name2(nt) = 'waxy' - nt=nt+1 ; sfc_name2(nt) = 'wtxy' - nt=nt+1 ; sfc_name2(nt) = 'lfmassxy' - nt=nt+1 ; sfc_name2(nt) = 'rtmassxy' - nt=nt+1 ; sfc_name2(nt) = 'stmassxy' - nt=nt+1 ; sfc_name2(nt) = 'woodxy' - nt=nt+1 ; sfc_name2(nt) = 'stblcpxy' - nt=nt+1 ; sfc_name2(nt) = 'fastcpxy' - nt=nt+1 ; sfc_name2(nt) = 'xsaixy' - nt=nt+1 ; sfc_name2(nt) = 'xlaixy' - nt=nt+1 ; sfc_name2(nt) = 'taussxy' - nt=nt+1 ; sfc_name2(nt) = 'smcwtdxy' - nt=nt+1 ; sfc_name2(nt) = 'deeprechxy' - nt=nt+1 ; sfc_name2(nt) = 'rechxy' - else if (Model%lsm == Model%lsm_ruc .and. warm_start) then - nt=nt+1 ; sfc_name2(nt) = 'wetness' - nt=nt+1 ; sfc_name2(nt) = 'clw_surf_land' - nt=nt+1 ; sfc_name2(nt) = 'clw_surf_ice' - nt=nt+1 ; sfc_name2(nt) = 'qwv_surf_land' - nt=nt+1 ; sfc_name2(nt) = 'qwv_surf_ice' - nt=nt+1 ; sfc_name2(nt) = 'tsnow_land' - nt=nt+1 ; sfc_name2(nt) = 'tsnow_ice' - nt=nt+1 ; sfc_name2(nt) = 'snowfall_acc_land' - nt=nt+1 ; sfc_name2(nt) = 'snowfall_acc_ice' - nt=nt+1 ; sfc_name2(nt) = 'sfalb_lnd' - nt=nt+1 ; sfc_name2(nt) = 'sfalb_lnd_bck' - nt=nt+1 ; sfc_name2(nt) = 'sfalb_ice' - if (Model%rdlai) then - nt=nt+1 ; sfc_name2(nt) = 'lai' - endif - else if (Model%lsm == Model%lsm_ruc .and. Model%rdlai) then - nt=nt+1 ; sfc_name2(nt) = 'lai' - endif - end subroutine fill_sfcprop_names - - pure subroutine copy_from_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(in) :: var_block(:) - real(kind=kind_phys), intent(out) :: var2d(:,:,:) - integer ix - - nt=nt+1 - do ix=1,size(var_block) - var2d(ii1(ix),jj1(ix),nt) = var_block(ix) - enddo - end subroutine copy_from_GFS_Data_2d_phys2phys - - pure subroutine copy_from_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(in) :: var_block(:,:) - real(kind=kind_phys), intent(out) :: var3d(:,:,:,:) - integer ix, k - - nt=nt+1 - do k=lbound(var_block,2),ubound(var_block,2) - do ix=1,size(var_block,1) - var3d(ii1(ix),jj1(ix),k,nt) = var_block(ix,k) - enddo - enddo - end subroutine copy_from_GFS_Data_3d_phys2phys - - pure subroutine copy_from_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc, var_block(:) - integer, intent(inout) :: nt - real(kind=kind_phys), intent(out) :: var2d(:,:,:) - integer ix - - nt=nt+1 - do ix=1,size(var_block) - var2d(ii1(ix),jj1(ix),nt) = var_block(ix) - enddo - end subroutine copy_from_GFS_Data_2d_int2phys - - pure subroutine copy_from_GFS_Data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - ! For copying phy_f2d and phy_fctd - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(in) :: var_block(:,:) - real(kind=kind_phys), intent(out) :: var3d(:,:,:) - integer ix, k - - nt=nt+1 - do k=lbound(var_block,2),ubound(var_block,2) - do ix=1,size(var_block,1) - var3d(ii1(ix),jj1(ix),nt) = var_block(ix,k) - enddo - enddo - end subroutine copy_from_GFS_Data_2d_stack_phys2phys - - pure subroutine copy_from_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), var_block(:,:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(out) :: var3d(:,:,:,:) - integer ix, k - - nt=nt+1 - do k=lbound(var_block,2),ubound(var_block,2) - do ix=1,size(var_block,1) - var3d(ii1(ix),jj1(ix),k,nt) = real(var_block(ix,k),kind_phys) - enddo - enddo - end subroutine copy_from_GFS_Data_3d_int2phys - end module FV3GFS_restart_io_mod diff --git a/io/FV3GFS_sfc_io.F90 b/io/FV3GFS_sfc_io.F90 index 0d9c64032..852ab1b0b 100644 --- a/io/FV3GFS_sfc_io.F90 +++ b/io/FV3GFS_sfc_io.F90 @@ -27,17 +27,17 @@ module FV3GFS_sfc_io real(kind_phys), parameter:: zero = 0, one = 1 type Sfc_io_data_type - integer, private :: nvar2o = 0 - integer, private :: nvar3 = 0 - integer, private :: nvar2r = 0 - integer, private :: nvar2mp = 0 - integer, private :: nvar3mp = 0 - integer, private :: nvar2l = 0 - integer, private :: nvar2m = 0 - integer, private :: nvar_before_lake = 0 + integer, public :: nvar2o = 0 + integer, public :: nvar3 = 0 + integer, public :: nvar2r = 0 + integer, public :: nvar2mp = 0 + integer, public :: nvar3mp = 0 + integer, public :: nvar2l = 0 + integer, public :: nvar2m = 0 + integer, public :: nvar_before_lake = 0 ! The lsoil flag is only meaningful when reading:; - logical, private :: is_lsoil = .false. + logical, public :: is_lsoil = .false. ! SYNONYMS: Some nvar variables had two names in FV3GFS_io.F90. They have ! only one name here. The "_s" is redundant because this file only has @@ -49,15 +49,15 @@ module FV3GFS_sfc_io ! - nvar2mp = nvar_s2mp ! - nvar3mp = nvar_s3mp - real(kind=kind_phys), pointer, dimension(:,:,:), private :: var2 => null() - real(kind=kind_phys), pointer, dimension(:,:,:), private :: var3ice => null() - real(kind=kind_phys), pointer, dimension(:,:,:,:), private :: var3 => null() - real(kind=kind_phys), pointer, dimension(:,:,:,:), private :: var3sn => null() - real(kind=kind_phys), pointer, dimension(:,:,:,:), private :: var3eq => null() - real(kind=kind_phys), pointer, dimension(:,:,:,:), private :: var3zn => null() + real(kind=kind_phys), pointer, dimension(:,:,:), public :: var2 => null() + real(kind=kind_phys), pointer, dimension(:,:,:), public :: var3ice => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3 => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3sn => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3eq => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:), public :: var3zn => null() - character(len=32), pointer, dimension(:), private :: name2 => null() - character(len=32), pointer, dimension(:), private :: name3 => null() + character(len=32), pointer, dimension(:), public :: name2 => null() + character(len=32), pointer, dimension(:), public :: name3 => null() contains From 2a548ec7b80112e5fd2ef64258f73bf9d60c6ced Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Mon, 22 May 2023 15:59:53 +0000 Subject: [PATCH 16/27] remove copy_from_GFS_Data calls from FV3GFS_restart_io.F90 --- io/FV3GFS_restart_io.F90 | 233 +-------------------------------------- 1 file changed, 1 insertion(+), 232 deletions(-) diff --git a/io/FV3GFS_restart_io.F90 b/io/FV3GFS_restart_io.F90 index ec3cf9d4a..677a88d43 100644 --- a/io/FV3GFS_restart_io.F90 +++ b/io/FV3GFS_restart_io.F90 @@ -140,238 +140,7 @@ subroutine fv_sfc_restart_output(Sfcprop, Atm_block, Model) type(block_control_type), intent(in) :: Atm_block type(GFS_control_type), intent(in) :: Model - integer :: i, j, k, nb, ix, lsoil, num, nt - integer :: isc, iec, jsc, jec, npz, nx, ny - integer, allocatable :: ii1(:), jj1(:) - real(kind_phys) :: ice - integer :: is, ie - - isc = Atm_block%isc - iec = Atm_block%iec - jsc = Atm_block%jsc - jec = Atm_block%jec - npz = Atm_block%npz - nx = (iec - isc + 1) - ny = (jec - jsc + 1) - -!$omp parallel do default(shared) private(i, j, nb, ix, nt, ii1, jj1, lsoil, k, ice) - block_loop: do nb = 1, Atm_block%nblks - allocate(ii1(Atm_block%blksz(nb))) - allocate(jj1(Atm_block%blksz(nb))) - ii1=Atm_block%index(nb)%ii - isc + 1 - jj1=Atm_block%index(nb)%jj - jsc + 1 - - nt=0 - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slmsk) !--- slmsk - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfco) !--- tsfc (tsea in sfc file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasd) !--- weasd (sheleg in sfc file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tg3) !--- tg3 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorl) !--- zorl - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvsf) !--- alvsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alvwf) !--- alvwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnsf) !--- alnsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alnwf) !--- alnwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facsf) !--- facsf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%facwf) !--- facwf - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vfrac) !--- vfrac - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canopy)!--- canopy - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%f10m) !--- f10m - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%t2m) !--- t2m - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%q2m) !--- q2m - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%vtype) !--- vtype - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stype) !--- stype - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%uustar)!--- uustar - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffmm) !--- ffmm - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ffhh) !--- ffhh - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%hice) !--- hice - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fice) !--- fice - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tisfc) !--- tisfc - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tprcp) !--- tprcp - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%srflag)!--- srflag - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowd) !--- snowd (snwdph in the file) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmin)!--- shdmin - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%shdmax)!--- shdmax - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%slope) !--- slope - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snoalb)!--- snoalb - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr) !--- sncovr - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodl) !--- snodl (snowd on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdl) !--- weasdl (weasd on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfc) !--- tsfc composite - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsfcl) !--- tsfcl (temp on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlw) !--- zorl (zorl on water) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorll) !--- zorll (zorl on land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorli) !--- zorli (zorl on ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%emis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sncovr_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snodi) !--- snodi (snowd on ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%weasdi) !--- weasdi (weasd on ice) - if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirvis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifvis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdirnir_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%albdifnir_ice) -! sfc%var2(i,j,53) = Sfcprop(nb)%sfalb_ice(ix) - endif - if (Model%cplwav) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zorlwav) !--- zorlwav (zorl from wav) - endif - !--- NSSTM variables - if (Model%nstf_name(1) > 0) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tref) !--- nsstm tref - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%z_c) !--- nsstm z_c - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_0) !--- nsstm c_0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%c_d) !--- nsstm c_d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_0) !--- nsstm w_0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%w_d) !--- nsstm w_d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xt) !--- nsstm xt - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xs) !--- nsstm xs - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xu) !--- nsstm xu - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xv) !--- nsstm xv - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xz) !--- nsstm xz - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zm) !--- nsstm zm - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xtts) !--- nsstm xtts - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xzts) !--- nsstm xzts - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%d_conv) !--- nsstm d_conv - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%ifd) !--- nsstm ifd - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%dt_cool)!--- nsstm dt_cool - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qrain) !--- nsstm qrain - - ! FIXME convert negative zero (-0.0) to zero (0.0) - do j=1,ny - do i=1,nx - if(sfc%var2(i,j,nt) == 0.0) sfc%var2(i,j,nt) = 0.0 - end do - end do - endif - - if (Model%lsm == Model%lsm_ruc) then - !--- Extra RUC variables - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wetness) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%clw_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qwv_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tsnow_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowfallac_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_lnd_bck) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sfalb_ice) - if (Model%rdlai) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) - endif - else if (Model%lsm == Model%lsm_noahmp) then - !--- Extra Noah MP variables - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%snowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tvxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tgxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canicexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%canliqxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%eahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%tahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%cmxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%chxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fwetxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%sneqvoxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%alboldxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%qsnowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wslakexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%zwtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%waxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%wtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%lfmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rtmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%woodxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%stblcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%fastcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xsaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%xlaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%taussxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%smcwtdxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%deeprechxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,sfc%var2,Sfcprop(nb)%rechxy) - endif - - do k = 1,Model%kice - do ix = 1, Atm_block%blksz(nb) - ice=Sfcprop(nb)%tiice(ix,k) - if(ice Date: Mon, 22 May 2023 18:44:54 +0000 Subject: [PATCH 17/27] bundle vars in FV3GFS_sfc_io.F90 --- io/FV3GFS_restart_io.F90 | 157 +-------------------------------------- io/FV3GFS_sfc_io.F90 | 98 +++++++++++++++++++++++- 2 files changed, 100 insertions(+), 155 deletions(-) diff --git a/io/FV3GFS_restart_io.F90 b/io/FV3GFS_restart_io.F90 index 677a88d43..043e323df 100644 --- a/io/FV3GFS_restart_io.F90 +++ b/io/FV3GFS_restart_io.F90 @@ -5,7 +5,8 @@ module FV3GFS_restart_io_mod use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys use GFS_restart, only: GFS_restart_type use FV3GFS_sfc_io - use FV3GFS_common_io, only: copy_from_GFS_Data + use FV3GFS_common_io, only: create_2d_field_and_add_to_bundle, & + create_3d_field_and_add_to_bundle, add_zaxis_to_field implicit none private @@ -220,13 +221,6 @@ subroutine fv_sfc_restart_bundle_setup(bundle, grid, Model, rc) integer :: num - if (.not. associated(sfc%var2)) then - write(0,*)'ERROR sfc%var2, NOT associated' - endif - if (.not. associated(sfc%var3)) then - write(0,*)'ERROR sfc%var3 NOT associated' - endif - sfc_bundle = bundle call ESMF_FieldBundleGet(bundle, name=sfcbdl_name,rc=rc) @@ -236,152 +230,9 @@ subroutine fv_sfc_restart_bundle_setup(bundle, grid, Model, rc) !*** add esmf fields - do num = 1,sfc%nvar2m - temp_r2d => sfc%var2(:,:,num) - call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc%name2(num)), outputfile, grid, bundle) - enddo - - if (Model%nstf_name(1) > 0) then - do num = sfc%nvar2m+1,sfc%nvar2m+sfc%nvar2o - temp_r2d => sfc%var2(:,:,num) - call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc%name2(num)), outputfile, grid, bundle) - enddo - endif - - if (Model%lsm == Model%lsm_ruc) then ! sfc%nvar2mp =0 - do num = sfc%nvar2m+sfc%nvar2o+1, sfc%nvar2m+sfc%nvar2o+sfc%nvar2r - temp_r2d => sfc%var2(:,:,num) - call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc%name2(num)), outputfile, grid, bundle) - enddo - else if (Model%lsm == Model%lsm_noahmp) then ! sfc%nvar2r =0 - do num = sfc%nvar2m+sfc%nvar2o+1,sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp - temp_r2d => sfc%var2(:,:,num) - call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc%name2(num)), outputfile, grid, bundle) - enddo - endif - - temp_r3d => sfc%var3ice(:,:,:) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(0)), "zaxis_1", Model%kice, trim(outputfile), grid, bundle) - - if(Model%lsm == Model%lsm_ruc) then - do num = 1,sfc%nvar3 - temp_r3d => sfc%var3(:,:,:,num) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_1", Model%kice, trim(outputfile), grid, bundle) - enddo - else - do num = 1,sfc%nvar3 - temp_r3d => sfc%var3(:,:,:,num) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_2", Model%lsoil, trim(outputfile), grid, bundle) - enddo - endif - - if (Model%lsm == Model%lsm_noahmp) then - do num = sfc%nvar3+1,sfc%nvar3+3 - temp_r3d => sfc%var3sn(:,:,:,num) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_3", 3, trim(outputfile), grid, bundle) - enddo - - temp_r3d => sfc%var3eq(:,:,:,7) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(7)), "zaxis_2", Model%lsoil, trim(outputfile), grid, bundle) - - temp_r3d => sfc%var3zn(:,:,:,8) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(8)), "zaxis_4", 7, trim(outputfile), grid, bundle) - endif ! lsm = lsm_noahmp + call sfc%bundle_2d_fields(bundle, grid, Model, outputfile) + call sfc%bundle_3d_fields(bundle, grid, Model, outputfile) end subroutine fv_sfc_restart_bundle_setup - subroutine create_2d_field_and_add_to_bundle(temp_r2d, field_name, outputfile, grid, bundle) - - use esmf - - implicit none - - real(kind_phys), dimension(:,:), pointer, intent(in) :: temp_r2d - character(len=*), intent(in) :: field_name - character(len=*), intent(in) :: outputfile - type(ESMF_Grid), intent(in) :: grid - type(ESMF_FieldBundle), intent(inout) :: bundle - - type(ESMF_Field) :: field - - integer :: rc, i - - field = ESMF_FieldCreate(grid, temp_r2d, datacopyflag=ESMF_DATACOPY_REFERENCE, & - name=trim(field_name), indexFlag=ESMF_INDEX_DELOCAL, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU,line=__LINE__, file=__FILE__)) & - call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", name='output_file', value=trim(outputfile), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_FieldBundleAdd(bundle, (/field/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - end subroutine create_2d_field_and_add_to_bundle - - subroutine create_3d_field_and_add_to_bundle(temp_r3d, field_name, axis_name, num_levels, outputfile, grid, bundle) - - use esmf - - implicit none - - real(kind_phys), dimension(:,:,:), pointer, intent(in) :: temp_r3d - character(len=*), intent(in) :: field_name - character(len=*), intent(in) :: axis_name - integer, intent(in) :: num_levels - character(len=*), intent(in) :: outputfile - type(ESMF_Grid), intent(in) :: grid - type(ESMF_FieldBundle), intent(inout) :: bundle - - type(ESMF_Field) :: field - - integer :: rc, i - - field = ESMF_FieldCreate(grid, temp_r3d, datacopyflag=ESMF_DATACOPY_REFERENCE, & - name=trim(field_name), indexFlag=ESMF_INDEX_DELOCAL, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU,line=__LINE__, file=__FILE__)) & - call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", name='output_file', value=trim(outputfile), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call add_zaxis_to_field(field, axis_name, num_levels) - - call ESMF_FieldBundleAdd(bundle, (/field/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - end subroutine create_3d_field_and_add_to_bundle - - subroutine add_zaxis_to_field(field, axis_name, num_levels) - - use esmf - - implicit none - - type(ESMF_Field), intent(inout) :: field - character(len=*), intent(in) :: axis_name - integer, intent(in) :: num_levels - - real(kind_phys), allocatable, dimension(:) :: buffer - integer :: rc, i - - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & - name="ESMF:ungridded_dim_labels", valueList=(/trim(axis_name)/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - allocate( buffer(num_levels) ) - do i=1, num_levels - buffer(i)=i - end do - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3-dim", & - name=trim(axis_name), valueList=buffer, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - deallocate(buffer) - - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3-dim", & - name=trim(axis_name)//"cartesian_axis", value="Z", rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - end subroutine add_zaxis_to_field - end module FV3GFS_restart_io_mod diff --git a/io/FV3GFS_sfc_io.F90 b/io/FV3GFS_sfc_io.F90 index 852ab1b0b..6cb5799bc 100644 --- a/io/FV3GFS_sfc_io.F90 +++ b/io/FV3GFS_sfc_io.F90 @@ -6,7 +6,9 @@ module FV3GFS_sfc_io register_variable_attribute, register_field, & read_restart, write_restart, write_data, & get_global_io_domain_indices, variable_exists - use FV3GFS_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data, GFS_Data_transfer + use FV3GFS_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data, GFS_Data_transfer, & + create_2d_field_and_add_to_bundle, create_3d_field_and_add_to_bundle, & + add_zaxis_to_field use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys use GFS_restart, only: GFS_restart_type use mpp_mod, only: mpp_error, mpp_pe, mpp_root_pe, & @@ -66,6 +68,8 @@ module FV3GFS_sfc_io procedure, public :: write_axes => Sfc_io_write_axes procedure, public :: register_2d_fields => Sfc_io_register_2d_fields procedure, public :: register_3d_fields => Sfc_io_register_3d_fields + procedure, public :: bundle_2d_fields => Sfc_io_bundle_2d_fields + procedure, public :: bundle_3d_fields => Sfc_io_bundle_3d_fields procedure, public :: fill_2d_names => Sfc_io_fill_2d_names procedure, public :: fill_3d_names => Sfc_io_fill_3d_names procedure, public :: init_fields => Sfc_io_init_fields @@ -1059,7 +1063,7 @@ subroutine Sfc_io_transfer(sfc, reading, Model, Atm_block, Sfcprop, warm_start, call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc%var3,Sfcprop(nb)%stc) call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc%var3,Sfcprop(nb)%smc) call GFS_Data_transfer(reading,ii1,jj1,isc,jsc,nt,1,Model%lsoil,sfc%var3,Sfcprop(nb)%slc) - + if (Model%lsm == Model%lsm_noahmp) then ! These use weird indexing which is lost during a Fortran @@ -1455,4 +1459,94 @@ subroutine Sfc_io_final(sfc) #undef IF_ASSOC_DEALLOC_NULL end subroutine Sfc_io_final + + subroutine Sfc_io_bundle_2d_fields(sfc, bundle, grid, Model, outputfile) + use esmf + use GFS_typedefs, only: GFS_control_type + implicit none + class(Sfc_io_data_type) :: sfc + type(ESMF_FieldBundle),intent(inout) :: bundle + type(ESMF_Grid),intent(inout) :: grid + type(GFS_control_type), intent(in) :: Model + character(*), intent(in) :: outputfile + + real(kind_phys),dimension(:,:),pointer :: temp_r2d + integer :: num + + if (.not. associated(sfc%var2)) then + write(0,*)'ERROR sfc%var2, NOT associated' + return + endif + if (.not. associated(sfc%name2)) then + write(0,*)'ERROR sfc%name2 NOT associated' + return + endif + + do num = 1,sfc%nvar2m + temp_r2d => sfc%var2(:,:,num) + call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc%name2(num)), outputfile, grid, bundle) + enddo + + if (Model%nstf_name(1) > 0) then + do num = sfc%nvar2m+1,sfc%nvar2m+sfc%nvar2o + temp_r2d => sfc%var2(:,:,num) + call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc%name2(num)), outputfile, grid, bundle) + enddo + endif + + if (Model%lsm == Model%lsm_ruc) then ! sfc%nvar2mp =0 + do num = sfc%nvar2m+sfc%nvar2o+1, sfc%nvar2m+sfc%nvar2o+sfc%nvar2r + temp_r2d => sfc%var2(:,:,num) + call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc%name2(num)), outputfile, grid, bundle) + enddo + else if (Model%lsm == Model%lsm_noahmp) then ! sfc%nvar2r =0 + do num = sfc%nvar2m+sfc%nvar2o+1,sfc%nvar2m+sfc%nvar2o+sfc%nvar2mp + temp_r2d => sfc%var2(:,:,num) + call create_2d_field_and_add_to_bundle(temp_r2d, trim(sfc%name2(num)), outputfile, grid, bundle) + enddo + endif + end subroutine Sfc_io_bundle_2d_fields + + subroutine Sfc_io_bundle_3d_fields(sfc, bundle, grid, Model, outputfile) + use esmf + use GFS_typedefs, only: GFS_control_type + implicit none + class(Sfc_io_data_type) :: sfc + type(ESMF_FieldBundle),intent(inout) :: bundle + type(ESMF_Grid),intent(inout) :: grid + type(GFS_control_type), intent(in) :: Model + character(*), intent(in) :: outputfile + + real(kind_phys),dimension(:,:,:),pointer :: temp_r3d + integer :: num + + temp_r3d => sfc%var3ice(:,:,:) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(0)), "zaxis_1", Model%kice, trim(outputfile), grid, bundle) + + if(Model%lsm == Model%lsm_ruc) then + do num = 1,sfc%nvar3 + temp_r3d => sfc%var3(:,:,:,num) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_1", Model%kice, trim(outputfile), grid, bundle) + enddo + else + do num = 1,sfc%nvar3 + temp_r3d => sfc%var3(:,:,:,num) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_2", Model%lsoil, trim(outputfile), grid, bundle) + enddo + endif + + if (Model%lsm == Model%lsm_noahmp) then + do num = sfc%nvar3+1,sfc%nvar3+3 + temp_r3d => sfc%var3sn(:,:,:,num) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_3", 3, trim(outputfile), grid, bundle) + enddo + + temp_r3d => sfc%var3eq(:,:,:,7) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(7)), "zaxis_2", Model%lsoil, trim(outputfile), grid, bundle) + + temp_r3d => sfc%var3zn(:,:,:,8) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(8)), "zaxis_4", 7, trim(outputfile), grid, bundle) + endif ! lsm = lsm_noahmp + + end subroutine Sfc_io_bundle_3d_fields end module FV3GFS_sfc_io From ed919fe12703e0e8c25308e20d11cc06196e5ea3 Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Tue, 23 May 2023 07:14:45 +0000 Subject: [PATCH 18/27] consistent naming and clm lake quilt restart --- io/FV3GFS_clm_lake_io.F90 | 72 +++++++++++++++++++++++++++++++++------ io/FV3GFS_io.F90 | 14 ++++---- io/FV3GFS_restart_io.F90 | 13 +++++++ io/FV3GFS_rrfs_sd_io.F90 | 16 ++++----- 4 files changed, 90 insertions(+), 25 deletions(-) diff --git a/io/FV3GFS_clm_lake_io.F90 b/io/FV3GFS_clm_lake_io.F90 index 6a47f3ab6..6dfba2027 100644 --- a/io/FV3GFS_clm_lake_io.F90 +++ b/io/FV3GFS_clm_lake_io.F90 @@ -1,4 +1,4 @@ -module clm_lake_io +module FV3GFS_clm_lake_io use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, & GFS_data_type, kind_phys use GFS_restart, only: GFS_restart_type @@ -10,6 +10,7 @@ module clm_lake_io register_variable_attribute, register_field, & read_restart, write_restart, write_data, & get_global_io_domain_indices, variable_exists + use FV3GFS_common_io implicit none @@ -56,11 +57,14 @@ module clm_lake_io ! each axis, containing the appropriate information procedure, public :: write_axes => clm_lake_write_axes - ! copy_to_temporaries copies from Sfcprop to internal pointers (declared above) - procedure, public :: copy_to_temporaries => clm_lake_copy_to_temporaries + ! copy_from_grid copies from Sfcprop to internal pointers (declared above) + procedure, public :: copy_from_grid => clm_lake_copy_from_grid - ! copy_to_temporaries copies from internal pointers (declared above) to Sfcprop - procedure, public :: copy_from_temporaries => clm_lake_copy_from_temporaries + ! copy_from_grid copies from internal pointers (declared above) to Sfcprop + procedure, public :: copy_to_grid => clm_lake_copy_to_grid + + ! send field bundles in restart quilt server + procedure, public :: bundle_fields => clm_lake_bundle_fields ! A fortran 2003 compliant compiler will call clm_lake_final ! automatically when an object of this type goes out of @@ -181,7 +185,7 @@ subroutine clm_lake_write_axes(data, Model, Sfc_restart) call write_data(Sfc_restart, 'levsnowsoil1_clm_lake', levsnowsoil1_clm_lake) end subroutine clm_lake_write_axes - subroutine clm_lake_copy_to_temporaries(data, Model, Sfcprop, Atm_block) + subroutine clm_lake_copy_from_grid(data, Model, Atm_block, Sfcprop) ! Copies from Sfcprop variables to the corresponding data temporary variables. ! Terrible things will happen if you don't call data%allocate_data first. implicit none @@ -232,9 +236,9 @@ subroutine clm_lake_copy_to_temporaries(data, Model, Sfcprop, Atm_block) data%lake_sand3d(i,j,:) = Sfcprop(nb)%lake_sand3d(ix,:) enddo enddo - end subroutine clm_lake_copy_to_temporaries + end subroutine clm_lake_copy_from_grid - subroutine clm_lake_copy_from_temporaries(data, Model, Sfcprop, Atm_block) + subroutine clm_lake_copy_to_grid(data, Model, Atm_block, Sfcprop) ! Copies from data temporary variables to the corresponding Sfcprop variables. ! Terrible things will happen if you don't call data%allocate_data first. implicit none @@ -285,7 +289,7 @@ subroutine clm_lake_copy_from_temporaries(data, Model, Sfcprop, Atm_block) Sfcprop(nb)%lake_sand3d(ix,:) = data%lake_sand3d(i,j,:) enddo enddo - end subroutine clm_lake_copy_from_temporaries + end subroutine clm_lake_copy_to_grid subroutine clm_lake_register_fields(data, Sfc_restart) ! Registers all restart fields needed by the CLM Lake Model. @@ -372,6 +376,54 @@ subroutine clm_lake_register_fields(data, Sfc_restart) 'levsoil_clm_lake ', 'Time '/), is_optional=.true.) end subroutine clm_lake_register_fields + + subroutine clm_lake_bundle_fields(clm_lake, bundle, grid, Model, outputfile) + use esmf + use GFS_typedefs, only: GFS_control_type + implicit none + class(Clm_lake_data_type) :: clm_lake + type(ESMF_FieldBundle),intent(inout) :: bundle + type(ESMF_Grid),intent(inout) :: grid + type(GFS_control_type), intent(in) :: Model + character(*), intent(in) :: outputfile + + real(kind_phys),dimension(:,:),pointer :: temp_r2d + real(kind_phys),dimension(:,:,:),pointer :: temp_r3d + integer :: num + + ! Register 2D fields + call create_2d_field_and_add_to_bundle(clm_lake%T_snow, "T_snow", trim(outputfile), grid, bundle) + call create_2d_field_and_add_to_bundle(clm_lake%T_ice, 'T_ice', trim(outputfile), grid, bundle) + call create_2d_field_and_add_to_bundle(clm_lake%lake_snl2d, "lake_snl2d", trim(outputfile), grid, bundle) + call create_2d_field_and_add_to_bundle(clm_lake%lake_h2osno2d, "lake_h2osno2d", trim(outputfile), grid, bundle) + call create_2d_field_and_add_to_bundle(clm_lake%lake_tsfc, "lake_tsfc", trim(outputfile), grid, bundle) + call create_2d_field_and_add_to_bundle(clm_lake%lake_savedtke12d, "lake_savedtke12d", trim(outputfile), grid, bundle) + call create_2d_field_and_add_to_bundle(clm_lake%lake_sndpth2d, "lake_sndpth2d", trim(outputfile), grid, bundle) + call create_2d_field_and_add_to_bundle(clm_lake%clm_lakedepth, "clm_lakedepth", trim(outputfile), grid, bundle) + call create_2d_field_and_add_to_bundle(clm_lake%clm_lake_initialized, "clm_lake_initialized", trim(outputfile), grid, bundle) + + ! Register 3D fields + call create_3d_field_and_add_to_bundle(clm_lake%lake_z3d, 'lake_z3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_dz3d, 'lake_dz3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_soil_watsat3d, 'lake_soil_watsat3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_csol3d, 'lake_csol3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_soil_tkmg3d, 'lake_soil_tkmg3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_soil_tkdry3d, 'lake_soil_tkdry3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_soil_tksatu3d, 'lake_soil_tksatu3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_snow_z3d, 'lake_snow_z3d', 'levsnowsoil1_clm_lake', Model%nlevsnowsoil1_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_snow_dz3d, 'lake_snow_dz3d', 'levsnowsoil1_clm_lake', Model%nlevsnowsoil1_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_snow_zi3d, 'lake_snow_zi3d', 'levsnowsoil_clm_lake', Model%nlevsnowsoil_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_h2osoi_vol3d, 'lake_h2osoi_vol3d', 'levsnowsoil1_clm_lake', Model%nlevsnowsoil1_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_h2osoi_liq3d, 'lake_h2osoi_liq3d', 'levsnowsoil1_clm_lake', Model%nlevsnowsoil1_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_h2osoi_ice3d, 'lake_h2osoi_ice3d', 'levsnowsoil1_clm_lake', Model%nlevsnowsoil1_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_t_soisno3d, 'lake_t_soisno3d', 'levsnowsoil1_clm_lake', Model%nlevsnowsoil1_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_t_lake3d, 'lake_t_lake3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_icefrac3d, 'lake_icefrac3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_clay3d, 'lake_clay3d', 'levsoil_clm_lake', Model%nlevsoil_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_sand3d, 'lake_sand3d', 'levsoil_clm_lake', Model%nlevsoil_clm_lake, trim(outputfile), grid, bundle) + + end subroutine Clm_lake_bundle_fields + subroutine clm_lake_final(data) ! Final routine for clm_lake_data_type, called automatically when ! an object of that type goes out of scope. This is simply a @@ -429,4 +481,4 @@ subroutine clm_lake_deallocate_data(data) #undef IF_ASSOC_DEALLOC_NULL end subroutine clm_lake_deallocate_data -end module clm_lake_io +end module FV3GFS_clm_lake_io diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index 43db1cb04..55901cb37 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -33,7 +33,7 @@ module FV3GFS_io_mod use diag_util_mod, only: find_input_field use constants_mod, only: grav, rdgas use physcons, only: con_tice !saltwater freezing temp (K) - use clm_lake_io, only: clm_lake_data_type + use FV3GFS_clm_lake_io, only: clm_lake_data_type ! !--- GFS_typedefs use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, & @@ -709,14 +709,14 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta ! Tell CLM Lake to allocate data, and register its axes and fields if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then call clm_lake%allocate_data(Model) - call clm_lake%copy_to_temporaries(Model,Sfcprop,Atm_block) + call clm_lake%copy_from_grid(Model,Atm_block,Sfcprop) call clm_lake%register_axes(Model, Sfc_restart) call clm_lake%register_fields(Sfc_restart) endif if(Model%rrfs_sd) then call rrfs_sd_state%allocate_data(Model) - call rrfs_sd_state%fill_data(Model, Sfcprop, Atm_block) + call rrfs_sd_state%fill_data(Model, Atm_block, Sfcprop) call rrfs_sd_state%register_axis(Model, Sfc_restart) call rrfs_sd_state%register_fields(Sfc_restart) endif @@ -735,11 +735,11 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta ! Tell clm_lake to copy data to temporary arrays if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then - call clm_lake%copy_from_temporaries(Model,Sfcprop,Atm_block) + call clm_lake%copy_to_grid(Model,Atm_block,Sfcprop) endif if(Model%rrfs_sd) then - call rrfs_sd_state%copy_from_temporaries(Model,Sfcprop,Atm_block) + call rrfs_sd_state%copy_to_grid(Model,Atm_block,Sfcprop) end if ! write(0,*)' stype read in min,max=',minval(sfc%var2(:,:,35)),maxval(sfc%var2(:,:,35)),' sfc%name2=',sfc%name2(35) @@ -862,11 +862,11 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta ! Tell clm_lake to copy Sfcprop data to its internal temporary arrays. if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then - call clm_lake%copy_to_temporaries(Model,Sfcprop,Atm_block) + call clm_lake%copy_from_grid(Model,Atm_block,Sfcprop) endif if(Model%rrfs_sd) then - call rrfs_sd_state%copy_to_temporaries(Model,Sfcprop,Atm_block) + call rrfs_sd_state%copy_from_grid(Model,Atm_block,Sfcprop) endif call sfc%copy_from_grid(Model, Atm_block, Sfcprop) diff --git a/io/FV3GFS_restart_io.F90 b/io/FV3GFS_restart_io.F90 index 043e323df..317069acd 100644 --- a/io/FV3GFS_restart_io.F90 +++ b/io/FV3GFS_restart_io.F90 @@ -7,6 +7,7 @@ module FV3GFS_restart_io_mod use FV3GFS_sfc_io use FV3GFS_common_io, only: create_2d_field_and_add_to_bundle, & create_3d_field_and_add_to_bundle, add_zaxis_to_field + use FV3GFS_clm_lake_io implicit none private @@ -19,6 +20,7 @@ module FV3GFS_restart_io_mod real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: phy_var3 character(len=32),dimension(:),allocatable :: phy_var2_names, phy_var3_names + type(clm_lake_data_type) :: clm_lake type(Sfc_io_data_type) :: sfc type(ESMF_FieldBundle) :: phy_bundle, sfc_bundle @@ -76,6 +78,10 @@ subroutine FV3GFS_restart_register (Sfcprop, GFS_restart, Atm_block, Model) call sfc%fill_2d_names(Model, .true.) call sfc%fill_3d_names(Model, .true.) + if(Model%iopt_lake == 2 .and. Model%lkm > 0) then + call clm_lake%allocate_data(Model) + endif + end subroutine FV3GFS_restart_register subroutine fv_phy_restart_output(GFS_Restart, Atm_block) @@ -142,6 +148,9 @@ subroutine fv_sfc_restart_output(Sfcprop, Atm_block, Model) type(GFS_control_type), intent(in) :: Model call sfc%copy_from_grid(Model, Atm_block, Sfcprop) + if(Model%iopt_lake == 2 .and. Model%lkm > 0) then + call clm_lake%copy_from_grid(Model, Atm_block, Sfcprop) + endif end subroutine fv_sfc_restart_output @@ -233,6 +242,10 @@ subroutine fv_sfc_restart_bundle_setup(bundle, grid, Model, rc) call sfc%bundle_2d_fields(bundle, grid, Model, outputfile) call sfc%bundle_3d_fields(bundle, grid, Model, outputfile) + if(Model%iopt_lake == 2 .and. Model%lkm > 0) then + call clm_lake%bundle_fields(bundle, grid, Model, outputfile) + endif + end subroutine fv_sfc_restart_bundle_setup end module FV3GFS_restart_io_mod diff --git a/io/FV3GFS_rrfs_sd_io.F90 b/io/FV3GFS_rrfs_sd_io.F90 index f166668e4..27c95dc09 100644 --- a/io/FV3GFS_rrfs_sd_io.F90 +++ b/io/FV3GFS_rrfs_sd_io.F90 @@ -18,7 +18,7 @@ module rrfs_sd_io public :: rrfs_sd_state_type, rrfs_sd_state_register_axis, rrfs_sd_state_write_axis, & rrfs_sd_state_fill_data, rrfs_sd_state_register_fields, rrfs_sd_state_deallocate_data, & - rrfs_sd_state_copy_to_temporaries, rrfs_sd_state_copy_from_temporaries, & + rrfs_sd_state_copy_from_grid, rrfs_sd_state_copy_to_grid, & rrfs_sd_state_final public :: rrfs_sd_emissions_type, rrfs_sd_emissions_final, & @@ -45,8 +45,8 @@ module rrfs_sd_io procedure, public :: fill_data => rrfs_sd_state_fill_data ! fill data with default values procedure, public :: register_fields => rrfs_sd_state_register_fields ! register rrfs_sd fields procedure, public :: deallocate_data => rrfs_sd_state_deallocate_data ! deallocate pointers - procedure, public :: copy_to_temporaries => rrfs_sd_state_copy_to_temporaries ! Copy Sfcprop to arrays - procedure, public :: copy_from_temporaries => rrfs_sd_state_copy_from_temporaries ! Copy arrays to Sfcprop + procedure, public :: copy_from_grid => rrfs_sd_state_copy_from_grid ! Copy Sfcprop to arrays + procedure, public :: copy_to_grid => rrfs_sd_state_copy_to_grid ! Copy arrays to Sfcprop final :: rrfs_sd_state_final ! Destructor; calls deallocate_data end type rrfs_sd_state_type @@ -142,7 +142,7 @@ end subroutine rrfs_sd_state_allocate_data ! -------------------------------------------------------------------- - subroutine rrfs_sd_state_fill_data(data, Model, Sfcprop, Atm_block) + subroutine rrfs_sd_state_fill_data(data, Model, Atm_block, Sfcprop) ! Fills all temporary variables with default values. ! Terrible things will happen if you don't call data%allocate_data first. ! IMPORTANT: This must match the corresponding code in sfcprop_create in @@ -246,7 +246,7 @@ end subroutine rrfs_sd_state_deallocate_data ! -------------------------------------------------------------------- - subroutine rrfs_sd_state_copy_from_temporaries(data, Model, Sfcprop, Atm_block) + subroutine rrfs_sd_state_copy_to_grid(data, Model, Atm_block, Sfcprop) implicit none class(rrfs_sd_state_type) :: data type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) @@ -270,11 +270,11 @@ subroutine rrfs_sd_state_copy_from_temporaries(data, Model, Sfcprop, Atm_block) Sfcprop(nb)%fire_in(ix,:) = data%fire_in(i,j,:) enddo enddo - end subroutine rrfs_sd_state_copy_from_temporaries + end subroutine rrfs_sd_state_copy_to_grid ! -------------------------------------------------------------------- - subroutine rrfs_sd_state_copy_to_temporaries(data, Model, Sfcprop, Atm_block) + subroutine rrfs_sd_state_copy_from_grid(data, Model, Atm_block, Sfcprop) implicit none class(rrfs_sd_state_type) :: data type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) @@ -298,7 +298,7 @@ subroutine rrfs_sd_state_copy_to_temporaries(data, Model, Sfcprop, Atm_block) data%fire_in(i,j,:) = Sfcprop(nb)%fire_in(ix,:) enddo enddo - end subroutine rrfs_sd_state_copy_to_temporaries + end subroutine rrfs_sd_state_copy_from_grid ! -------------------------------------------------------------------- ! -- RRFS_SD_EMISSIONS IMPLEMENTATION -------------------------------- From 91b63c130c97867af4fd0aaafcdb2eb6eee3ebd5 Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Tue, 23 May 2023 18:45:06 +0000 Subject: [PATCH 19/27] rrfs sd restart in quilt (still under testing) --- io/FV3GFS_io.F90 | 4 ++-- io/FV3GFS_restart_io.F90 | 12 ++++++++++++ io/FV3GFS_rrfs_sd_io.F90 | 35 ++++++++++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/io/FV3GFS_io.F90 b/io/FV3GFS_io.F90 index 55901cb37..3291e815b 100644 --- a/io/FV3GFS_io.F90 +++ b/io/FV3GFS_io.F90 @@ -536,7 +536,7 @@ end subroutine FV3GFS_GFS_checksum ! !---------------------------------------------------------------------- subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) - use rrfs_sd_io + use FV3GFS_rrfs_sd_io implicit none !--- interface variable definitions type(GFS_sfcprop_type), intent(inout) :: Sfcprop(:) @@ -771,7 +771,7 @@ end subroutine sfc_prop_restart_read ! calls: register_restart_field, save_restart !---------------------------------------------------------------------- subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timestamp) - use rrfs_sd_io + use FV3GFS_rrfs_sd_io implicit none !--- interface variable definitions type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) diff --git a/io/FV3GFS_restart_io.F90 b/io/FV3GFS_restart_io.F90 index 317069acd..6b7b13cf1 100644 --- a/io/FV3GFS_restart_io.F90 +++ b/io/FV3GFS_restart_io.F90 @@ -7,6 +7,7 @@ module FV3GFS_restart_io_mod use FV3GFS_sfc_io use FV3GFS_common_io, only: create_2d_field_and_add_to_bundle, & create_3d_field_and_add_to_bundle, add_zaxis_to_field + use FV3GFS_rrfs_sd_io use FV3GFS_clm_lake_io implicit none @@ -20,6 +21,7 @@ module FV3GFS_restart_io_mod real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: phy_var3 character(len=32),dimension(:),allocatable :: phy_var2_names, phy_var3_names + type(rrfs_sd_state_type) :: rrfs_sd type(clm_lake_data_type) :: clm_lake type(Sfc_io_data_type) :: sfc type(ESMF_FieldBundle) :: phy_bundle, sfc_bundle @@ -82,6 +84,10 @@ subroutine FV3GFS_restart_register (Sfcprop, GFS_restart, Atm_block, Model) call clm_lake%allocate_data(Model) endif + if(Model%rrfs_sd) then + call rrfs_sd%allocate_data(Model) + endif + end subroutine FV3GFS_restart_register subroutine fv_phy_restart_output(GFS_Restart, Atm_block) @@ -151,6 +157,9 @@ subroutine fv_sfc_restart_output(Sfcprop, Atm_block, Model) if(Model%iopt_lake == 2 .and. Model%lkm > 0) then call clm_lake%copy_from_grid(Model, Atm_block, Sfcprop) endif + if(Model%rrfs_sd) then + call rrfs_sd%copy_from_grid(Model, Atm_block, Sfcprop) + endif end subroutine fv_sfc_restart_output @@ -245,6 +254,9 @@ subroutine fv_sfc_restart_bundle_setup(bundle, grid, Model, rc) if(Model%iopt_lake == 2 .and. Model%lkm > 0) then call clm_lake%bundle_fields(bundle, grid, Model, outputfile) endif + if(Model%rrfs_sd) then + call rrfs_sd%bundle_fields(bundle, grid, Model, outputfile) + endif end subroutine fv_sfc_restart_bundle_setup diff --git a/io/FV3GFS_rrfs_sd_io.F90 b/io/FV3GFS_rrfs_sd_io.F90 index 27c95dc09..099eaa28d 100644 --- a/io/FV3GFS_rrfs_sd_io.F90 +++ b/io/FV3GFS_rrfs_sd_io.F90 @@ -1,4 +1,4 @@ -module rrfs_sd_io +module FV3GFS_rrfs_sd_io use block_control_mod, only: block_control_type use fms2_io_mod, only: FmsNetcdfDomainFile_t, unlimited, & open_file, close_file, & @@ -10,7 +10,8 @@ module rrfs_sd_io GFS_data_type, kind_phys use GFS_restart, only: GFS_restart_type use GFS_diagnostics, only: GFS_externaldiag_type - use FV3GFS_common_io, only: get_nx_ny_from_atm + use FV3GFS_common_io, only: get_nx_ny_from_atm, create_2d_field_and_add_to_bundle, & + create_3d_field_and_add_to_bundle, add_zaxis_to_field implicit none @@ -47,6 +48,7 @@ module rrfs_sd_io procedure, public :: deallocate_data => rrfs_sd_state_deallocate_data ! deallocate pointers procedure, public :: copy_from_grid => rrfs_sd_state_copy_from_grid ! Copy Sfcprop to arrays procedure, public :: copy_to_grid => rrfs_sd_state_copy_to_grid ! Copy arrays to Sfcprop + procedure, public :: bundle_fields => rrfs_sd_bundle_fields ! Point esmf bundles to arrays final :: rrfs_sd_state_final ! Destructor; calls deallocate_data end type rrfs_sd_state_type @@ -206,6 +208,33 @@ end subroutine rrfs_sd_state_register_fields ! -------------------------------------------------------------------- + subroutine rrfs_sd_bundle_fields(data, bundle, grid, Model, outputfile) + use esmf + use GFS_typedefs, only: GFS_control_type + ! Registers all restart fields needed by the RRFS-SD + ! Terrible things will happen if you don't call data%allocate_data + ! and data%register_axes first. + implicit none + class(rrfs_sd_state_type) :: data + type(ESMF_FieldBundle),intent(inout) :: bundle + type(ESMF_Grid),intent(inout) :: grid + type(GFS_control_type), intent(in) :: Model + character(*), intent(in) :: outputfile + + ! Register 2D fields + call create_2d_field_and_add_to_bundle(data%emdust, "emdust", trim(outputfile), grid, bundle) + call create_2d_field_and_add_to_bundle(data%emseas, "emseas", trim(outputfile), grid, bundle) + call create_2d_field_and_add_to_bundle(data%emanoc, "emanoc", trim(outputfile), grid, bundle) + call create_2d_field_and_add_to_bundle(data%fhist, "fhist", trim(outputfile), grid, bundle) + call create_2d_field_and_add_to_bundle(data%coef_bb_dc, "coef_bb_dc", trim(outputfile), grid, bundle) + + ! Register 3D field + call create_3d_field_and_add_to_bundle(data%fire_in, 'fire_in', 'fire_aux_data_levels', & + Model%fire_aux_data_levels, trim(outputfile), grid, bundle) + end subroutine rrfs_sd_bundle_fields + + ! -------------------------------------------------------------------- + subroutine rrfs_sd_state_final(data) ! Final routine for rrfs_sd_state_type, called automatically when ! an object of that type goes out of scope. This is a wrapper @@ -542,4 +571,4 @@ subroutine rrfs_sd_emissions_final(data) #undef IF_ASSOC_DEALLOC_NULL end subroutine rrfs_sd_emissions_final -end module rrfs_sd_io +end module FV3GFS_rrfs_sd_io From 63de19239752dc3b2d430e8e0dcdd79ff6df2e99 Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Wed, 24 May 2023 17:26:16 +0000 Subject: [PATCH 20/27] explicitly write axis values (from DusanJovic-NOAA), and clean up code --- io/FV3GFS_clm_lake_io.F90 | 389 ++++++++++++++++++++------------------ io/FV3GFS_common_io.F90 | 20 +- io/FV3GFS_restart_io.F90 | 8 +- io/FV3GFS_rrfs_sd_io.F90 | 31 +-- io/FV3GFS_sfc_io.F90 | 35 +++- 5 files changed, 259 insertions(+), 224 deletions(-) diff --git a/io/FV3GFS_clm_lake_io.F90 b/io/FV3GFS_clm_lake_io.F90 index 6dfba2027..84d2de08d 100644 --- a/io/FV3GFS_clm_lake_io.F90 +++ b/io/FV3GFS_clm_lake_io.F90 @@ -38,6 +38,10 @@ module FV3GFS_clm_lake_io lake_h2osoi_ice3d=>null(), lake_t_soisno3d=>null(), lake_t_lake3d=>null(), & lake_icefrac3d=>null(), lake_clay3d=>null(), lake_sand3d=>null() + ! Axis indices in 1-based array, containing non-1-based indices + real(kind_phys), pointer, private, dimension(:) :: & + levlake_clm_lake, levsoil_clm_lake, levsnowsoil_clm_lake, & + levsnowsoil1_clm_lake contains ! register_axes calls registers_axis on Sfc_restart for all required axes @@ -75,77 +79,86 @@ module FV3GFS_clm_lake_io end type clm_lake_data_type CONTAINS - subroutine clm_lake_allocate_data(data,Model) + subroutine clm_lake_allocate_data(clm_lake,Model) ! Deallocate all data, and reallocate to the size specified in Model implicit none - class(clm_lake_data_type) :: data + class(clm_lake_data_type) :: clm_lake type(GFS_control_type), intent(in) :: Model - integer :: nx, ny - call data%deallocate_data + integer :: nx, ny, i + call clm_lake%deallocate_data nx=Model%nx ny=Model%ny - allocate(data%T_snow(nx,ny)) - allocate(data%T_ice(nx,ny)) - allocate(data%lake_snl2d(nx,ny)) - allocate(data%lake_h2osno2d(nx,ny)) - allocate(data%lake_tsfc(nx,ny)) - allocate(data%lake_savedtke12d(nx,ny)) - allocate(data%lake_sndpth2d(nx,ny)) - allocate(data%clm_lakedepth(nx,ny)) - allocate(data%clm_lake_initialized(nx,ny)) + allocate(clm_lake%T_snow(nx,ny)) + allocate(clm_lake%T_ice(nx,ny)) + allocate(clm_lake%lake_snl2d(nx,ny)) + allocate(clm_lake%lake_h2osno2d(nx,ny)) + allocate(clm_lake%lake_tsfc(nx,ny)) + allocate(clm_lake%lake_savedtke12d(nx,ny)) + allocate(clm_lake%lake_sndpth2d(nx,ny)) + allocate(clm_lake%clm_lakedepth(nx,ny)) + allocate(clm_lake%clm_lake_initialized(nx,ny)) - allocate(data%lake_z3d(nx,ny,Model%nlevlake_clm_lake)) - allocate(data%lake_dz3d(nx,ny,Model%nlevlake_clm_lake)) - allocate(data%lake_soil_watsat3d(nx,ny,Model%nlevlake_clm_lake)) - allocate(data%lake_csol3d(nx,ny,Model%nlevlake_clm_lake)) - allocate(data%lake_soil_tkmg3d(nx,ny,Model%nlevlake_clm_lake)) - allocate(data%lake_soil_tkdry3d(nx,ny,Model%nlevlake_clm_lake)) - allocate(data%lake_soil_tksatu3d(nx,ny,Model%nlevlake_clm_lake)) - allocate(data%lake_snow_z3d(nx,ny,Model%nlevsnowsoil1_clm_lake)) - allocate(data%lake_snow_dz3d(nx,ny,Model%nlevsnowsoil1_clm_lake)) - allocate(data%lake_snow_zi3d(nx,ny,Model%nlevsnowsoil_clm_lake)) - allocate(data%lake_h2osoi_vol3d(nx,ny,Model%nlevsnowsoil1_clm_lake)) - allocate(data%lake_h2osoi_liq3d(nx,ny,Model%nlevsnowsoil1_clm_lake)) - allocate(data%lake_h2osoi_ice3d(nx,ny,Model%nlevsnowsoil1_clm_lake)) - allocate(data%lake_t_soisno3d(nx,ny,Model%nlevsnowsoil1_clm_lake)) - allocate(data%lake_t_lake3d(nx,ny,Model%nlevlake_clm_lake)) - allocate(data%lake_icefrac3d(nx,ny,Model%nlevlake_clm_lake)) - allocate(data%lake_clay3d(nx,ny,Model%nlevsoil_clm_lake)) - allocate(data%lake_sand3d(nx,ny,Model%nlevsoil_clm_lake)) + allocate(clm_lake%lake_z3d(nx,ny,Model%nlevlake_clm_lake)) + allocate(clm_lake%lake_dz3d(nx,ny,Model%nlevlake_clm_lake)) + allocate(clm_lake%lake_soil_watsat3d(nx,ny,Model%nlevlake_clm_lake)) + allocate(clm_lake%lake_csol3d(nx,ny,Model%nlevlake_clm_lake)) + allocate(clm_lake%lake_soil_tkmg3d(nx,ny,Model%nlevlake_clm_lake)) + allocate(clm_lake%lake_soil_tkdry3d(nx,ny,Model%nlevlake_clm_lake)) + allocate(clm_lake%lake_soil_tksatu3d(nx,ny,Model%nlevlake_clm_lake)) + allocate(clm_lake%lake_snow_z3d(nx,ny,Model%nlevsnowsoil1_clm_lake)) + allocate(clm_lake%lake_snow_dz3d(nx,ny,Model%nlevsnowsoil1_clm_lake)) + allocate(clm_lake%lake_snow_zi3d(nx,ny,Model%nlevsnowsoil_clm_lake)) + allocate(clm_lake%lake_h2osoi_vol3d(nx,ny,Model%nlevsnowsoil1_clm_lake)) + allocate(clm_lake%lake_h2osoi_liq3d(nx,ny,Model%nlevsnowsoil1_clm_lake)) + allocate(clm_lake%lake_h2osoi_ice3d(nx,ny,Model%nlevsnowsoil1_clm_lake)) + allocate(clm_lake%lake_t_soisno3d(nx,ny,Model%nlevsnowsoil1_clm_lake)) + allocate(clm_lake%lake_t_lake3d(nx,ny,Model%nlevlake_clm_lake)) + allocate(clm_lake%lake_icefrac3d(nx,ny,Model%nlevlake_clm_lake)) + allocate(clm_lake%lake_clay3d(nx,ny,Model%nlevsoil_clm_lake)) + allocate(clm_lake%lake_sand3d(nx,ny,Model%nlevsoil_clm_lake)) + + allocate(clm_lake%levlake_clm_lake(Model%nlevlake_clm_lake)) + allocate(clm_lake%levsoil_clm_lake(Model%nlevsoil_clm_lake)) + allocate(clm_lake%levsnowsoil_clm_lake(Model%nlevsnowsoil_clm_lake)) + allocate(clm_lake%levsnowsoil1_clm_lake(Model%nlevsnowsoil1_clm_lake)) + + do i=1,Model%nlevlake_clm_lake + clm_lake%levlake_clm_lake(i) = i + enddo + do i=1,Model%nlevsoil_clm_lake + clm_lake%levsoil_clm_lake(i) = i + enddo + do i=-Model%nlevsnow_clm_lake,Model%nlevsoil_clm_lake + clm_lake%levsnowsoil_clm_lake(i+Model%nlevsnow_clm_lake+1) = i + enddo + do i=-Model%nlevsnow_clm_lake+1,Model%nlevsoil_clm_lake + clm_lake%levsnowsoil1_clm_lake(i+Model%nlevsnow_clm_lake) = i + enddo end subroutine clm_lake_allocate_data - subroutine clm_lake_register_axes(data,Model,Sfc_restart) + subroutine clm_lake_register_axes(clm_lake,Model,Sfc_restart) ! Register all five axes needed by CLM Lake restart data implicit none - class(clm_lake_data_type) :: data + class(clm_lake_data_type) :: clm_lake type(GFS_control_type), intent(in) :: Model type(FmsNetcdfDomainFile_t) :: Sfc_restart - call register_axis(Sfc_restart, 'levlake_clm_lake', dimension_length=Model%nlevlake_clm_lake) + call register_axis(Sfc_restart, 'levlake_clm_lake', dimension_length=Model%nlevlake_clm_lake) call register_axis(Sfc_restart, 'levsoil_clm_lake', dimension_length=Model%nlevsoil_clm_lake) - - call register_axis(Sfc_restart, 'levsnow_clm_lake', dimension_length=Model%nlevsnow_clm_lake) - call register_axis(Sfc_restart, 'levsnowsoil_clm_lake', dimension_length=Model%nlevsnowsoil_clm_lake) - call register_axis(Sfc_restart, 'levsnowsoil1_clm_lake', dimension_length=Model%nlevsnowsoil1_clm_lake) end subroutine clm_lake_register_axes - subroutine clm_lake_write_axes(data, Model, Sfc_restart) + subroutine clm_lake_write_axes(clm_lake, Model, Sfc_restart) ! Create variables with the name name as each clm_lake axis, and ! fill the variable with the appropriate indices implicit none - class(clm_lake_data_type) :: data + class(clm_lake_data_type) :: clm_lake type(GFS_control_type), intent(in) :: Model type(FmsNetcdfDomainFile_t) :: Sfc_restart - real(kind_phys) :: levlake_clm_lake(Model%nlevlake_clm_lake) - real(kind_phys) :: levsoil_clm_lake(Model%nlevsoil_clm_lake) - real(kind_phys) :: levsnow_clm_lake(Model%nlevsnow_clm_lake) - real(kind_phys) :: levsnowsoil_clm_lake(Model%nlevsnowsoil_clm_lake) - real(kind_phys) :: levsnowsoil1_clm_lake(Model%nlevsnowsoil1_clm_lake) integer :: i call register_field(Sfc_restart, 'levlake_clm_lake', 'double', (/'levlake_clm_lake'/)) call register_variable_attribute(Sfc_restart, 'levlake_clm_lake', 'cartesian_axis' ,'Z', str_len=1) @@ -153,43 +166,23 @@ subroutine clm_lake_write_axes(data, Model, Sfc_restart) call register_field(Sfc_restart, 'levsoil_clm_lake', 'double', (/'levsoil_clm_lake'/)) call register_variable_attribute(Sfc_restart, 'levsoil_clm_lake', 'cartesian_axis' ,'Z', str_len=1) - call register_field(Sfc_restart, 'levsnow_clm_lake', 'double', (/'levsnow_clm_lake'/)) - call register_variable_attribute(Sfc_restart, 'levsnow_clm_lake', 'cartesian_axis' ,'Z', str_len=1) - call register_field(Sfc_restart, 'levsnowsoil_clm_lake', 'double', (/'levsnowsoil_clm_lake'/)) call register_variable_attribute(Sfc_restart, 'levsnowsoil_clm_lake', 'cartesian_axis' ,'Z', str_len=1) call register_field(Sfc_restart, 'levsnowsoil1_clm_lake', 'double', (/'levsnowsoil1_clm_lake'/)) call register_variable_attribute(Sfc_restart, 'levsnowsoil1_clm_lake', 'cartesian_axis' ,'Z', str_len=1) - do i=1,Model%nlevlake_clm_lake - levlake_clm_lake(i) = i - enddo - do i=1,Model%nlevsoil_clm_lake - levsoil_clm_lake(i) = i - enddo - do i=1,Model%nlevsnow_clm_lake - levsnow_clm_lake(i) = i - enddo - do i=-Model%nlevsnow_clm_lake,Model%nlevsoil_clm_lake - levsnowsoil_clm_lake(i+Model%nlevsnow_clm_lake+1) = i - enddo - do i=-Model%nlevsnow_clm_lake+1,Model%nlevsoil_clm_lake - levsnowsoil1_clm_lake(i+Model%nlevsnow_clm_lake) = i - enddo - - call write_data(Sfc_restart, 'levlake_clm_lake', levlake_clm_lake) - call write_data(Sfc_restart, 'levsoil_clm_lake', levsoil_clm_lake) - call write_data(Sfc_restart, 'levsnow_clm_lake', levsnow_clm_lake) - call write_data(Sfc_restart, 'levsnowsoil_clm_lake', levsnowsoil_clm_lake) - call write_data(Sfc_restart, 'levsnowsoil1_clm_lake', levsnowsoil1_clm_lake) + call write_data(Sfc_restart, 'levlake_clm_lake', clm_lake%levlake_clm_lake) + call write_data(Sfc_restart, 'levsoil_clm_lake', clm_lake%levsoil_clm_lake) + call write_data(Sfc_restart, 'levsnowsoil_clm_lake', clm_lake%levsnowsoil_clm_lake) + call write_data(Sfc_restart, 'levsnowsoil1_clm_lake', clm_lake%levsnowsoil1_clm_lake) end subroutine clm_lake_write_axes - subroutine clm_lake_copy_from_grid(data, Model, Atm_block, Sfcprop) + subroutine clm_lake_copy_from_grid(clm_lake, Model, Atm_block, Sfcprop) ! Copies from Sfcprop variables to the corresponding data temporary variables. - ! Terrible things will happen if you don't call data%allocate_data first. + ! Terrible things will happen if you don't call clm_lake%allocate_data first. implicit none - class(clm_lake_data_type) :: data + class(clm_lake_data_type) :: clm_lake type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) type(GFS_control_type), intent(in) :: Model type(block_control_type), intent(in) :: Atm_block @@ -206,43 +199,43 @@ subroutine clm_lake_copy_from_grid(data, Model, Atm_block, Sfcprop) i = Atm_block%index(nb)%ii(ix) - isc + 1 j = Atm_block%index(nb)%jj(ix) - jsc + 1 - data%T_snow(i,j) = Sfcprop(nb)%T_snow(ix) - data%T_ice(i,j) = Sfcprop(nb)%T_ice(ix) - data%lake_snl2d(i,j) = Sfcprop(nb)%lake_snl2d(ix) - data%lake_h2osno2d(i,j) = Sfcprop(nb)%lake_h2osno2d(ix) - data%lake_tsfc(i,j) = Sfcprop(nb)%lake_tsfc(ix) - data%lake_savedtke12d(i,j) = Sfcprop(nb)%lake_savedtke12d(ix) - data%lake_sndpth2d(i,j) = Sfcprop(nb)%lake_sndpth2d(ix) - data%clm_lakedepth(i,j) = Sfcprop(nb)%clm_lakedepth(ix) - data%clm_lake_initialized(i,j) = Sfcprop(nb)%clm_lake_initialized(ix) - - data%lake_z3d(i,j,:) = Sfcprop(nb)%lake_z3d(ix,:) - data%lake_dz3d(i,j,:) = Sfcprop(nb)%lake_dz3d(ix,:) - data%lake_soil_watsat3d(i,j,:) = Sfcprop(nb)%lake_soil_watsat3d(ix,:) - data%lake_csol3d(i,j,:) = Sfcprop(nb)%lake_csol3d(ix,:) - data%lake_soil_tkmg3d(i,j,:) = Sfcprop(nb)%lake_soil_tkmg3d(ix,:) - data%lake_soil_tkdry3d(i,j,:) = Sfcprop(nb)%lake_soil_tkdry3d(ix,:) - data%lake_soil_tksatu3d(i,j,:) = Sfcprop(nb)%lake_soil_tksatu3d(ix,:) - data%lake_snow_z3d(i,j,:) = Sfcprop(nb)%lake_snow_z3d(ix,:) - data%lake_snow_dz3d(i,j,:) = Sfcprop(nb)%lake_snow_dz3d(ix,:) - data%lake_snow_zi3d(i,j,:) = Sfcprop(nb)%lake_snow_zi3d(ix,:) - data%lake_h2osoi_vol3d(i,j,:) = Sfcprop(nb)%lake_h2osoi_vol3d(ix,:) - data%lake_h2osoi_liq3d(i,j,:) = Sfcprop(nb)%lake_h2osoi_liq3d(ix,:) - data%lake_h2osoi_ice3d(i,j,:) = Sfcprop(nb)%lake_h2osoi_ice3d(ix,:) - data%lake_t_soisno3d(i,j,:) = Sfcprop(nb)%lake_t_soisno3d(ix,:) - data%lake_t_lake3d(i,j,:) = Sfcprop(nb)%lake_t_lake3d(ix,:) - data%lake_icefrac3d(i,j,:) = Sfcprop(nb)%lake_icefrac3d(ix,:) - data%lake_clay3d(i,j,:) = Sfcprop(nb)%lake_clay3d(ix,:) - data%lake_sand3d(i,j,:) = Sfcprop(nb)%lake_sand3d(ix,:) + clm_lake%T_snow(i,j) = Sfcprop(nb)%T_snow(ix) + clm_lake%T_ice(i,j) = Sfcprop(nb)%T_ice(ix) + clm_lake%lake_snl2d(i,j) = Sfcprop(nb)%lake_snl2d(ix) + clm_lake%lake_h2osno2d(i,j) = Sfcprop(nb)%lake_h2osno2d(ix) + clm_lake%lake_tsfc(i,j) = Sfcprop(nb)%lake_tsfc(ix) + clm_lake%lake_savedtke12d(i,j) = Sfcprop(nb)%lake_savedtke12d(ix) + clm_lake%lake_sndpth2d(i,j) = Sfcprop(nb)%lake_sndpth2d(ix) + clm_lake%clm_lakedepth(i,j) = Sfcprop(nb)%clm_lakedepth(ix) + clm_lake%clm_lake_initialized(i,j) = Sfcprop(nb)%clm_lake_initialized(ix) + + clm_lake%lake_z3d(i,j,:) = Sfcprop(nb)%lake_z3d(ix,:) + clm_lake%lake_dz3d(i,j,:) = Sfcprop(nb)%lake_dz3d(ix,:) + clm_lake%lake_soil_watsat3d(i,j,:) = Sfcprop(nb)%lake_soil_watsat3d(ix,:) + clm_lake%lake_csol3d(i,j,:) = Sfcprop(nb)%lake_csol3d(ix,:) + clm_lake%lake_soil_tkmg3d(i,j,:) = Sfcprop(nb)%lake_soil_tkmg3d(ix,:) + clm_lake%lake_soil_tkdry3d(i,j,:) = Sfcprop(nb)%lake_soil_tkdry3d(ix,:) + clm_lake%lake_soil_tksatu3d(i,j,:) = Sfcprop(nb)%lake_soil_tksatu3d(ix,:) + clm_lake%lake_snow_z3d(i,j,:) = Sfcprop(nb)%lake_snow_z3d(ix,:) + clm_lake%lake_snow_dz3d(i,j,:) = Sfcprop(nb)%lake_snow_dz3d(ix,:) + clm_lake%lake_snow_zi3d(i,j,:) = Sfcprop(nb)%lake_snow_zi3d(ix,:) + clm_lake%lake_h2osoi_vol3d(i,j,:) = Sfcprop(nb)%lake_h2osoi_vol3d(ix,:) + clm_lake%lake_h2osoi_liq3d(i,j,:) = Sfcprop(nb)%lake_h2osoi_liq3d(ix,:) + clm_lake%lake_h2osoi_ice3d(i,j,:) = Sfcprop(nb)%lake_h2osoi_ice3d(ix,:) + clm_lake%lake_t_soisno3d(i,j,:) = Sfcprop(nb)%lake_t_soisno3d(ix,:) + clm_lake%lake_t_lake3d(i,j,:) = Sfcprop(nb)%lake_t_lake3d(ix,:) + clm_lake%lake_icefrac3d(i,j,:) = Sfcprop(nb)%lake_icefrac3d(ix,:) + clm_lake%lake_clay3d(i,j,:) = Sfcprop(nb)%lake_clay3d(ix,:) + clm_lake%lake_sand3d(i,j,:) = Sfcprop(nb)%lake_sand3d(ix,:) enddo enddo end subroutine clm_lake_copy_from_grid - subroutine clm_lake_copy_to_grid(data, Model, Atm_block, Sfcprop) + subroutine clm_lake_copy_to_grid(clm_lake, Model, Atm_block, Sfcprop) ! Copies from data temporary variables to the corresponding Sfcprop variables. ! Terrible things will happen if you don't call data%allocate_data first. implicit none - class(clm_lake_data_type) :: data + class(clm_lake_data_type) :: clm_lake type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) type(GFS_control_type), intent(in) :: Model type(block_control_type), intent(in) :: Atm_block @@ -259,119 +252,119 @@ subroutine clm_lake_copy_to_grid(data, Model, Atm_block, Sfcprop) i = Atm_block%index(nb)%ii(ix) - isc + 1 j = Atm_block%index(nb)%jj(ix) - jsc + 1 - Sfcprop(nb)%T_snow(ix) = data%T_snow(i,j) - Sfcprop(nb)%T_ice(ix) = data%T_ice(i,j) - Sfcprop(nb)%lake_snl2d(ix) = data%lake_snl2d(i,j) - Sfcprop(nb)%lake_h2osno2d(ix) = data%lake_h2osno2d(i,j) - Sfcprop(nb)%lake_tsfc(ix) = data%lake_tsfc(i,j) - Sfcprop(nb)%lake_savedtke12d(ix) = data%lake_savedtke12d(i,j) - Sfcprop(nb)%lake_sndpth2d(ix) = data%lake_sndpth2d(i,j) - Sfcprop(nb)%clm_lakedepth(ix) = data%clm_lakedepth(i,j) - Sfcprop(nb)%clm_lake_initialized(ix) = data%clm_lake_initialized(i,j) - - Sfcprop(nb)%lake_z3d(ix,:) = data%lake_z3d(i,j,:) - Sfcprop(nb)%lake_dz3d(ix,:) = data%lake_dz3d(i,j,:) - Sfcprop(nb)%lake_soil_watsat3d(ix,:) = data%lake_soil_watsat3d(i,j,:) - Sfcprop(nb)%lake_csol3d(ix,:) = data%lake_csol3d(i,j,:) - Sfcprop(nb)%lake_soil_tkmg3d(ix,:) = data%lake_soil_tkmg3d(i,j,:) - Sfcprop(nb)%lake_soil_tkdry3d(ix,:) = data%lake_soil_tkdry3d(i,j,:) - Sfcprop(nb)%lake_soil_tksatu3d(ix,:) = data%lake_soil_tksatu3d(i,j,:) - Sfcprop(nb)%lake_snow_z3d(ix,:) = data%lake_snow_z3d(i,j,:) - Sfcprop(nb)%lake_snow_dz3d(ix,:) = data%lake_snow_dz3d(i,j,:) - Sfcprop(nb)%lake_snow_zi3d(ix,:) = data%lake_snow_zi3d(i,j,:) - Sfcprop(nb)%lake_h2osoi_vol3d(ix,:) = data%lake_h2osoi_vol3d(i,j,:) - Sfcprop(nb)%lake_h2osoi_liq3d(ix,:) = data%lake_h2osoi_liq3d(i,j,:) - Sfcprop(nb)%lake_h2osoi_ice3d(ix,:) = data%lake_h2osoi_ice3d(i,j,:) - Sfcprop(nb)%lake_t_soisno3d(ix,:) = data%lake_t_soisno3d(i,j,:) - Sfcprop(nb)%lake_t_lake3d(ix,:) = data%lake_t_lake3d(i,j,:) - Sfcprop(nb)%lake_icefrac3d(ix,:) = data%lake_icefrac3d(i,j,:) - Sfcprop(nb)%lake_clay3d(ix,:) = data%lake_clay3d(i,j,:) - Sfcprop(nb)%lake_sand3d(ix,:) = data%lake_sand3d(i,j,:) + Sfcprop(nb)%T_snow(ix) = clm_lake%T_snow(i,j) + Sfcprop(nb)%T_ice(ix) = clm_lake%T_ice(i,j) + Sfcprop(nb)%lake_snl2d(ix) = clm_lake%lake_snl2d(i,j) + Sfcprop(nb)%lake_h2osno2d(ix) = clm_lake%lake_h2osno2d(i,j) + Sfcprop(nb)%lake_tsfc(ix) = clm_lake%lake_tsfc(i,j) + Sfcprop(nb)%lake_savedtke12d(ix) = clm_lake%lake_savedtke12d(i,j) + Sfcprop(nb)%lake_sndpth2d(ix) = clm_lake%lake_sndpth2d(i,j) + Sfcprop(nb)%clm_lakedepth(ix) = clm_lake%clm_lakedepth(i,j) + Sfcprop(nb)%clm_lake_initialized(ix) = clm_lake%clm_lake_initialized(i,j) + + Sfcprop(nb)%lake_z3d(ix,:) = clm_lake%lake_z3d(i,j,:) + Sfcprop(nb)%lake_dz3d(ix,:) = clm_lake%lake_dz3d(i,j,:) + Sfcprop(nb)%lake_soil_watsat3d(ix,:) = clm_lake%lake_soil_watsat3d(i,j,:) + Sfcprop(nb)%lake_csol3d(ix,:) = clm_lake%lake_csol3d(i,j,:) + Sfcprop(nb)%lake_soil_tkmg3d(ix,:) = clm_lake%lake_soil_tkmg3d(i,j,:) + Sfcprop(nb)%lake_soil_tkdry3d(ix,:) = clm_lake%lake_soil_tkdry3d(i,j,:) + Sfcprop(nb)%lake_soil_tksatu3d(ix,:) = clm_lake%lake_soil_tksatu3d(i,j,:) + Sfcprop(nb)%lake_snow_z3d(ix,:) = clm_lake%lake_snow_z3d(i,j,:) + Sfcprop(nb)%lake_snow_dz3d(ix,:) = clm_lake%lake_snow_dz3d(i,j,:) + Sfcprop(nb)%lake_snow_zi3d(ix,:) = clm_lake%lake_snow_zi3d(i,j,:) + Sfcprop(nb)%lake_h2osoi_vol3d(ix,:) = clm_lake%lake_h2osoi_vol3d(i,j,:) + Sfcprop(nb)%lake_h2osoi_liq3d(ix,:) = clm_lake%lake_h2osoi_liq3d(i,j,:) + Sfcprop(nb)%lake_h2osoi_ice3d(ix,:) = clm_lake%lake_h2osoi_ice3d(i,j,:) + Sfcprop(nb)%lake_t_soisno3d(ix,:) = clm_lake%lake_t_soisno3d(i,j,:) + Sfcprop(nb)%lake_t_lake3d(ix,:) = clm_lake%lake_t_lake3d(i,j,:) + Sfcprop(nb)%lake_icefrac3d(ix,:) = clm_lake%lake_icefrac3d(i,j,:) + Sfcprop(nb)%lake_clay3d(ix,:) = clm_lake%lake_clay3d(i,j,:) + Sfcprop(nb)%lake_sand3d(ix,:) = clm_lake%lake_sand3d(i,j,:) enddo enddo end subroutine clm_lake_copy_to_grid - subroutine clm_lake_register_fields(data, Sfc_restart) + subroutine clm_lake_register_fields(clm_lake, Sfc_restart) ! Registers all restart fields needed by the CLM Lake Model. - ! Terrible things will happen if you don't call data%allocate_data - ! and data%register_axes first. + ! Terrible things will happen if you don't call clm_lake%allocate_data + ! and clm_lake%register_axes first. implicit none - class(clm_lake_data_type) :: data + class(clm_lake_data_type) :: clm_lake type(FmsNetcdfDomainFile_t) :: Sfc_restart ! Register 2D fields - call register_restart_field(Sfc_restart, 'T_snow', data%T_snow, & + call register_restart_field(Sfc_restart, 'T_snow', clm_lake%T_snow, & dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart, 'T_ice', data%T_ice, & + call register_restart_field(Sfc_restart, 'T_ice', clm_lake%T_ice, & dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart, 'lake_snl2d', data%lake_snl2d, & + call register_restart_field(Sfc_restart, 'lake_snl2d', clm_lake%lake_snl2d, & dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart, 'lake_h2osno2d', data%lake_h2osno2d, & + call register_restart_field(Sfc_restart, 'lake_h2osno2d', clm_lake%lake_h2osno2d, & dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart, 'lake_tsfc', data%lake_tsfc, & + call register_restart_field(Sfc_restart, 'lake_tsfc', clm_lake%lake_tsfc, & dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart, 'lake_savedtke12d', data%lake_savedtke12d, & + call register_restart_field(Sfc_restart, 'lake_savedtke12d', clm_lake%lake_savedtke12d, & dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart, 'lake_sndpth2d', data%lake_sndpth2d, & + call register_restart_field(Sfc_restart, 'lake_sndpth2d', clm_lake%lake_sndpth2d, & dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart, 'clm_lakedepth', data%clm_lakedepth, & + call register_restart_field(Sfc_restart, 'clm_lakedepth', clm_lake%clm_lakedepth, & dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart, 'clm_lake_initialized', data%clm_lake_initialized, & + call register_restart_field(Sfc_restart, 'clm_lake_initialized', clm_lake%clm_lake_initialized, & dimensions=(/'xaxis_1', 'yaxis_1', 'Time '/), is_optional=.true.) ! Register 3D fields - call register_restart_field(Sfc_restart, 'lake_z3d', data%lake_z3d, & + call register_restart_field(Sfc_restart, 'lake_z3d', clm_lake%lake_z3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levlake_clm_lake ', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart, 'lake_dz3d', data%lake_dz3d, & + call register_restart_field(Sfc_restart, 'lake_dz3d', clm_lake%lake_dz3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levlake_clm_lake ', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_soil_watsat3d', data%lake_soil_watsat3d, & + call register_restart_field(Sfc_restart,'lake_soil_watsat3d', clm_lake%lake_soil_watsat3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levlake_clm_lake ', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_csol3d', data%lake_csol3d, & + call register_restart_field(Sfc_restart,'lake_csol3d', clm_lake%lake_csol3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levlake_clm_lake ', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_soil_tkmg3d', data%lake_soil_tkmg3d, & + call register_restart_field(Sfc_restart,'lake_soil_tkmg3d', clm_lake%lake_soil_tkmg3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levlake_clm_lake ', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_soil_tkdry3d', data%lake_soil_tkdry3d, & + call register_restart_field(Sfc_restart,'lake_soil_tkdry3d', clm_lake%lake_soil_tkdry3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levlake_clm_lake ', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_soil_tksatu3d', data%lake_soil_tksatu3d, & + call register_restart_field(Sfc_restart,'lake_soil_tksatu3d', clm_lake%lake_soil_tksatu3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levlake_clm_lake ', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_snow_z3d', data%lake_snow_z3d, & + call register_restart_field(Sfc_restart,'lake_snow_z3d', clm_lake%lake_snow_z3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_snow_dz3d', data%lake_snow_dz3d, & + call register_restart_field(Sfc_restart,'lake_snow_dz3d', clm_lake%lake_snow_dz3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_snow_zi3d', data%lake_snow_zi3d, & + call register_restart_field(Sfc_restart,'lake_snow_zi3d', clm_lake%lake_snow_zi3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levsnowsoil_clm_lake ', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_h2osoi_vol3d', data%lake_h2osoi_vol3d, & + call register_restart_field(Sfc_restart,'lake_h2osoi_vol3d', clm_lake%lake_h2osoi_vol3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_h2osoi_liq3d', data%lake_h2osoi_liq3d, & + call register_restart_field(Sfc_restart,'lake_h2osoi_liq3d', clm_lake%lake_h2osoi_liq3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_h2osoi_ice3d', data%lake_h2osoi_ice3d, & + call register_restart_field(Sfc_restart,'lake_h2osoi_ice3d', clm_lake%lake_h2osoi_ice3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_t_soisno3d', data%lake_t_soisno3d, & + call register_restart_field(Sfc_restart,'lake_t_soisno3d', clm_lake%lake_t_soisno3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_t_lake3d', data%lake_t_lake3d, & + call register_restart_field(Sfc_restart,'lake_t_lake3d', clm_lake%lake_t_lake3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levlake_clm_lake ', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_icefrac3d', data%lake_icefrac3d, & + call register_restart_field(Sfc_restart,'lake_icefrac3d', clm_lake%lake_icefrac3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levlake_clm_lake ', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_clay3d', data%lake_clay3d, & + call register_restart_field(Sfc_restart,'lake_clay3d', clm_lake%lake_clay3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levsoil_clm_lake ', 'Time '/), is_optional=.true.) - call register_restart_field(Sfc_restart,'lake_sand3d', data%lake_sand3d, & + call register_restart_field(Sfc_restart,'lake_sand3d', clm_lake%lake_sand3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & 'levsoil_clm_lake ', 'Time '/), is_optional=.true.) end subroutine clm_lake_register_fields @@ -403,50 +396,68 @@ subroutine clm_lake_bundle_fields(clm_lake, bundle, grid, Model, outputfile) call create_2d_field_and_add_to_bundle(clm_lake%clm_lake_initialized, "clm_lake_initialized", trim(outputfile), grid, bundle) ! Register 3D fields - call create_3d_field_and_add_to_bundle(clm_lake%lake_z3d, 'lake_z3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_dz3d, 'lake_dz3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_soil_watsat3d, 'lake_soil_watsat3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_csol3d, 'lake_csol3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_soil_tkmg3d, 'lake_soil_tkmg3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_soil_tkdry3d, 'lake_soil_tkdry3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_soil_tksatu3d, 'lake_soil_tksatu3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_snow_z3d, 'lake_snow_z3d', 'levsnowsoil1_clm_lake', Model%nlevsnowsoil1_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_snow_dz3d, 'lake_snow_dz3d', 'levsnowsoil1_clm_lake', Model%nlevsnowsoil1_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_snow_zi3d, 'lake_snow_zi3d', 'levsnowsoil_clm_lake', Model%nlevsnowsoil_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_h2osoi_vol3d, 'lake_h2osoi_vol3d', 'levsnowsoil1_clm_lake', Model%nlevsnowsoil1_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_h2osoi_liq3d, 'lake_h2osoi_liq3d', 'levsnowsoil1_clm_lake', Model%nlevsnowsoil1_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_h2osoi_ice3d, 'lake_h2osoi_ice3d', 'levsnowsoil1_clm_lake', Model%nlevsnowsoil1_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_t_soisno3d, 'lake_t_soisno3d', 'levsnowsoil1_clm_lake', Model%nlevsnowsoil1_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_t_lake3d, 'lake_t_lake3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_icefrac3d, 'lake_icefrac3d', 'levlake_clm_lake', Model%nlevlake_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_clay3d, 'lake_clay3d', 'levsoil_clm_lake', Model%nlevsoil_clm_lake, trim(outputfile), grid, bundle) - call create_3d_field_and_add_to_bundle(clm_lake%lake_sand3d, 'lake_sand3d', 'levsoil_clm_lake', Model%nlevsoil_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_z3d, 'lake_z3d', 'levlake_clm_lake', & + clm_lake%levlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_dz3d, 'lake_dz3d', 'levlake_clm_lake', & + clm_lake%levlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_soil_watsat3d, 'lake_soil_watsat3d', 'levlake_clm_lake', & + clm_lake%levlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_csol3d, 'lake_csol3d', 'levlake_clm_lake', & + clm_lake%levlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_soil_tkmg3d, 'lake_soil_tkmg3d', 'levlake_clm_lake', & + clm_lake%levlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_soil_tkdry3d, 'lake_soil_tkdry3d', 'levlake_clm_lake', & + clm_lake%levlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_soil_tksatu3d, 'lake_soil_tksatu3d', 'levlake_clm_lake', & + clm_lake%levlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_snow_z3d, 'lake_snow_z3d', 'levsnowsoil1_clm_lake', & + clm_lake%levsnowsoil1_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_snow_dz3d, 'lake_snow_dz3d', 'levsnowsoil1_clm_lake', & + clm_lake%levsnowsoil1_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_snow_zi3d, 'lake_snow_zi3d', 'levsnowsoil_clm_lake', & + clm_lake%levsnowsoil_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_h2osoi_vol3d, 'lake_h2osoi_vol3d', 'levsnowsoil1_clm_lake', & + clm_lake%levsnowsoil1_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_h2osoi_liq3d, 'lake_h2osoi_liq3d', 'levsnowsoil1_clm_lake', & + clm_lake%levsnowsoil1_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_h2osoi_ice3d, 'lake_h2osoi_ice3d', 'levsnowsoil1_clm_lake', & + clm_lake%levsnowsoil1_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_t_soisno3d, 'lake_t_soisno3d', 'levsnowsoil1_clm_lake', & + clm_lake%levsnowsoil1_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_t_lake3d, 'lake_t_lake3d', 'levlake_clm_lake', & + clm_lake%levlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_icefrac3d, 'lake_icefrac3d', 'levlake_clm_lake', & + clm_lake%levlake_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_clay3d, 'lake_clay3d', 'levsoil_clm_lake', & + clm_lake%levsoil_clm_lake, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(clm_lake%lake_sand3d, 'lake_sand3d', 'levsoil_clm_lake', & + clm_lake%levsoil_clm_lake, trim(outputfile), grid, bundle) end subroutine Clm_lake_bundle_fields - subroutine clm_lake_final(data) + subroutine clm_lake_final(clm_lake) ! Final routine for clm_lake_data_type, called automatically when ! an object of that type goes out of scope. This is simply a - ! wrapper around data%deallocate_data(). + ! wrapper around clm_lake%deallocate_data(). implicit none - type(clm_lake_data_type) :: data - call clm_lake_deallocate_data(data) + type(clm_lake_data_type) :: clm_lake + call clm_lake_deallocate_data(clm_lake) end subroutine clm_lake_final - subroutine clm_lake_deallocate_data(data) - ! Deallocates all data used, and nullifies the pointers. The data + subroutine clm_lake_deallocate_data(clm_lake) + ! Deallocates all data used, and nullifies the pointers. The clm_lake ! object can safely be used again after this call. This is also ! the implementation of the clm_lake_data_type final routine. implicit none - class(clm_lake_data_type) :: data + class(clm_lake_data_type) :: clm_lake ! Deallocate and nullify any associated pointers ! This #define reduces code length by a lot #define IF_ASSOC_DEALLOC_NULL(var) \ - if(associated(data%var)) then ; \ - deallocate(data%var) ; \ - nullify(data%var) ; \ + if(associated(clm_lake%var)) then ; \ + deallocate(clm_lake%var) ; \ + nullify(clm_lake%var) ; \ endif IF_ASSOC_DEALLOC_NULL(T_snow) diff --git a/io/FV3GFS_common_io.F90 b/io/FV3GFS_common_io.F90 index ce0fc60f6..c2d0a96e0 100644 --- a/io/FV3GFS_common_io.F90 +++ b/io/FV3GFS_common_io.F90 @@ -375,7 +375,7 @@ subroutine create_2d_field_and_add_to_bundle(temp_r2d, field_name, outputfile, g end subroutine create_2d_field_and_add_to_bundle - subroutine create_3d_field_and_add_to_bundle(temp_r3d, field_name, axis_name, num_levels, outputfile, grid, bundle) + subroutine create_3d_field_and_add_to_bundle(temp_r3d, field_name, axis_name, axis_values, outputfile, grid, bundle) use esmf @@ -384,7 +384,7 @@ subroutine create_3d_field_and_add_to_bundle(temp_r3d, field_name, axis_name, nu real(kind_phys), dimension(:,:,:), pointer, intent(in) :: temp_r3d character(len=*), intent(in) :: field_name character(len=*), intent(in) :: axis_name - integer, intent(in) :: num_levels + real(kind_phys), dimension(:), intent(in) :: axis_values character(len=*), intent(in) :: outputfile type(ESMF_Grid), intent(in) :: grid type(ESMF_FieldBundle), intent(inout) :: bundle @@ -401,14 +401,14 @@ subroutine create_3d_field_and_add_to_bundle(temp_r3d, field_name, axis_name, nu call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", name='output_file', value=trim(outputfile), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - call add_zaxis_to_field(field, axis_name, num_levels) + call add_zaxis_to_field(field, axis_name, axis_values) call ESMF_FieldBundleAdd(bundle, (/field/), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) end subroutine create_3d_field_and_add_to_bundle - subroutine add_zaxis_to_field(field, axis_name, num_levels) + subroutine add_zaxis_to_field(field, axis_name, axis_values) use esmf @@ -416,23 +416,17 @@ subroutine add_zaxis_to_field(field, axis_name, num_levels) type(ESMF_Field), intent(inout) :: field character(len=*), intent(in) :: axis_name - integer, intent(in) :: num_levels + real(kind_phys), dimension(:), intent(in) :: axis_values - real(kind_phys), allocatable, dimension(:) :: buffer - integer :: rc, i + integer :: rc call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & name="ESMF:ungridded_dim_labels", valueList=(/trim(axis_name)/), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - allocate( buffer(num_levels) ) - do i=1, num_levels - buffer(i)=i - end do call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3-dim", & - name=trim(axis_name), valueList=buffer, rc=rc) + name=trim(axis_name), valueList=axis_values, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - deallocate(buffer) call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3-dim", & name=trim(axis_name)//"cartesian_axis", value="Z", rc=rc) diff --git a/io/FV3GFS_restart_io.F90 b/io/FV3GFS_restart_io.F90 index 6b7b13cf1..b64fe255f 100644 --- a/io/FV3GFS_restart_io.F90 +++ b/io/FV3GFS_restart_io.F90 @@ -185,6 +185,7 @@ subroutine fv_phy_restart_bundle_setup(bundle, grid, rc) real(kind_phys),dimension(:,:),pointer :: temp_r2d real(kind_phys),dimension(:,:,:),pointer :: temp_r3d integer :: num + real(kind_phys), allocatable :: axis_values(:) if (.not. allocated(phy_var2)) then write(0,*)'ERROR phy_var2, NOT allocated' @@ -207,11 +208,16 @@ subroutine fv_phy_restart_bundle_setup(bundle, grid, rc) call create_2d_field_and_add_to_bundle(temp_r2d, trim(phy_var2_names(num)), trim(outputfile), grid, bundle) enddo + allocate(axis_values(npz)) + axis_values = (/ (i, i=1,npz) /) + do num = 1,nvar3d temp_r3d => phy_var3(:,:,:,num) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(phy_var3_names(num)), "zaxis_1", npz, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(phy_var3_names(num)), "zaxis_1", axis_values, trim(outputfile), grid, bundle) enddo + deallocate(axis_values) + end subroutine fv_phy_restart_bundle_setup subroutine fv_sfc_restart_bundle_setup(bundle, grid, Model, rc) diff --git a/io/FV3GFS_rrfs_sd_io.F90 b/io/FV3GFS_rrfs_sd_io.F90 index 099eaa28d..4acac886c 100644 --- a/io/FV3GFS_rrfs_sd_io.F90 +++ b/io/FV3GFS_rrfs_sd_io.F90 @@ -39,6 +39,9 @@ module FV3GFS_rrfs_sd_io real(kind_phys), pointer, private, dimension(:,:,:) :: & fire_in=>null() ! i, j, fire_aux_data_levels + real(kind_phys), pointer, private, dimension(:) :: & + fire_aux_data_levels=>null() ! 1:Model%fire_aux_data_levels index array for metadata write + contains procedure, public :: register_axis => rrfs_sd_state_register_axis ! register fire_aux_data_levels axis procedure, public :: write_axis => rrfs_sd_state_write_axis ! write fire_aux_data_levels variable @@ -106,17 +109,10 @@ subroutine rrfs_sd_state_write_axis(data,Model,Sfc_restart) class(rrfs_sd_state_type) :: data type(FmsNetcdfDomainFile_t) :: Sfc_restart type(GFS_control_type), intent(in) :: Model - real(kind_phys) :: fire_aux_data_levels(Model%fire_aux_data_levels) - integer :: i call register_field(Sfc_restart, 'fire_aux_data_levels', 'double', (/'fire_aux_data_levels'/)) call register_variable_attribute(Sfc_restart, 'fire_aux_data_levels', 'cartesian_axis' ,'Z', str_len=1) - - do i=1,Model%fire_aux_data_levels - fire_aux_data_levels(i) = i - enddo - - call write_data(Sfc_restart, 'fire_aux_data_levels', fire_aux_data_levels) + call write_data(Sfc_restart, 'fire_aux_data_levels', data%fire_aux_data_levels) end subroutine rrfs_sd_state_write_axis ! -------------------------------------------------------------------- @@ -125,7 +121,7 @@ subroutine rrfs_sd_state_allocate_data(data,Model) implicit none class(rrfs_sd_state_type) :: data type(GFS_control_type), intent(in) :: Model - integer :: nx, ny + integer :: nx, ny, i call data%deallocate_data @@ -137,9 +133,13 @@ subroutine rrfs_sd_state_allocate_data(data,Model) allocate(data%emanoc(nx,ny)) allocate(data%fhist(nx,ny)) allocate(data%coef_bb_dc(nx,ny)) - + allocate(data%fire_aux_data_levels(Model%fire_aux_data_levels)) allocate(data%fire_in(nx,ny,Model%fire_aux_data_levels)) + do i=1,Model%fire_aux_data_levels + data%fire_aux_data_levels(i) = i + enddo + end subroutine rrfs_sd_state_allocate_data ! -------------------------------------------------------------------- @@ -230,7 +230,7 @@ subroutine rrfs_sd_bundle_fields(data, bundle, grid, Model, outputfile) ! Register 3D field call create_3d_field_and_add_to_bundle(data%fire_in, 'fire_in', 'fire_aux_data_levels', & - Model%fire_aux_data_levels, trim(outputfile), grid, bundle) + data%fire_aux_data_levels, trim(outputfile), grid, bundle) end subroutine rrfs_sd_bundle_fields ! -------------------------------------------------------------------- @@ -368,7 +368,8 @@ subroutine rrfs_sd_emissions_register_dust12m(data, restart, Atm_block) !--- register the 3D fields do num = 1,data%nvar_dust12m var3_p2 => data%dust12m_var(:,:,:,num) - call register_restart_field(restart, data%dust12m_name(num), var3_p2, dimensions=(/'time', 'lat ', 'lon '/),& + call register_restart_field(restart, data%dust12m_name(num), var3_p2, & + dimensions=(/'time', 'lat ', 'lon '/),& &is_optional=.true.) ! That was "is_optional=.not.mand" in the original, but mand was never initialized. enddo @@ -444,7 +445,8 @@ subroutine rrfs_sd_emissions_register_emi(data, restart, Atm_block) !--- register the 2D fields do num = 1,data%nvar_emi var3_p2 => data%emi_var(:,:,:,num) - call register_restart_field(restart, data%emi_name(num), var3_p2, dimensions=(/'time ','grid_yt','grid_xt'/)) + call register_restart_field(restart, data%emi_name(num), var3_p2, & + dimensions=(/'time ','grid_yt','grid_xt'/)) enddo end subroutine rrfs_sd_emissions_register_emi @@ -518,7 +520,8 @@ subroutine rrfs_sd_emissions_register_fire(data, restart, Atm_block) !--- register the 3D fields do num = 1,data%nvar_fire var3_p2 => data%fire_var(:,:,:,num) - call register_restart_field(restart, data%fire_name(num), var3_p2, dimensions=(/'t ', 'lat', 'lon'/), is_optional=.true.) + call register_restart_field(restart, data%fire_name(num), var3_p2, & + dimensions=(/'t ', 'lat', 'lon'/), is_optional=.true.) enddo end subroutine rrfs_sd_emissions_register_fire diff --git a/io/FV3GFS_sfc_io.F90 b/io/FV3GFS_sfc_io.F90 index 6cb5799bc..b450ec7de 100644 --- a/io/FV3GFS_sfc_io.F90 +++ b/io/FV3GFS_sfc_io.F90 @@ -1518,35 +1518,56 @@ subroutine Sfc_io_bundle_3d_fields(sfc, bundle, grid, Model, outputfile) character(*), intent(in) :: outputfile real(kind_phys),dimension(:,:,:),pointer :: temp_r3d - integer :: num + integer :: num, i + real(kind_phys), dimension(:), allocatable :: zaxis_1, zaxis_2, zaxis_3, zaxis_4 + + allocate(zaxis_1(Model%kice)) + zaxis_1 = (/ (i, i=1,Model%kice) /) temp_r3d => sfc%var3ice(:,:,:) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(0)), "zaxis_1", Model%kice, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(0)), "zaxis_1", zaxis_1, trim(outputfile), grid, bundle) if(Model%lsm == Model%lsm_ruc) then do num = 1,sfc%nvar3 temp_r3d => sfc%var3(:,:,:,num) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_1", Model%kice, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_1", zaxis_1, trim(outputfile), grid, bundle) enddo else + allocate(zaxis_2(Model%lsoil)) + zaxis_2 = (/ (i, i=1,Model%lsoil) /) do num = 1,sfc%nvar3 temp_r3d => sfc%var3(:,:,:,num) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_2", Model%lsoil, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_2", zaxis_2, trim(outputfile), grid, bundle) enddo + deallocate(zaxis_2) endif if (Model%lsm == Model%lsm_noahmp) then + allocate(zaxis_3(3)) + zaxis_3 = (/ (i, i=1,3) /) + do num = sfc%nvar3+1,sfc%nvar3+3 temp_r3d => sfc%var3sn(:,:,:,num) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_3", 3, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(num)), "zaxis_3", zaxis_3, trim(outputfile), grid, bundle) enddo + allocate(zaxis_2(Model%lsoil)) + zaxis_2 = (/ (i, i=1,Model%lsoil) /) + temp_r3d => sfc%var3eq(:,:,:,7) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(7)), "zaxis_2", Model%lsoil, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(7)), "zaxis_2", zaxis_2, trim(outputfile), grid, bundle) + + allocate(zaxis_4(7)) + zaxis_4 = (/ (i, i=1,7) /) temp_r3d => sfc%var3zn(:,:,:,8) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(8)), "zaxis_4", 7, trim(outputfile), grid, bundle) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(sfc%name3(8)), "zaxis_4", zaxis_4, trim(outputfile), grid, bundle) endif ! lsm = lsm_noahmp + if(allocated(zaxis_1)) deallocate(zaxis_1) + if(allocated(zaxis_2)) deallocate(zaxis_2) + if(allocated(zaxis_3)) deallocate(zaxis_3) + if(allocated(zaxis_4)) deallocate(zaxis_4) + end subroutine Sfc_io_bundle_3d_fields end module FV3GFS_sfc_io From b336138cfcbd927978cb1bf968dab040b28fc195 Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Fri, 26 May 2023 17:58:22 +0000 Subject: [PATCH 21/27] rename FV3GFS to fv3atm in code, except output metadata --- CMakeLists.txt | 14 ++-- atmos_model.F90 | 26 +++---- fv3_cap.F90 | 18 ++--- ...clm_lake_io.F90 => fv3atm_clm_lake_io.F90} | 6 +- ...GFS_common_io.F90 => fv3atm_common_io.F90} | 4 +- io/{FV3GFS_io.F90 => fv3atm_history_io.F90} | 74 +++++++++---------- io/{FV3GFS_oro_io.F90 => fv3atm_oro_io.F90} | 6 +- ...S_restart_io.F90 => fv3atm_restart_io.F90} | 18 ++--- ...S_rrfs_sd_io.F90 => fv3atm_rrfs_sd_io.F90} | 6 +- io/{FV3GFS_sfc_io.F90 => fv3atm_sfc_io.F90} | 8 +- io/module_wrt_grid_comp.F90 | 4 +- module_fcst_grid_comp.F90 | 4 +- moving_nest/fv_moving_nest_physics.F90 | 2 +- 13 files changed, 95 insertions(+), 95 deletions(-) rename io/{FV3GFS_clm_lake_io.F90 => fv3atm_clm_lake_io.F90} (99%) rename io/{FV3GFS_common_io.F90 => fv3atm_common_io.F90} (99%) rename io/{FV3GFS_io.F90 => fv3atm_history_io.F90} (98%) rename io/{FV3GFS_oro_io.F90 => fv3atm_oro_io.F90} (99%) rename io/{FV3GFS_restart_io.F90 => fv3atm_restart_io.F90} (95%) rename io/{FV3GFS_rrfs_sd_io.F90 => fv3atm_rrfs_sd_io.F90} (99%) rename io/{FV3GFS_sfc_io.F90 => fv3atm_sfc_io.F90} (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd6d56202..549738794 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,13 +85,13 @@ add_library(fv3atm cpl/module_block_data.F90 cpl/module_cplfields.F90 cpl/module_cap_cpl.F90 - io/FV3GFS_common_io.F90 - io/FV3GFS_clm_lake_io.F90 - io/FV3GFS_rrfs_sd_io.F90 - io/FV3GFS_sfc_io.F90 - io/FV3GFS_oro_io.F90 - io/FV3GFS_io.F90 - io/FV3GFS_restart_io.F90 + io/fv3atm_common_io.F90 + io/fv3atm_clm_lake_io.F90 + io/fv3atm_rrfs_sd_io.F90 + io/fv3atm_sfc_io.F90 + io/fv3atm_oro_io.F90 + io/fv3atm_history_io.F90 + io/fv3atm_restart_io.F90 io/module_write_netcdf.F90 io/module_write_restart_netcdf.F90 io/module_fv3_io_def.F90 diff --git a/atmos_model.F90 b/atmos_model.F90 index 7470f6971..559194410 100644 --- a/atmos_model.F90 +++ b/atmos_model.F90 @@ -90,11 +90,11 @@ module atmos_model_mod use stochastic_physics_wrapper_mod, only: stochastic_physics_wrapper,stochastic_physics_wrapper_end -use FV3GFS_io_mod, only: FV3GFS_restart_read, FV3GFS_restart_write, & - FV3GFS_GFS_checksum, & - FV3GFS_diag_register, FV3GFS_diag_output, & +use fv3atm_history_io_mod, only: fv3atm_restart_read, fv3atm_restart_write, & + fv3atm_checksum, & + fv3atm_diag_register, fv3atm_diag_output, & DIAG_SIZE -use FV3GFS_restart_io_mod, only: FV3GFS_restart_register, & +use fv3atm_restart_io_mod, only: fv3atm_restart_register, & fv_phy_restart_output, & fv_sfc_restart_output use fv_ufs_restart_io_mod, only: fv_dyn_restart_register, & @@ -369,7 +369,7 @@ subroutine update_atmos_radiation_physics (Atmos) if (chksum_debug) then if (mpp_pe() == mpp_root_pe()) print *,'RADIATION STEP ', GFS_control%kdt, GFS_control%fhour - call FV3GFS_GFS_checksum(GFS_control, GFS_data, Atm_block) + call fv3atm_checksum(GFS_control, GFS_data, Atm_block) endif if (mpp_pe() == mpp_root_pe() .and. debug) write(6,*) "physics driver" @@ -383,7 +383,7 @@ subroutine update_atmos_radiation_physics (Atmos) if (chksum_debug) then if (mpp_pe() == mpp_root_pe()) print *,'PHYSICS STEP1 ', GFS_control%kdt, GFS_control%fhour - call FV3GFS_GFS_checksum(GFS_control, GFS_data, Atm_block) + call fv3atm_checksum(GFS_control, GFS_data, Atm_block) endif if (GFS_Control%do_sppt .or. GFS_Control%do_shum .or. GFS_Control%do_skeb .or. & @@ -402,7 +402,7 @@ subroutine update_atmos_radiation_physics (Atmos) if (chksum_debug) then if (mpp_pe() == mpp_root_pe()) print *,'PHYSICS STEP2 ', GFS_control%kdt, GFS_control%fhour - call FV3GFS_GFS_checksum(GFS_control, GFS_data, Atm_block) + call fv3atm_checksum(GFS_control, GFS_data, Atm_block) endif call getiauforcing(GFS_control,IAU_data) if (mpp_pe() == mpp_root_pe() .and. debug) write(6,*) "end of radiation and physics step" @@ -736,15 +736,15 @@ subroutine atmos_model_init (Atmos, Time_init, Time, Time_step) !rab call atmosphere_tracer_postinit (GFS_data, Atm_block) call atmosphere_nggps_diag (Time, init=.true.) - call FV3GFS_diag_register (GFS_Diag, Time, Atm_block, GFS_control, Atmos%lon, Atmos%lat, Atmos%axes) + call fv3atm_diag_register (GFS_Diag, Time, Atm_block, GFS_control, Atmos%lon, Atmos%lat, Atmos%axes) call GFS_restart_populate (GFS_restart_var, GFS_control, GFS_data%Statein, GFS_data%Stateout, GFS_data%Sfcprop, & GFS_data%Coupling, GFS_data%Grid, GFS_data%Tbd, GFS_data%Cldprop, GFS_data%Radtend, & GFS_data%IntDiag, Init_parm, GFS_Diag) if (quilting_restart) then call fv_dyn_restart_register (Atm(mygrid)) - call FV3GFS_restart_register (GFS_data%Sfcprop, GFS_restart_var, Atm_block, GFS_control) + call fv3atm_restart_register (GFS_data%Sfcprop, GFS_restart_var, Atm_block, GFS_control) endif - call FV3GFS_restart_read (GFS_data, GFS_restart_var, Atm_block, GFS_control, Atmos%domain_for_read, & + call fv3atm_restart_read (GFS_data, GFS_restart_var, Atm_block, GFS_control, Atmos%domain_for_read, & Atm(mygrid)%flagstruct%warm_start, ignore_rst_cksum) if(GFS_control%do_ca .and. Atm(mygrid)%flagstruct%warm_start)then call read_ca_restart (Atmos%domain,GFS_control%ncells,GFS_control%nca,GFS_control%ncells_g,GFS_control%nca_g) @@ -966,7 +966,7 @@ subroutine update_atmos_model_state (Atmos, rc) if (chksum_debug) then if (mpp_pe() == mpp_root_pe()) print *,'UPDATE STATE ', GFS_control%kdt, GFS_control%fhour if (mpp_pe() == mpp_root_pe()) print *,'in UPDATE STATE ', size(GFS_data(1)%SfcProp%tsfc),'nblks=',Atm_block%nblks - call FV3GFS_GFS_checksum(GFS_control, GFS_data, Atm_block) + call fv3atm_checksum(GFS_control, GFS_data, Atm_block) endif !--- advance time --- @@ -995,7 +995,7 @@ subroutine update_atmos_model_state (Atmos, rc) endif if (mpp_pe() == mpp_root_pe()) write(6,*) ' gfs diags time since last bucket empty: ',time_int/3600.,'hrs' call atmosphere_nggps_diag(Atmos%Time) - call FV3GFS_diag_output(Atmos%Time, GFS_Diag, Atm_block, GFS_control%nx, GFS_control%ny, & + call fv3atm_diag_output(Atmos%Time, GFS_Diag, Atm_block, GFS_control%nx, GFS_control%ny, & GFS_control%levs, 1, 1, 1.0_GFS_kind_phys, time_int, time_intfull, & GFS_control%fhswr, GFS_control%fhlwr) endif @@ -1109,7 +1109,7 @@ subroutine atmos_model_restart(Atmos, timestamp) call fv_dyn_restart_output(Atm(mygrid), timestamp) else call atmosphere_restart(timestamp) - call FV3GFS_restart_write (GFS_data, GFS_restart_var, Atm_block, & + call fv3atm_restart_write (GFS_data, GFS_restart_var, Atm_block, & GFS_control, Atmos%domain, timestamp) endif if(GFS_control%do_ca)then diff --git a/fv3_cap.F90 b/fv3_cap.F90 index 7b3ab2eba..50ad49104 100644 --- a/fv3_cap.F90 +++ b/fv3_cap.F90 @@ -1,4 +1,4 @@ -!--------------- FV3GFS solo model ----------------- +!--------------- FV3 ATM solo model ---------------- ! !*** The FV3 atmosphere grid component nuopc cap ! @@ -11,7 +11,7 @@ ! 02 Nov 2017: J. Wang Use Gerhard's transferable RouteHandle ! -module fv3gfs_cap_mod +module fv3atm_cap_mod use ESMF use NUOPC @@ -80,14 +80,14 @@ module fv3gfs_cap_mod contains !----------------------------------------------------------------------- -!------------------- Solo fv3gfs code starts here ---------------------- +!------------------- Solo fv3atm code starts here ---------------------- !----------------------------------------------------------------------- subroutine SetServices(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc - character(len=*),parameter :: subname='(fv3gfs_cap:SetServices)' + character(len=*),parameter :: subname='(fv3atm_cap:SetServices)' rc = ESMF_SUCCESS @@ -983,7 +983,7 @@ subroutine InitializeRealize(gcomp, rc) integer, intent(out) :: rc ! local variables - character(len=*),parameter :: subname='(fv3gfs_cap:InitializeRealize)' + character(len=*),parameter :: subname='(fv3atm_cap:InitializeRealize)' type(ESMF_Clock) :: clock type(ESMF_State) :: importState, exportState integer :: urc @@ -1248,7 +1248,7 @@ subroutine fv3_checkimport(gcomp, rc) integer, intent(out) :: rc ! local variables - character(len=*),parameter :: subname='(fv3gfs_cap:fv3_checkimport)' + character(len=*),parameter :: subname='(fv3atm_cap:fv3_checkimport)' integer :: n, nf type(ESMF_Clock) :: clock type(ESMF_Time) :: currTime, invalidTime @@ -1335,7 +1335,7 @@ subroutine TimestampExport_phase1(gcomp, rc) integer, intent(out) :: rc ! local variables - character(len=*),parameter :: subname='(fv3gfs_cap:TimestampExport_phase1)' + character(len=*),parameter :: subname='(fv3atm_cap:TimestampExport_phase1)' type(ESMF_Clock) :: driverClock, modelClock type(ESMF_State) :: exportState @@ -1365,7 +1365,7 @@ subroutine ModelFinalize(gcomp, rc) integer, intent(out) :: rc ! local variables - character(len=*),parameter :: subname='(fv3gfs_cap:ModelFinalize)' + character(len=*),parameter :: subname='(fv3atm_cap:ModelFinalize)' integer :: i, urc type(ESMF_VM) :: vm real(kind=8) :: MPI_Wtime, timeffs @@ -1413,4 +1413,4 @@ end subroutine ModelFinalize ! !----------------------------------------------------------------------------- -end module fv3gfs_cap_mod +end module fv3atm_cap_mod diff --git a/io/FV3GFS_clm_lake_io.F90 b/io/fv3atm_clm_lake_io.F90 similarity index 99% rename from io/FV3GFS_clm_lake_io.F90 rename to io/fv3atm_clm_lake_io.F90 index 84d2de08d..98d539277 100644 --- a/io/FV3GFS_clm_lake_io.F90 +++ b/io/fv3atm_clm_lake_io.F90 @@ -1,4 +1,4 @@ -module FV3GFS_clm_lake_io +module fv3atm_clm_lake_io use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, & GFS_data_type, kind_phys use GFS_restart, only: GFS_restart_type @@ -10,7 +10,7 @@ module FV3GFS_clm_lake_io register_variable_attribute, register_field, & read_restart, write_restart, write_data, & get_global_io_domain_indices, variable_exists - use FV3GFS_common_io + use fv3atm_common_io implicit none @@ -492,4 +492,4 @@ subroutine clm_lake_deallocate_data(clm_lake) #undef IF_ASSOC_DEALLOC_NULL end subroutine clm_lake_deallocate_data -end module FV3GFS_clm_lake_io +end module fv3atm_clm_lake_io diff --git a/io/FV3GFS_common_io.F90 b/io/fv3atm_common_io.F90 similarity index 99% rename from io/FV3GFS_common_io.F90 rename to io/fv3atm_common_io.F90 index c2d0a96e0..4ce7c5a2a 100644 --- a/io/FV3GFS_common_io.F90 +++ b/io/fv3atm_common_io.F90 @@ -1,4 +1,4 @@ -module FV3GFS_common_io +module fv3atm_common_io use GFS_typedefs, only: kind_phys use block_control_mod, only: block_control_type @@ -434,4 +434,4 @@ subroutine add_zaxis_to_field(field, axis_name, axis_values) end subroutine add_zaxis_to_field -end module FV3GFS_common_io +end module fv3atm_common_io diff --git a/io/FV3GFS_io.F90 b/io/fv3atm_history_io.F90 similarity index 98% rename from io/FV3GFS_io.F90 rename to io/fv3atm_history_io.F90 index 3291e815b..9c2f246d2 100644 --- a/io/FV3GFS_io.F90 +++ b/io/fv3atm_history_io.F90 @@ -1,4 +1,4 @@ -module FV3GFS_io_mod +module fv3atm_history_io_mod !----------------------------------------------------------------------- ! gfs_physics_driver_mod defines the GFS physics routines used by @@ -33,7 +33,7 @@ module FV3GFS_io_mod use diag_util_mod, only: find_input_field use constants_mod, only: grav, rdgas use physcons, only: con_tice !saltwater freezing temp (K) - use FV3GFS_clm_lake_io, only: clm_lake_data_type + use fv3atm_clm_lake_io, only: clm_lake_data_type ! !--- GFS_typedefs use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, & @@ -41,9 +41,9 @@ module FV3GFS_io_mod use GFS_restart, only: GFS_restart_type use GFS_diagnostics, only: GFS_externaldiag_type - use FV3GFS_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data - use FV3GFS_sfc_io - use FV3GFS_oro_io + use fv3atm_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data + use fv3atm_sfc_io + use fv3atm_oro_io ! !----------------------------------------------------------------------- @@ -51,9 +51,9 @@ module FV3GFS_io_mod private !--- public interfaces --- - public FV3GFS_restart_read, FV3GFS_restart_write - public FV3GFS_GFS_checksum - public fv3gfs_diag_register, fv3gfs_diag_output + public fv3atm_restart_read, fv3atm_restart_write + public fv3atm_checksum + public fv3atm_diag_register, fv3atm_diag_output #ifdef use_WRTCOMP public fv_phys_bundle_setup #endif @@ -119,9 +119,9 @@ module FV3GFS_io_mod !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ! !-------------------- -! FV3GFS_restart_read +! fv3atm_restart_read !-------------------- - subroutine FV3GFS_restart_read (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) + subroutine fv3atm_restart_read (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) type(GFS_data_type), intent(inout) :: GFS_Data(:) type(GFS_restart_type), intent(inout) :: GFS_Restart type(block_control_type), intent(in) :: Atm_block @@ -136,12 +136,12 @@ subroutine FV3GFS_restart_read (GFS_Data, GFS_Restart, Atm_block, Model, fv_doma !--- read in physics restart data call phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_rst_cksum) - end subroutine FV3GFS_restart_read + end subroutine fv3atm_restart_read !--------------------- -! FV3GFS_restart_write +! fv3atm_restart_write !--------------------- - subroutine FV3GFS_restart_write (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, timestamp) + subroutine fv3atm_restart_write (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, timestamp) type(GFS_data_type), intent(inout) :: GFS_Data(:) type(GFS_restart_type), intent(inout) :: GFS_Restart type(block_control_type), intent(in) :: Atm_block @@ -155,13 +155,13 @@ subroutine FV3GFS_restart_write (GFS_Data, GFS_Restart, Atm_block, Model, fv_dom !--- write physics restart data call phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timestamp) - end subroutine FV3GFS_restart_write + end subroutine fv3atm_restart_write -!-------------------- -! FV3GFS_GFS_checksum -!-------------------- - subroutine FV3GFS_GFS_checksum (Model, GFS_Data, Atm_block) +!---------------- +! fv3atm_checksum +!---------------- + subroutine fv3atm_checksum (Model, GFS_Data, Atm_block) !--- interface variables type(GFS_control_type), intent(in) :: Model type(GFS_data_type), intent(in) :: GFS_Data(:) @@ -514,7 +514,7 @@ subroutine FV3GFS_GFS_checksum (Model, GFS_Data, Atm_block) deallocate(temp2d) deallocate(temp3d) deallocate(temp3dlevsp1) - end subroutine FV3GFS_GFS_checksum + end subroutine fv3atm_checksum !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ! @@ -536,7 +536,7 @@ end subroutine FV3GFS_GFS_checksum ! !---------------------------------------------------------------------- subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) - use FV3GFS_rrfs_sd_io + use fv3atm_rrfs_sd_io implicit none !--- interface variable definitions type(GFS_sfcprop_type), intent(inout) :: Sfcprop(:) @@ -771,7 +771,7 @@ end subroutine sfc_prop_restart_read ! calls: register_restart_field, save_restart !---------------------------------------------------------------------- subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timestamp) - use FV3GFS_rrfs_sd_io + use fv3atm_rrfs_sd_io implicit none !--- interface variable definitions type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) @@ -1144,7 +1144,7 @@ end subroutine phys_restart_write ! ! calls: register_diag_field !------------------------------------------------------------------------- - subroutine fv3gfs_diag_register(Diag, Time, Atm_block, Model, xlon, xlat, axes) + subroutine fv3atm_diag_register(Diag, Time, Atm_block, Model, xlon, xlat, axes) use physcons, only: con_g !--- subroutine interface variable definitions type(GFS_externaldiag_type), intent(inout) :: Diag(:) @@ -1169,7 +1169,7 @@ subroutine fv3gfs_diag_register(Diag, Time, Atm_block, Model, xlon, xlat, axes) dtp = Model%dtp imp_physics = Model%imp_physics landsfcmdl = Model%lsm -! print *,'in fv3gfs_diag_register,ncld=',Model%ncld,Model%lsoil,Model%imp_physics, & +! print *,'in fv3atm_diag_register,ncld=',Model%ncld,Model%lsoil,Model%imp_physics, & ! ' dtp=',dtp,' landsfcmdl=',Model%lsm ! !save lon/lat for vector interpolation @@ -1184,7 +1184,7 @@ subroutine fv3gfs_diag_register(Diag, Time, Atm_block, Model, xlon, xlat, axes) enddo if (tot_diag_idx == DIAG_SIZE) then - call mpp_error(fatal, 'FV3GFS_io::fv3gfs_diag_register - need to increase parameter DIAG_SIZE') + call mpp_error(fatal, 'fv3atm_io::fv3atm_diag_register - need to increase parameter DIAG_SIZE') endif allocate(nstt(tot_diag_idx), nstt_vctbl(tot_diag_idx)) @@ -1245,10 +1245,10 @@ subroutine fv3gfs_diag_register(Diag, Time, Atm_block, Model, xlon, xlat, axes) buffer_phys_bl = zero buffer_phys_nb = zero buffer_phys_windvect = zero - if(mpp_pe() == mpp_root_pe()) print *,'in fv3gfs_diag_register, nrgst_bl=',nrgst_bl,' nrgst_nb=',nrgst_nb, & + if(mpp_pe() == mpp_root_pe()) print *,'in fv3atm_diag_register, nrgst_bl=',nrgst_bl,' nrgst_nb=',nrgst_nb, & ' nrgst_vctbl=',nrgst_vctbl, 'isco=',isco,ieco,'jsco=',jsco,jeco,' num_axes_phys=', num_axes_phys - end subroutine fv3gfs_diag_register + end subroutine fv3atm_diag_register !------------------------------------------------------------------------- @@ -1260,7 +1260,7 @@ end subroutine fv3gfs_diag_register ! ! calls: send_data !------------------------------------------------------------------------- - subroutine fv3gfs_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & + subroutine fv3atm_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & dt, time_int, time_intfull, time_radsw, time_radlw) !--- subroutine interface variable definitions type(time_type), intent(in) :: time @@ -1303,23 +1303,23 @@ subroutine fv3gfs_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & is_in = atm_block%isc js_in = atm_block%jsc -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3gfs_io. time avg, time_int=',time_int +! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. time avg, time_int=',time_int do idx = 1,tot_diag_idx if (diag(idx)%id > 0) then lcnvfac = diag(idx)%cnvfac if (diag(idx)%time_avg) then if ( trim(diag(idx)%time_avg_kind) == 'full' ) then lcnvfac = lcnvfac*rtime_intfull -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3gfs_io. full time avg, field=',trim(Diag(idx)%name),' time=',time_intfull +! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. full time avg, field=',trim(Diag(idx)%name),' time=',time_intfull else if ( trim(diag(idx)%time_avg_kind) == 'rad_lw' ) then lcnvfac = lcnvfac*min(rtime_radlw,rtime_int) -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3gfs_io. rad longwave avg, field=',trim(Diag(idx)%name),' time=',time_radlw +! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. rad longwave avg, field=',trim(Diag(idx)%name),' time=',time_radlw else if ( trim(diag(idx)%time_avg_kind) == 'rad_sw' ) then lcnvfac = lcnvfac*min(rtime_radsw,rtime_int) -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3gfs_io. rad shortwave avg, field=',trim(Diag(idx)%name),' time=',time_radsw +! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. rad shortwave avg, field=',trim(Diag(idx)%name),' time=',time_radsw else if ( trim(diag(idx)%time_avg_kind) == 'rad_swlw_min' ) then lcnvfac = lcnvfac*min(max(rtime_radsw,rtime_radlw),rtime_int) -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3gfs_io. rad swlw min avg, field=',trim(Diag(idx)%name),' time=',time_radlw,time_radsw,time_int +! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. rad swlw min avg, field=',trim(Diag(idx)%name),' time=',time_radlw,time_radsw,time_int else lcnvfac = lcnvfac*rtime_int endif @@ -1450,7 +1450,7 @@ subroutine fv3gfs_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & !--- !--- skipping other 3D variables with the following else statement !--- -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3gfs_io. 3D fields, idx=',idx,'varname=',trim(diag(idx)%name), & +! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. 3D fields, idx=',idx,'varname=',trim(diag(idx)%name), & ! 'lcnvfac=',lcnvfac, 'levo=',levo,'nx=',nx,'ny=',ny do k=1, levo do j = 1, ny @@ -1459,7 +1459,7 @@ subroutine fv3gfs_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & ii = i + isc -1 nb = Atm_block%blkno(ii,jj) ix = Atm_block%ixp(ii,jj) -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3gfs_io,sze(Diag(idx)%data(nb)%var3)=', & +! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io,sze(Diag(idx)%data(nb)%var3)=', & ! size(Diag(idx)%data(nb)%var3,1),size(Diag(idx)%data(nb)%var3,2) var3(i,j,k) = Diag(idx)%data(nb)%var3(ix,levo-k+1)*lcnvfac enddo @@ -1520,7 +1520,7 @@ subroutine fv3gfs_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & enddo - end subroutine fv3gfs_diag_output + end subroutine fv3atm_diag_output ! !------------------------------------------------------------------------- subroutine store_data(id, work, Time, idx, intpl_method, fldname) @@ -1847,7 +1847,7 @@ subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nb allocate(udimList(udimCount)) call ESMF_AttributeGet(fcst_grid, convention="NetCDF", purpose="FV3", & name="vertical_dim_labels", valueList=udimList, rc=rc) -! if(mpp_pe()==mpp_root_pe()) print *,'in fv3gfsio, vertical +! if(mpp_pe()==mpp_root_pe()) print *,'in fv3atmio, vertical ! list=',udimList(1:udimCount),'rc=',rc if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return @@ -2203,4 +2203,4 @@ end subroutine find_output_name #endif !------------------------------------------------------------------------- -end module FV3GFS_io_mod +end module fv3atm_history_io_mod diff --git a/io/FV3GFS_oro_io.F90 b/io/fv3atm_oro_io.F90 similarity index 99% rename from io/FV3GFS_oro_io.F90 rename to io/fv3atm_oro_io.F90 index 6ab57850e..37f4e15b0 100644 --- a/io/FV3GFS_oro_io.F90 +++ b/io/fv3atm_oro_io.F90 @@ -1,4 +1,4 @@ -module FV3GFS_oro_io +module fv3atm_oro_io use block_control_mod, only: block_control_type use fms2_io_mod, only: FmsNetcdfDomainFile_t, unlimited, & @@ -6,7 +6,7 @@ module FV3GFS_oro_io register_variable_attribute, register_field, & read_restart, write_restart, write_data, & get_global_io_domain_indices, variable_exists - use FV3GFS_common_io, only: get_nx_ny_from_atm + use fv3atm_common_io, only: get_nx_ny_from_atm use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys use GFS_restart, only: GFS_restart_type use mpp_mod, only: mpp_error, mpp_pe, mpp_root_pe, & @@ -307,4 +307,4 @@ subroutine Oro_scale_io_final(oro_scale) #undef IF_ASSOC_DEALLOC_NULL end subroutine Oro_scale_io_final -end module FV3GFS_oro_io +end module fv3atm_oro_io diff --git a/io/FV3GFS_restart_io.F90 b/io/fv3atm_restart_io.F90 similarity index 95% rename from io/FV3GFS_restart_io.F90 rename to io/fv3atm_restart_io.F90 index b64fe255f..712c86516 100644 --- a/io/FV3GFS_restart_io.F90 +++ b/io/fv3atm_restart_io.F90 @@ -1,14 +1,14 @@ -module FV3GFS_restart_io_mod +module fv3atm_restart_io_mod use esmf use block_control_mod, only: block_control_type use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys use GFS_restart, only: GFS_restart_type - use FV3GFS_sfc_io - use FV3GFS_common_io, only: create_2d_field_and_add_to_bundle, & + use fv3atm_sfc_io + use fv3atm_common_io, only: create_2d_field_and_add_to_bundle, & create_3d_field_and_add_to_bundle, add_zaxis_to_field - use FV3GFS_rrfs_sd_io - use FV3GFS_clm_lake_io + use fv3atm_rrfs_sd_io + use fv3atm_clm_lake_io implicit none private @@ -26,7 +26,7 @@ module FV3GFS_restart_io_mod type(Sfc_io_data_type) :: sfc type(ESMF_FieldBundle) :: phy_bundle, sfc_bundle - public FV3GFS_restart_register + public fv3atm_restart_register public fv_phy_restart_output public fv_phy_restart_bundle_setup @@ -36,7 +36,7 @@ module FV3GFS_restart_io_mod contains - subroutine FV3GFS_restart_register (Sfcprop, GFS_restart, Atm_block, Model) + subroutine fv3atm_restart_register (Sfcprop, GFS_restart, Atm_block, Model) ! this subroutine must allocate all data buffers and set the variable names ! for both 'phy' and 'sfc' restart bundles @@ -88,7 +88,7 @@ subroutine FV3GFS_restart_register (Sfcprop, GFS_restart, Atm_block, Model) call rrfs_sd%allocate_data(Model) endif - end subroutine FV3GFS_restart_register + end subroutine fv3atm_restart_register subroutine fv_phy_restart_output(GFS_Restart, Atm_block) @@ -266,4 +266,4 @@ subroutine fv_sfc_restart_bundle_setup(bundle, grid, Model, rc) end subroutine fv_sfc_restart_bundle_setup -end module FV3GFS_restart_io_mod +end module fv3atm_restart_io_mod diff --git a/io/FV3GFS_rrfs_sd_io.F90 b/io/fv3atm_rrfs_sd_io.F90 similarity index 99% rename from io/FV3GFS_rrfs_sd_io.F90 rename to io/fv3atm_rrfs_sd_io.F90 index 4acac886c..1fbbe2dfc 100644 --- a/io/FV3GFS_rrfs_sd_io.F90 +++ b/io/fv3atm_rrfs_sd_io.F90 @@ -1,4 +1,4 @@ -module FV3GFS_rrfs_sd_io +module fv3atm_rrfs_sd_io use block_control_mod, only: block_control_type use fms2_io_mod, only: FmsNetcdfDomainFile_t, unlimited, & open_file, close_file, & @@ -10,7 +10,7 @@ module FV3GFS_rrfs_sd_io GFS_data_type, kind_phys use GFS_restart, only: GFS_restart_type use GFS_diagnostics, only: GFS_externaldiag_type - use FV3GFS_common_io, only: get_nx_ny_from_atm, create_2d_field_and_add_to_bundle, & + use fv3atm_common_io, only: get_nx_ny_from_atm, create_2d_field_and_add_to_bundle, & create_3d_field_and_add_to_bundle, add_zaxis_to_field implicit none @@ -574,4 +574,4 @@ subroutine rrfs_sd_emissions_final(data) #undef IF_ASSOC_DEALLOC_NULL end subroutine rrfs_sd_emissions_final -end module FV3GFS_rrfs_sd_io +end module fv3atm_rrfs_sd_io diff --git a/io/FV3GFS_sfc_io.F90 b/io/fv3atm_sfc_io.F90 similarity index 99% rename from io/FV3GFS_sfc_io.F90 rename to io/fv3atm_sfc_io.F90 index b450ec7de..77c2bef10 100644 --- a/io/FV3GFS_sfc_io.F90 +++ b/io/fv3atm_sfc_io.F90 @@ -1,4 +1,4 @@ -module FV3GFS_sfc_io +module fv3atm_sfc_io use block_control_mod, only: block_control_type use fms2_io_mod, only: FmsNetcdfDomainFile_t, unlimited, & @@ -6,7 +6,7 @@ module FV3GFS_sfc_io register_variable_attribute, register_field, & read_restart, write_restart, write_data, & get_global_io_domain_indices, variable_exists - use FV3GFS_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data, GFS_Data_transfer, & + use fv3atm_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data, GFS_Data_transfer, & create_2d_field_and_add_to_bundle, create_3d_field_and_add_to_bundle, & add_zaxis_to_field use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys @@ -41,7 +41,7 @@ module FV3GFS_sfc_io ! The lsoil flag is only meaningful when reading:; logical, public :: is_lsoil = .false. - ! SYNONYMS: Some nvar variables had two names in FV3GFS_io.F90. They have + ! SYNONYMS: Some nvar variables had two names in fv3atm_io.F90. They have ! only one name here. The "_s" is redundant because this file only has ! surface restart variables. ! @@ -1570,4 +1570,4 @@ subroutine Sfc_io_bundle_3d_fields(sfc, bundle, grid, Model, outputfile) if(allocated(zaxis_4)) deallocate(zaxis_4) end subroutine Sfc_io_bundle_3d_fields -end module FV3GFS_sfc_io +end module fv3atm_sfc_io diff --git a/io/module_wrt_grid_comp.F90 b/io/module_wrt_grid_comp.F90 index 94e568073..3cd17002f 100644 --- a/io/module_wrt_grid_comp.F90 +++ b/io/module_wrt_grid_comp.F90 @@ -2024,7 +2024,7 @@ subroutine wrt_run(wrt_comp, imp_state_write, exp_state_write,clock,rc) if (mype == lead_write_task) then !** write out inline post log file open(newunit=nolog,file='log.atm.inlinepost.f'//trim(cfhour),form='FORMATTED') - write(nolog,"(' completed fv3gfs fhour=',f10.3,2x,6(i4,2x))") nfhour, idate(1:6) + write(nolog,"(' completed fv3atm fhour=',f10.3,2x,6(i4,2x))") nfhour, idate(1:6) close(nolog) endif if (lprnt) then @@ -2327,7 +2327,7 @@ subroutine wrt_run(wrt_comp, imp_state_write, exp_state_write,clock,rc) if (out_phase == 1 .and. mype == lead_write_task) then !** write out log file open(newunit=nolog,file='log.atm.f'//trim(cfhour),form='FORMATTED') - write(nolog,"(' completed fv3gfs fhour=',f10.3,2x,6(i4,2x))") nfhour, idate(1:6) + write(nolog,"(' completed fv3atm fhour=',f10.3,2x,6(i4,2x))") nfhour, idate(1:6) close(nolog) endif enddo two_phase_loop diff --git a/module_fcst_grid_comp.F90 b/module_fcst_grid_comp.F90 index 3897ff43c..6557f76f8 100644 --- a/module_fcst_grid_comp.F90 +++ b/module_fcst_grid_comp.F90 @@ -55,8 +55,8 @@ module module_fcst_grid_comp use data_override_mod, only: data_override_init use fv_nggps_diags_mod, only: fv_dyn_bundle_setup - use fv3gfs_io_mod, only: fv_phys_bundle_setup - use fv3gfs_restart_io_mod, only: fv_phy_restart_bundle_setup, fv_sfc_restart_bundle_setup + use fv3atm_history_io_mod, only: fv_phys_bundle_setup + use fv3atm_restart_io_mod, only: fv_phy_restart_bundle_setup, fv_sfc_restart_bundle_setup use fv_ufs_restart_io_mod, only: fv_core_restart_bundle_setup, & fv_srf_wnd_restart_bundle_setup, & fv_tracer_restart_bundle_setup diff --git a/moving_nest/fv_moving_nest_physics.F90 b/moving_nest/fv_moving_nest_physics.F90 index 2dc6bce5b..1219617a6 100644 --- a/moving_nest/fv_moving_nest_physics.F90 +++ b/moving_nest/fv_moving_nest_physics.F90 @@ -177,7 +177,7 @@ subroutine mn_phys_reset_sfc_props(Atm, n, mn_static, Atm_block, IPD_data, ioffs IPD_data(nb)%Sfcprop%tg3(ix) = mn_static%deep_soil_temp_grid(i_idx, j_idx) - ! Follow logic from FV3/io/FV3GFS_io.F90 line 1187 + ! Follow logic from FV3/io/fv3atm_sfc_io.F90 ! TODO this will need to be more complicated if we support frac_grid !if (nint(mn_static%soil_type_grid(i_idx, j_idx)) == 14 .or. int(mn_static%soil_type_grid(i_idx, j_idx)+0.5) <= 0) then !if (nint(mn_static%soil_type_grid(i_idx, j_idx)) == 14 .or. From 305e99688406e2f53aa7d768d7680723acc5fe06 Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Mon, 29 May 2023 21:18:18 +0000 Subject: [PATCH 22/27] refactor a bit more, putting history into fv3atm_history_io.F90 and restart into fv3atm_restart_io.F90 --- atmos_model.F90 | 9 +- io/fv3atm_clm_lake_io.F90 | 6 + io/fv3atm_history_io.F90 | 1660 +++++++------------------------------ io/fv3atm_restart_io.F90 | 1446 +++++++++++++++++++++++++++----- 4 files changed, 1586 insertions(+), 1535 deletions(-) diff --git a/atmos_model.F90 b/atmos_model.F90 index 559194410..5c54aed86 100644 --- a/atmos_model.F90 +++ b/atmos_model.F90 @@ -90,13 +90,14 @@ module atmos_model_mod use stochastic_physics_wrapper_mod, only: stochastic_physics_wrapper,stochastic_physics_wrapper_end -use fv3atm_history_io_mod, only: fv3atm_restart_read, fv3atm_restart_write, & - fv3atm_checksum, & - fv3atm_diag_register, fv3atm_diag_output, & +use fv3atm_history_io_mod, only: fv3atm_diag_register, fv3atm_diag_output, & DIAG_SIZE use fv3atm_restart_io_mod, only: fv3atm_restart_register, & + fv3atm_checksum, & fv_phy_restart_output, & - fv_sfc_restart_output + fv_sfc_restart_output, & + fv3atm_restart_read, & + fv3atm_restart_write use fv_ufs_restart_io_mod, only: fv_dyn_restart_register, & fv_dyn_restart_output use fv_iau_mod, only: iau_external_data_type,getiauforcing,iau_initialize diff --git a/io/fv3atm_clm_lake_io.F90 b/io/fv3atm_clm_lake_io.F90 index 98d539277..481485a12 100644 --- a/io/fv3atm_clm_lake_io.F90 +++ b/io/fv3atm_clm_lake_io.F90 @@ -14,6 +14,12 @@ module fv3atm_clm_lake_io implicit none + private + public :: clm_lake_data_type, clm_lake_register_axes, clm_lake_allocate_data, & + clm_lake_register_fields, clm_lake_deallocate_data, clm_lake_write_axes, & + clm_lake_copy_from_grid, clm_lake_copy_to_grid, clm_lake_bundle_fields, & + clm_lake_final + type clm_lake_data_type ! The clm_lake_data_type derived type is a class that stores ! temporary arrays used to read or write CLM Lake model restart diff --git a/io/fv3atm_history_io.F90 b/io/fv3atm_history_io.F90 index 9c2f246d2..43cb33b60 100644 --- a/io/fv3atm_history_io.F90 +++ b/io/fv3atm_history_io.F90 @@ -42,8 +42,6 @@ module fv3atm_history_io_mod use GFS_diagnostics, only: GFS_externaldiag_type use fv3atm_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data - use fv3atm_sfc_io - use fv3atm_oro_io ! !----------------------------------------------------------------------- @@ -51,1087 +49,56 @@ module fv3atm_history_io_mod private !--- public interfaces --- - public fv3atm_restart_read, fv3atm_restart_write - public fv3atm_checksum public fv3atm_diag_register, fv3atm_diag_output #ifdef use_WRTCOMP public fv_phys_bundle_setup #endif - !--- GFDL filenames - character(len=32) :: fn_oro = 'oro_data.nc' - character(len=32) :: fn_oro_ls = 'oro_data_ls.nc' - character(len=32) :: fn_oro_ss = 'oro_data_ss.nc' - character(len=32) :: fn_srf = 'sfc_data.nc' - character(len=32) :: fn_phy = 'phy_data.nc' - character(len=32) :: fn_dust12m= 'dust12m_data.nc' - character(len=32) :: fn_emi = 'emi_data.nc' - character(len=32) :: fn_rrfssd = 'SMOKE_RRFS_data.nc' - - !--- GFDL FMS netcdf restart data types defined in fms2_io - type(FmsNetcdfDomainFile_t) :: Oro_restart, Sfc_restart, Phy_restart, dust12m_restart, emi_restart, rrfssd_restart - type(FmsNetcdfDomainFile_t) :: Oro_ls_restart, Oro_ss_restart - - !--- GFDL FMS restart containers - real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: phy_var3 - character(len=32), allocatable, dimension(:) :: oro_ls_ss_name - real(kind=kind_phys), allocatable, target, dimension(:,:,:) :: oro_ls_var, oro_ss_var - real(kind=kind_phys), allocatable, target, dimension(:,:,:) :: phy_var2 - - !--- Noah MP restart containers - real(kind=kind_phys) :: zhour -! - integer, parameter :: r8 = kind_phys - integer :: tot_diag_idx = 0 - integer :: total_outputlevel = 0 - integer :: isco,ieco,jsco,jeco,levo,num_axes_phys - integer :: fhzero, ncld, nsoil, imp_physics, landsfcmdl - real(4) :: dtp - logical :: lprecip_accu - character(len=64) :: Sprecip_accu - integer,dimension(:), allocatable :: nstt, nstt_vctbl, all_axes - character(20),dimension(:), allocatable :: axis_name, axis_name_vert - real(4), dimension(:,:,:), allocatable, target :: buffer_phys_bl, buffer_phys_nb - real(4), dimension(:,:,:,:), allocatable, target :: buffer_phys_windvect - real(kind=kind_phys),dimension(:,:),allocatable :: lon, lat, uwork - real(kind=kind_phys),dimension(:,:,:),allocatable:: uwork3d - logical :: uwork_set = .false. - character(128) :: uwindname integer, parameter, public :: DIAG_SIZE = 800 - real, parameter :: missing_value = 9.99e20_r8 - real, parameter:: stndrd_atmos_ps = 101325.0_r8 - real, parameter:: stndrd_atmos_lapse = 0.0065_r8 - real, parameter:: drythresh = 1.e-4_r8, zero = 0.0_r8, one = 1.0_r8 - - type(Sfc_io_data_type) :: sfc - type(Oro_io_data_type) :: oro + real, parameter :: missing_value = 9.99e20_kind_phys + real, parameter :: stndrd_atmos_ps = 101325.0_kind_phys + real, parameter :: stndrd_atmos_lapse = 0.0065_kind_phys + real, parameter :: drythresh = 1.e-4_kind_phys + real, parameter :: zero = 0.0_kind_phys, one = 1.0_kind_phys + + type history_type + integer :: tot_diag_idx = 0 + + integer :: isco=0,ieco=0,jsco=0,jeco=0,levo=0,num_axes_phys=0 + integer :: fhzero=0, ncld=0, nsoil=0, imp_physics=0, landsfcmdl=0 + real(4) :: dtp=0 + integer,dimension(:), pointer :: nstt => null() + integer,dimension(:), pointer :: nstt_vctbl => null() + integer,dimension(:), pointer :: all_axes => null() + character(20),dimension(:), pointer :: axis_name => null() + real(4), dimension(:,:,:), pointer :: buffer_phys_bl => null() + real(4), dimension(:,:,:), pointer :: buffer_phys_nb => null() + real(4), dimension(:,:,:,:), pointer :: buffer_phys_windvect => null() + real(kind=kind_phys),dimension(:,:),pointer :: lon => null() + real(kind=kind_phys),dimension(:,:),pointer :: lat => null() + real(kind=kind_phys),dimension(:,:),pointer :: uwork => null() + real(kind=kind_phys),dimension(:,:,:),pointer:: uwork3d => null() + logical :: uwork_set = .false. + character(128) :: uwindname = "(noname)" + + !--- miscellaneous other variables + logical :: use_wrtgridcomp_output = .FALSE. + contains + procedure :: register => history_type_register + procedure :: output => history_type_output + procedure :: store_data => history_type_store_data + procedure :: store_data3D => history_type_store_data3D +#ifdef use_WRTCOMP + procedure :: bundle_setup => history_type_bundle_setup + procedure :: add_field_to_phybundle => history_type_add_field_to_phybundle + procedure :: find_output_name => history_type_find_output_name +#endif + end type history_type -!--- miscellaneous other variables - logical :: use_wrtgridcomp_output = .FALSE. - logical :: module_is_initialized = .FALSE. + type(history_type) :: shared_history_data CONTAINS -!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -! -! PUBLIC SUBROUTINES -! -!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -! -!-------------------- -! fv3atm_restart_read -!-------------------- - subroutine fv3atm_restart_read (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) - type(GFS_data_type), intent(inout) :: GFS_Data(:) - type(GFS_restart_type), intent(inout) :: GFS_Restart - type(block_control_type), intent(in) :: Atm_block - type(GFS_control_type), intent(inout) :: Model - type(domain2d), intent(in) :: fv_domain - logical, intent(in) :: warm_start - logical, intent(in) :: ignore_rst_cksum - - !--- read in surface data from chgres - call sfc_prop_restart_read (GFS_Data%Sfcprop, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) - - !--- read in physics restart data - call phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_rst_cksum) - - end subroutine fv3atm_restart_read - -!--------------------- -! fv3atm_restart_write -!--------------------- - subroutine fv3atm_restart_write (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, timestamp) - type(GFS_data_type), intent(inout) :: GFS_Data(:) - type(GFS_restart_type), intent(inout) :: GFS_Restart - type(block_control_type), intent(in) :: Atm_block - 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 - 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) - - end subroutine fv3atm_restart_write - - -!---------------- -! fv3atm_checksum -!---------------- - subroutine fv3atm_checksum (Model, GFS_Data, Atm_block) - !--- interface variables - type(GFS_control_type), intent(in) :: Model - type(GFS_data_type), intent(in) :: GFS_Data(:) - type (block_control_type), intent(in) :: Atm_block - !--- local variables - integer :: outunit, j, i, ix, nb, isc, iec, jsc, jec, lev, ct, l, ntr, k - integer :: nsfcprop2d, idx_opt, nt - real(kind=kind_phys), allocatable :: temp2d(:,:,:) - real(kind=kind_phys), allocatable :: temp3d(:,:,:,:) - real(kind=kind_phys), allocatable :: temp3dlevsp1(:,:,:,:) - integer, allocatable :: ii1(:), jj1(:) - character(len=32) :: name - - isc = Model%isc - iec = Model%isc+Model%nx-1 - jsc = Model%jsc - jec = Model%jsc+Model%ny-1 - lev = Model%levs - - ntr = size(GFS_Data(1)%Statein%qgrs,3) - - nsfcprop2d = 93 - if (Model%lsm == Model%lsm_noahmp) then - nsfcprop2d = nsfcprop2d + 49 - if (Model%use_cice_alb) then - nsfcprop2d = nsfcprop2d + 4 - endif - elseif (Model%lsm == Model%lsm_ruc) then - nsfcprop2d = nsfcprop2d + 4 + 12 - if (Model%rdlai) then - nsfcprop2d = nsfcprop2d + 1 - endif - else - if (Model%use_cice_alb) then - nsfcprop2d = nsfcprop2d + 4 - endif - endif - - if (Model%nstf_name(1) > 0) then - nsfcprop2d = nsfcprop2d + 16 - endif - - if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_flake) then - nsfcprop2d = nsfcprop2d + 10 - endif - - allocate (temp2d(isc:iec,jsc:jec,nsfcprop2d+Model%ntot2d+Model%nctp)) - allocate (temp3d(isc:iec,jsc:jec,1:lev,14+Model%ntot3d+2*ntr)) - allocate (temp3dlevsp1(isc:iec,jsc:jec,1:lev+1,3)) - - temp2d = zero - temp3d = zero - temp3dlevsp1 = zero - -!$omp parallel do default(shared) private(i, j, k, nb, ix, nt, ii1, jj1) - block_loop: do nb = 1, Atm_block%nblks - allocate(ii1(Atm_block%blksz(nb))) - allocate(jj1(Atm_block%blksz(nb))) - ii1=Atm_block%index(nb)%ii - isc + 1 - jj1=Atm_block%index(nb)%jj - jsc + 1 - - ! Copy into temp2d - nt=0 - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Statein%pgr) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%slmsk) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tsfc) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tisfc) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snowd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%zorl) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%fice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%hprime(:,1)) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sncovr) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snoalb) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%alvsf) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%alnsf) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%alvwf) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%alnwf) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%facsf) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%facwf) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%slope) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%shdmin) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%shdmax) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tg3) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%vfrac) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%vtype) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%stype) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%uustar) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%oro) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%oro_uf) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%hice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%weasd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%canopy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%ffmm) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%ffhh) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%f10m) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tprcp) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%srflag) - lsm_choice: if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%slc) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%smc) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%stc) - elseif (Model%lsm == Model%lsm_ruc) then - do k=1,3 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sh2o(:,k)) - enddo - ! Combine levels 4 to lsoil_lsm (9 for RUC) into one - nt=nt+1 - do ix=1,Atm_block%blksz(nb) - temp2d(ii1(ix),jj1(ix),nt) = sum(GFS_Data(nb)%Sfcprop%sh2o(ix,4:Model%lsoil_lsm)) - enddo - do k=1,3 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%smois(:,k)) - enddo - ! Combine levels 4 to lsoil_lsm (9 for RUC) into one - nt=nt+1 - do ix=1,Atm_block%blksz(nb) - temp2d(ii1(ix),jj1(ix),nt) = sum(GFS_Data(nb)%Sfcprop%smois(ix,4:Model%lsoil_lsm)) - enddo - do k=1,3 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tslb(:,k)) - enddo - ! Combine levels 4 to lsoil_lsm (9 for RUC) into one - nt=nt+1 - do ix=1,Atm_block%blksz(nb) - temp2d(ii1(ix),jj1(ix),nt) = sum(GFS_Data(nb)%Sfcprop%tslb(ix,4:Model%lsoil_lsm)) - enddo - endif lsm_choice - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%t2m) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%q2m) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%nirbmdi) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%nirdfdi) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%visbmdi) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%visdfdi) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%nirbmui) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%nirdfui) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%visbmui) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%visdfui) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%sfcdsw) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%sfcnsw) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%sfcdlw) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%xlon) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%xlat) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%xlat_d) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%sinlat) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%coslat) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%area) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%dx) - if (Model%ntoz > 0) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%ddy_o3) - endif - if (Model%h2o_phys) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%ddy_h) - endif - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Cldprop%cv) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Cldprop%cvt) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Cldprop%cvb) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Radtend%sfalb) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Radtend%coszen) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Radtend%tsflw) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Radtend%semis) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Radtend%coszdg) - - ! Radtend%sfcfsw is an array of derived type, so we copy all - ! eight elements of the type in one loop - do ix=1,Atm_block%blksz(nb) - temp2d(ii1(ix),jj1(ix),nt+1) = GFS_Data(nb)%Radtend%sfcfsw(ix)%upfxc - temp2d(ii1(ix),jj1(ix),nt+2) = GFS_Data(nb)%Radtend%sfcfsw(ix)%upfx0 - temp2d(ii1(ix),jj1(ix),nt+3) = GFS_Data(nb)%Radtend%sfcfsw(ix)%dnfxc - temp2d(ii1(ix),jj1(ix),nt+4) = GFS_Data(nb)%Radtend%sfcfsw(ix)%dnfx0 - temp2d(ii1(ix),jj1(ix),nt+5) = GFS_Data(nb)%Radtend%sfcflw(ix)%upfxc - temp2d(ii1(ix),jj1(ix),nt+6) = GFS_Data(nb)%Radtend%sfcflw(ix)%upfx0 - temp2d(ii1(ix),jj1(ix),nt+7) = GFS_Data(nb)%Radtend%sfcflw(ix)%dnfxc - temp2d(ii1(ix),jj1(ix),nt+8) = GFS_Data(nb)%Radtend%sfcflw(ix)%dnfx0 - enddo - nt = nt + 8 - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tiice(:,1)) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tiice(:,2)) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdirvis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdirnir_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdifvis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdifnir_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%emis_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%emis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sncovr_ice) - - if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdirvis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdirnir_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdifvis_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdifnir_ice) - endif - - lsm_choice_2: if (Model%lsm == Model%lsm_noahmp) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tvxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tgxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%canicexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%canliqxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%eahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tahxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%cmxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%chxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%fwetxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sneqvoxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%alboldxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%qsnowxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%wslakexy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%zwtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%waxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%wtxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%lfmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%rtmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%stmassxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%woodxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%stblcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%fastcpxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xsaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xlaixy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%taussxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%smcwtdxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%deeprechxy) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%rechxy) - - ! These five arrays use bizarre indexing, so we use loops: - do k=-2,0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snicexy(:,k)) - enddo - - do k=-2,0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snliqxy(:,k)) - enddo - - do k=-2,0 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tsnoxy(:,k)) - enddo - - do k=1,4 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%smoiseq(:,k)) - enddo - - do k=-2,4 - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%zsnsoxy(:,k)) - enddo - elseif (Model%lsm == Model%lsm_ruc) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%wetness) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%clw_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%clw_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%qwv_surf_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%qwv_surf_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tsnow_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tsnow_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snowfallac_land) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snowfallac_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sfalb_lnd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sfalb_lnd_bck) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sfalb_ice) - if (Model%rdlai) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xlaixy) - endif - endif lsm_choice_2 - - nstf_name_choice: if (Model%nstf_name(1) > 0) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tref) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%z_c) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%c_0) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%c_d) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%w_0) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%w_d) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xt) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xs) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xu) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xz) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%zm) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xtts) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xzts) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%ifd) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%dt_cool) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%qrain) - endif nstf_name_choice - -! Flake - if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%T_snow) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%T_ice) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%h_ML) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%t_ML) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%t_mnw) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%h_talb) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%t_talb) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%t_bot1) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%t_bot2) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%c_t) - endif - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Tbd%phy_f2d) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Tbd%phy_fctd) - - ! Copy to temp3dlevsp1 - nt=0 - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3dlevsp1, GFS_Data(nb)%Statein%phii) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3dlevsp1, GFS_Data(nb)%Statein%prsi) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3dlevsp1, GFS_Data(nb)%Statein%prsik) - - ! Copy to temp3d - nt=0 - - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%phil) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%prsl) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%prslk) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%ugrs) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%vgrs) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%vvl) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%tgrs) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Stateout%gu0) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Stateout%gv0) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Stateout%gt0) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Radtend%htrsw) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Radtend%htrlw) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Radtend%swhc) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Radtend%lwhc) - do l = 1,Model%ntot3d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Tbd%phy_f3d(:,:,l)) - enddo - do l = 1,ntr - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%qgrs(:,:,l)) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Stateout%gq0(:,:,l)) - enddo - enddo block_loop - - - outunit = stdout() - do i = 1,nsfcprop2d+Model%ntot2d+Model%nctp - write (name, '(i3.3,3x,4a)') i, ' 2d ' - write(outunit,100) name, mpp_chksum(temp2d(:,:,i:i)) - enddo - do i = 1,3 - write (name, '(i2.2,3x,4a)') i, ' 3d levsp1' - write(outunit,100) name, mpp_chksum(temp3dlevsp1(:,:,:,i:i)) - enddo - do i = 1,14+Model%ntot3d+2*ntr - write (name, '(i2.2,3x,4a)') i, ' 3d levs' - write(outunit,100) name, mpp_chksum(temp3d(:,:,:,i:i)) - enddo -100 format("CHECKSUM::",A32," = ",Z20) - - deallocate(temp2d) - deallocate(temp3d) - deallocate(temp3dlevsp1) - end subroutine fv3atm_checksum - -!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -! -! PRIVATE SUBROUTINES -! -!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -!---------------------------------------------------------------------- -! sfc_prop_restart_read -!---------------------------------------------------------------------- -! creates and populates a data type which is then used to "register" -! restart variables with the GFDL FMS restart subsystem. -! calls a GFDL FMS routine to restore the data from a restart file. -! calculates sncovr if it is not present in the restart file. -! -! 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, ignore_rst_cksum) - use fv3atm_rrfs_sd_io - implicit none - !--- interface variable definitions - type(GFS_sfcprop_type), intent(inout) :: Sfcprop(:) - type (block_control_type), intent(in) :: Atm_block - type(GFS_control_type), intent(inout) :: Model - type (domain2d), intent(in) :: fv_domain - logical, intent(in) :: warm_start - logical, intent(in) :: ignore_rst_cksum - !--- local variables - integer :: i, j, k, ix, lsoil, num, nb, i_start, j_start, i_end, j_end, nt, n - integer :: isc, iec, jsc, jec, npz, nx, ny - integer :: id_restart - integer :: nvar_o2 - integer :: nvar_oro_ls_ss - integer :: nvar_vegfr, nvar_soilfr - integer :: isnow - integer, allocatable :: ii1(:), jj1(:) - real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() - real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() - 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() - real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_fr => NULL() - !--- local variables for sncovr calculation - 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 :: override_frac_grid - - type(clm_lake_data_type) :: clm_lake - type(rrfs_sd_state_type) :: rrfs_sd_state - type(rrfs_sd_emissions_type) :: rrfs_sd_emis - type(Oro_scale_io_data_type) :: oro_ss - type(Oro_scale_io_data_type) :: oro_ls - - nvar_vegfr = Model%nvegcat - nvar_soilfr = Model%nsoilcat - - isc = Atm_block%isc - iec = Atm_block%iec - jsc = Atm_block%jsc - jec = Atm_block%jec - 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) ) - - call oro%register(Model,Oro_restart,Atm_block) - - !--- read the orography restart/data - call mpp_error(NOTE,'reading topographic/orographic information from INPUT/oro_data.tile*.nc') - call read_restart(Oro_restart, ignore_checksum=ignore_rst_cksum) - call close_file(Oro_restart) - - !--- copy data into GFS containers - call oro%copy(Model, Sfcprop, Atm_block) - - if_smoke: if(Model%rrfs_sd) then ! for RRFS-SD - - !--- Dust input FILE - !--- open file - infile=trim(indir)//'/'//trim(fn_dust12m) - amiopen=open_file(dust12m_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) ) - - !--- Register axes and variables, allocate memory: - call rrfs_sd_emis%register_dust12m(dust12m_restart, Atm_block) - - !--- read new GSL created dust12m restart/data - call mpp_error(NOTE,'reading dust12m information from INPUT/dust12m_data.tile*.nc') - call read_restart(dust12m_restart) - call close_file(dust12m_restart) - - !--- Copy to Sfcprop and free temporary arrays: - call rrfs_sd_emis%copy_dust12m(Sfcprop, Atm_block) - - !---------------------------------------------- - - !--- open anthropogenic emission file - infile=trim(indir)//'/'//trim(fn_emi) - amiopen=open_file(emi_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) ) - - ! Register axes and variables, allocate memory - call rrfs_sd_emis%register_emi(emi_restart, Atm_block) - - !--- read anthropogenic emi restart/data - call mpp_error(NOTE,'reading emi information from INPUT/emi_data.tile*.nc') - call read_restart(emi_restart) - call close_file(emi_restart) - - !--- Copy to Sfcprop and free temporary arrays: - call rrfs_sd_emis%copy_emi(Sfcprop, Atm_block) - - !---------------------------------------------- - - !--- Dust input FILE - !--- open file - infile=trim(indir)//'/'//trim(fn_rrfssd) - amiopen=open_file(rrfssd_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) ) - - ! Register axes and variables, allocate memory - call rrfs_sd_emis%register_fire(rrfssd_restart, Atm_block) - - !--- read new GSL created rrfssd restart/data - call mpp_error(NOTE,'reading rrfssd information from INPUT/SMOKE_RRFS_data.nc') - call read_restart(rrfssd_restart) - call close_file(rrfssd_restart) - - !--- Copy to Sfcprop and free temporary arrays: - call rrfs_sd_emis%copy_fire(Sfcprop, Atm_block) - - endif if_smoke ! RRFS_SD - - !--- 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 - - if ( (Model%gwd_opt==3 .or. Model%gwd_opt==33) .or. & - ( (Model%gwd_opt==2 .or. Model%gwd_opt==22) .and. & - Model%do_gsl_drag_ls_bl ) ) 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) ) - call oro_ls%register(Model,Oro_ls_restart,Atm_block) - !--- read new GSL created orography restart/data - call mpp_error(NOTE,'reading topographic/orographic information from & - &INPUT/oro_data_ls.tile*.nc') - call read_restart(Oro_ls_restart, ignore_checksum=ignore_rst_cksum) - call close_file(Oro_ls_restart) - call oro_ls%copy(Sfcprop,Atm_block,1) - endif - - !--- 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) ) - call oro_ss%register(Model,Oro_ss_restart,Atm_block) - call mpp_error(NOTE,'reading topographic/orographic information from & - &INPUT/oro_data_ss.tile*.nc') - call read_restart(Oro_ss_restart, ignore_checksum=ignore_rst_cksum) - call close_file(Oro_ss_restart) - call oro_ss%copy(Sfcprop,Atm_block,15) - 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)) - - if(sfc%allocate_arrays(Model, Atm_block, .true., warm_start)) then - call sfc%fill_2d_names(Model, warm_start) - call sfc%register_axes(Model, Sfc_restart, .true., warm_start) - - ! Tell CLM Lake to allocate data, and register its axes and fields - if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then - call clm_lake%allocate_data(Model) - call clm_lake%copy_from_grid(Model,Atm_block,Sfcprop) - call clm_lake%register_axes(Model, Sfc_restart) - call clm_lake%register_fields(Sfc_restart) - endif - - if(Model%rrfs_sd) then - call rrfs_sd_state%allocate_data(Model) - call rrfs_sd_state%fill_data(Model, Atm_block, Sfcprop) - call rrfs_sd_state%register_axis(Model, Sfc_restart) - call rrfs_sd_state%register_fields(Sfc_restart) - endif - - call sfc%register_2d_fields(Model,Sfc_restart,.true.,warm_start) - endif ! if not allocated - - call sfc%fill_3d_names(Model,warm_start) - call sfc%register_3d_fields(Model,Sfc_restart,.true.,warm_start) - call sfc%init_fields(Model) - - !--- read the surface restart/data - call mpp_error(NOTE,'reading surface properties data from INPUT/sfc_data.tile*.nc') - call read_restart(Sfc_restart, ignore_checksum=ignore_rst_cksum) - call close_file(Sfc_restart) - - ! Tell clm_lake to copy data to temporary arrays - if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then - call clm_lake%copy_to_grid(Model,Atm_block,Sfcprop) - endif - - if(Model%rrfs_sd) then - call rrfs_sd_state%copy_to_grid(Model,Atm_block,Sfcprop) - end if - -! 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)) -! write(0,*)' sfc%var2=',sfc%var2(:,:,12) - - !--- place the data into the block GFS containers - override_frac_grid=Model%frac_grid - call sfc%copy_to_grid(Model, Atm_block, Sfcprop, warm_start, override_frac_grid) - Model%frac_grid=override_frac_grid - - call mpp_error(NOTE, 'gfs_driver:: - after put to container ') - - call sfc%apply_safeguards(Model, Atm_block, Sfcprop) - - ! A standard-compliant Fortran 2003 compiler will call clm_lake_final and rrfs_sd_final here. - - end subroutine sfc_prop_restart_read - - -!---------------------------------------------------------------------- -! sfc_prop_restart_write -!---------------------------------------------------------------------- -! routine to write out GFS surface restarts via the GFDL FMS restart -! subsystem. -! takes an optional argument to append timestamps for intermediate -! restarts. -! -! calls: register_restart_field, save_restart -!---------------------------------------------------------------------- - subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timestamp) - use fv3atm_rrfs_sd_io - implicit none - !--- interface variable definitions - type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) - type(block_control_type), intent(in) :: Atm_block - type(GFS_control_type), intent(in) :: Model - type(domain2d), intent(in) :: fv_domain - character(len=32), optional, intent(in) :: timestamp - !--- local variables - integer :: i, j, k, nb, ix, lsoil, num, nt - integer :: isc, iec, jsc, jec, npz, nx, ny - integer :: id_restart - logical :: mand - integer, allocatable :: ii1(:), jj1(:) - character(len=32) :: fn_srf = 'sfc_data.nc' - real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() - real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() - 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() - real(kind_phys) :: ice - !--- 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 - type(clm_lake_data_type), target :: clm_lake - !--- temporary variables for storing rrfs_sd fields - type(rrfs_sd_state_type) :: rrfs_sd_state - - isc = Atm_block%isc - iec = Atm_block%iec - jsc = Atm_block%jsc - jec = Atm_block%jec - npz = Atm_block%npz - nx = (iec - isc + 1) - ny = (jec - jsc + 1) - - !--- 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: if( amiopen ) then - call sfc%register_axes(Model, Sfc_restart, .false., .true.) - call sfc%write_axes(Model, Sfc_restart) - else - call mpp_error(FATAL, 'Error in opening file'//trim(infile) ) - end if if_amiopen - - ! Tell clm_lake to allocate data, register its axes, and call write_data for each axis's variable - if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then - call clm_lake%allocate_data(Model) - call clm_lake%register_axes(Model, Sfc_restart) - call clm_lake%write_axes(Model, Sfc_restart) - endif - - if(Model%rrfs_sd) then - call rrfs_sd_state%allocate_data(Model) - call rrfs_sd_state%register_axis(Model,Sfc_restart) - call rrfs_sd_state%write_axis(Model,Sfc_restart) - end if - - if (sfc%allocate_arrays(Model, Atm_block, .false., .true.)) then - call sfc%fill_2d_names(Model,.true.) - end if - - if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then - ! Tell clm_lake to register all of its fields - call clm_lake%register_fields(Sfc_restart) - endif - - if(Model%rrfs_sd) then - call rrfs_sd_state%register_fields(Sfc_restart) - endif - - ! Register 2D surface property fields (except lake, smoke, and dust) - call sfc%register_2d_fields(Model, Sfc_restart, .false., .true.) - - ! Determine list of 3D surface property fields names: - call sfc%fill_3d_names(Model, .true.) - - ! Register 3D surface property fields (except lake, smoke, and dust) - call sfc%register_3d_fields(Model, Sfc_restart, .false., .true.) - - ! Tell clm_lake to copy Sfcprop data to its internal temporary arrays. - if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then - call clm_lake%copy_from_grid(Model,Atm_block,Sfcprop) - endif - - if(Model%rrfs_sd) then - call rrfs_sd_state%copy_from_grid(Model,Atm_block,Sfcprop) - endif - - call sfc%copy_from_grid(Model, Atm_block, Sfcprop) - - call write_restart(Sfc_restart) - call close_file(Sfc_restart) - - ! A standard-compliant Fortran 2003 compiler will call rrfs_sd_final and clm_lake_final here - - end subroutine sfc_prop_restart_write - -!---------------------------------------------------------------------- -! phys_restart_read -!---------------------------------------------------------------------- -! creates and populates a data type which is then used to "register" -! restart variables with the GFDL FMS restart subsystem. -! calls a GFDL FMS routine to restore the data from a restart file. -! calculates sncovr if it is not present in the restart file. -! -! calls: register_restart_field, restart_state, free_restart -! -! opens: phys_data.tile?.nc -! -!---------------------------------------------------------------------- - subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_rst_cksum) - !--- interface variable definitions - type(GFS_restart_type), intent(in) :: GFS_Restart - type(block_control_type), intent(in) :: Atm_block - type(GFS_control_type), intent(in) :: Model - type(domain2d), intent(in) :: fv_domain - logical, intent(in) :: ignore_rst_cksum - !--- local variables - integer :: i, j, k, nb, ix, num - integer :: isc, iec, jsc, jec, npz, nx, ny - integer :: id_restart - integer :: nvar2d, nvar3d, fdiag, ldiag - 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 - jsc = Atm_block%jsc - jec = Atm_block%jec - npz = Atm_block%npz - nx = (iec - isc + 1) - ny = (jec - jsc + 1) - - nvar2d = GFS_Restart%num2d - 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)) - allocate (phy_var3(nx,ny,npz,nvar3d)) - phy_var2 = zero - phy_var3 = zero - - 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) - 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, ignore_checksum=ignore_rst_cksum) - 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) - do num = 1,nvar2d - do nb = 1,Atm_block%nblks - 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 - GFS_Restart%data(nb,num)%var2p(ix) = phy_var2(i,j,num) - enddo - enddo - enddo - !-- if restart from init time, reset accumulated diag fields - if( Model%phour < 1.e-7) then - do num = fdiag,ldiag -!$omp parallel do default(shared) private(i, j, nb, ix) - do nb = 1,Atm_block%nblks - 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 - GFS_Restart%data(nb,num)%var2p(ix) = zero - enddo - enddo - enddo - endif - do num = 1,nvar3d -!$omp parallel do default(shared) private(i, j, k, nb, ix) - do nb = 1,Atm_block%nblks - do k=1,npz - 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 - GFS_Restart%data(nb,num)%var3p(ix,k) = phy_var3(i,j,k,num) - enddo - enddo - enddo - enddo - - end subroutine phys_restart_read - - -!---------------------------------------------------------------------- -! phys_restart_write -!---------------------------------------------------------------------- -! routine to write out GFS surface restarts via the GFDL FMS restart -! subsystem. -! takes an optional argument to append timestamps for intermediate -! restarts. -! -! calls: register_restart_field, save_restart -!---------------------------------------------------------------------- - subroutine phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timestamp) - !--- interface variable definitions - type(GFS_restart_type), intent(in) :: GFS_Restart - type(block_control_type), intent(in) :: Atm_block - type(GFS_control_type), intent(in) :: Model - type(domain2d), intent(in) :: fv_domain - character(len=32), optional, intent(in) :: timestamp - !--- local variables - integer :: i, j, k, nb, ix, num - integer :: isc, iec, jsc, jec, npz, nx, ny - integer :: id_restart - 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 - jsc = Atm_block%jsc - jec = Atm_block%jec - npz = Atm_block%npz - nx = (iec - isc + 1) - ny = (jec - jsc + 1) - nvar2d = GFS_Restart%num2d - nvar3d = GFS_Restart%num3d - - !--- 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 - 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) - 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) - enddo - enddo - enddo - !--- 3D variables -!$omp parallel do default(shared) private(i, j, k, num, nb, ix) - do num = 1,nvar3d - do nb = 1,Atm_block%nblks - do k=1,npz - 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) - enddo - enddo - enddo - enddo - - call write_restart(Phy_restart) - call close_file(Phy_restart) - - end subroutine phys_restart_write - !------------------------------------------------------------------------- !--- gfdl_diag_register --- !------------------------------------------------------------------------- @@ -1146,7 +113,24 @@ end subroutine phys_restart_write !------------------------------------------------------------------------- subroutine fv3atm_diag_register(Diag, Time, Atm_block, Model, xlon, xlat, axes) use physcons, only: con_g + implicit none +!--- subroutine interface variable definitions + type(GFS_externaldiag_type), intent(inout) :: Diag(:) + type(time_type), intent(in) :: Time + type (block_control_type), intent(in) :: Atm_block + type(GFS_control_type), intent(in) :: Model + real(kind=kind_phys), intent(in) :: xlon(:,:) + real(kind=kind_phys), intent(in) :: xlat(:,:) + integer, dimension(4), intent(in) :: axes + + call shared_history_data%register(Diag, Time, Atm_block, Model, xlon, xlat, axes) + end subroutine fv3atm_diag_register + + subroutine history_type_register(hist, Diag, Time, Atm_block, Model, xlon, xlat, axes) + use physcons, only: con_g + implicit none !--- subroutine interface variable definitions + class(history_type) :: hist type(GFS_externaldiag_type), intent(inout) :: Diag(:) type(time_type), intent(in) :: Time type (block_control_type), intent(in) :: Atm_block @@ -1156,45 +140,46 @@ subroutine fv3atm_diag_register(Diag, Time, Atm_block, Model, xlon, xlat, axes) integer, dimension(4), intent(in) :: axes !--- local variables integer :: idx, nrgst_bl, nrgst_nb, nrgst_vctbl - - isco = Atm_block%isc - ieco = Atm_block%iec - jsco = Atm_block%jsc - jeco = Atm_block%jec - levo = model%levs - fhzero = nint(Model%fhzero) -! ncld = Model%ncld - ncld = Model%imp_physics - nsoil = Model%lsoil - dtp = Model%dtp - imp_physics = Model%imp_physics - landsfcmdl = Model%lsm -! print *,'in fv3atm_diag_register,ncld=',Model%ncld,Model%lsoil,Model%imp_physics, & -! ' dtp=',dtp,' landsfcmdl=',Model%lsm + integer :: total_outputlevel = 0 + + hist%isco = Atm_block%isc + hist%ieco = Atm_block%iec + hist%jsco = Atm_block%jsc + hist%jeco = Atm_block%jec + hist%levo = model%levs + hist%fhzero = nint(Model%fhzero) +! hist%ncld = Model%ncld + hist%ncld = Model%imp_physics + hist%nsoil = Model%lsoil + hist%dtp = Model%dtp + hist%imp_physics = Model%imp_physics + hist%landsfcmdl = Model%lsm +! print *,'in fv3atm_diag_register,hist%ncld=',Model%ncld,Model%lsoil,Model%imp_physics, & +! ' hist%dtp=',hist%dtp,' hist%landsfcmdl=',Model%lsm ! !save lon/lat for vector interpolation - allocate(lon(isco:ieco,jsco:jeco)) - allocate(lat(isco:ieco,jsco:jeco)) - lon = xlon - lat = xlat + allocate(hist%lon(hist%isco:hist%ieco,hist%jsco:hist%jeco)) + allocate(hist%lat(hist%isco:hist%ieco,hist%jsco:hist%jeco)) + hist%lon = xlon + hist%lat = xlat do idx = 1,DIAG_SIZE if (trim(Diag(idx)%name) == '') exit - tot_diag_idx = idx + hist%tot_diag_idx = idx enddo - if (tot_diag_idx == DIAG_SIZE) then + if (hist%tot_diag_idx == DIAG_SIZE) then call mpp_error(fatal, 'fv3atm_io::fv3atm_diag_register - need to increase parameter DIAG_SIZE') endif - allocate(nstt(tot_diag_idx), nstt_vctbl(tot_diag_idx)) - nstt = 0 - nstt_vctbl = 0 + allocate(hist%nstt(hist%tot_diag_idx), hist%nstt_vctbl(hist%tot_diag_idx)) + hist%nstt = 0 + hist%nstt_vctbl = 0 nrgst_bl = 0 nrgst_nb = 0 nrgst_vctbl = 0 - num_axes_phys = 2 - do idx = 1,tot_diag_idx + hist%num_axes_phys = 2 + do idx = 1,hist%tot_diag_idx if (diag(idx)%axes == -99) then call mpp_error(fatal, 'gfs_driver::gfs_diag_register - attempt to register an undefined variable') endif @@ -1205,50 +190,50 @@ subroutine fv3atm_diag_register(Diag, Time, Atm_block, Model, xlon, xlat, axes) if (Diag(idx)%axes == 2) then if( index(trim(Diag(idx)%intpl_method),'bilinear') > 0 ) then nrgst_bl = nrgst_bl + 1 - nstt(idx) = nrgst_bl + hist%nstt(idx) = nrgst_bl else if (trim(Diag(idx)%intpl_method) == 'nearest_stod' ) then nrgst_nb = nrgst_nb + 1 - nstt(idx) = nrgst_nb + hist%nstt(idx) = nrgst_nb endif if(trim(Diag(idx)%intpl_method) == 'vector_bilinear') then if(Diag(idx)%name(1:1) == 'v' .or. Diag(idx)%name(1:1) == 'V') then nrgst_vctbl = nrgst_vctbl + 1 - nstt_vctbl(idx) = nrgst_vctbl -! print *,'in phy_setup, vector_bilinear, name=', trim(Diag(idx)%name),' nstt_vctbl=', nstt_vctbl(idx), 'idx=',idx + hist%nstt_vctbl(idx) = nrgst_vctbl +! print *,'in phy_setup, vector_bilinear, name=', trim(Diag(idx)%name),' nstt_vctbl=', hist%nstt_vctbl(idx), 'idx=',idx endif endif else if (diag(idx)%axes == 3) then if( index(trim(diag(idx)%intpl_method),'bilinear') > 0 ) then - nstt(idx) = nrgst_bl + 1 - nrgst_bl = nrgst_bl + levo + hist%nstt(idx) = nrgst_bl + 1 + nrgst_bl = nrgst_bl + hist%levo else if (trim(diag(idx)%intpl_method) == 'nearest_stod' ) then - nstt(idx) = nrgst_nb + 1 - nrgst_nb = nrgst_nb + levo + hist%nstt(idx) = nrgst_nb + 1 + nrgst_nb = nrgst_nb + hist%levo endif if(trim(diag(idx)%intpl_method) == 'vector_bilinear') then if(diag(idx)%name(1:1) == 'v' .or. diag(idx)%name(1:1) == 'V') then - nstt_vctbl(idx) = nrgst_vctbl + 1 - nrgst_vctbl = nrgst_vctbl + levo -! print *,'in phy_setup, vector_bilinear, name=', trim(diag(idx)%name),' nstt_vctbl=', nstt_vctbl(idx), 'idx=',idx + hist%nstt_vctbl(idx) = nrgst_vctbl + 1 + nrgst_vctbl = nrgst_vctbl + hist%levo +! print *,'in phy_setup, vector_bilinear, name=', trim(diag(idx)%name),' nstt_vctbl=', hist%nstt_vctbl(idx), 'idx=',idx endif endif - num_axes_phys = 3 + hist%num_axes_phys = 3 endif endif enddo total_outputlevel = nrgst_bl + nrgst_nb - allocate(buffer_phys_bl(isco:ieco,jsco:jeco,nrgst_bl)) - allocate(buffer_phys_nb(isco:ieco,jsco:jeco,nrgst_nb)) - allocate(buffer_phys_windvect(3,isco:ieco,jsco:jeco,nrgst_vctbl)) - buffer_phys_bl = zero - buffer_phys_nb = zero - buffer_phys_windvect = zero + allocate(hist%buffer_phys_bl(hist%isco:hist%ieco,hist%jsco:hist%jeco,nrgst_bl)) + allocate(hist%buffer_phys_nb(hist%isco:hist%ieco,hist%jsco:hist%jeco,nrgst_nb)) + allocate(hist%buffer_phys_windvect(3,hist%isco:hist%ieco,hist%jsco:hist%jeco,nrgst_vctbl)) + hist%buffer_phys_bl = zero + hist%buffer_phys_nb = zero + hist%buffer_phys_windvect = zero if(mpp_pe() == mpp_root_pe()) print *,'in fv3atm_diag_register, nrgst_bl=',nrgst_bl,' nrgst_nb=',nrgst_nb, & - ' nrgst_vctbl=',nrgst_vctbl, 'isco=',isco,ieco,'jsco=',jsco,jeco,' num_axes_phys=', num_axes_phys + ' nrgst_vctbl=',nrgst_vctbl, 'hist%isco=',hist%isco,hist%ieco,'hist%jsco=',hist%jsco,hist%jeco,' hist%num_axes_phys=', hist%num_axes_phys - end subroutine fv3atm_diag_register + end subroutine history_type_register !------------------------------------------------------------------------- @@ -1272,6 +257,25 @@ subroutine fv3atm_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & real(kind=kind_phys), intent(in) :: time_intfull real(kind=kind_phys), intent(in) :: time_radsw real(kind=kind_phys), intent(in) :: time_radlw + + call shared_history_data%output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & + dt, time_int, time_intfull, time_radsw, time_radlw) + + end subroutine fv3atm_diag_output + + subroutine history_type_output(hist, time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & + dt, time_int, time_intfull, time_radsw, time_radlw) +!--- subroutine interface variable definitions + class(history_type) :: hist + type(time_type), intent(in) :: time + type(GFS_externaldiag_type), intent(in) :: diag(:) + type (block_control_type), intent(in) :: atm_block + integer, intent(in) :: nx, ny, levs, ntcw, ntoz + real(kind=kind_phys), intent(in) :: dt + real(kind=kind_phys), intent(in) :: time_int + real(kind=kind_phys), intent(in) :: time_intfull + real(kind=kind_phys), intent(in) :: time_radsw + real(kind=kind_phys), intent(in) :: time_radlw !--- local variables integer :: i, j, k, idx, nblks, nb, ix, ii, jj integer :: is_in, js_in, isc, jsc @@ -1304,8 +308,8 @@ subroutine fv3atm_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & js_in = atm_block%jsc ! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. time avg, time_int=',time_int - do idx = 1,tot_diag_idx - if (diag(idx)%id > 0) then + history_loop: do idx = 1,hist%tot_diag_idx + has_id: if (diag(idx)%id > 0) then lcnvfac = diag(idx)%cnvfac if (diag(idx)%time_avg) then if ( trim(diag(idx)%time_avg_kind) == 'full' ) then @@ -1324,7 +328,7 @@ subroutine fv3atm_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & lcnvfac = lcnvfac*rtime_int endif endif - if (diag(idx)%axes == 2) then + if_2d: if (diag(idx)%axes == 2) then ! Integer data int_or_real: if (associated(Diag(idx)%data(1)%int2)) then if (trim(Diag(idx)%intpl_method) == 'nearest_stod') then @@ -1338,14 +342,14 @@ subroutine fv3atm_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & var2(i,j) = real(Diag(idx)%data(nb)%int2(ix), kind=kind_phys) enddo enddo - call store_data(Diag(idx)%id, var2, Time, idx, Diag(idx)%intpl_method, Diag(idx)%name) + call hist%store_data(Diag(idx)%id, var2, Time, idx, Diag(idx)%intpl_method, Diag(idx)%name) else call mpp_error(FATAL, 'Interpolation method ' // trim(Diag(idx)%intpl_method) // ' for integer variable ' & // trim(Diag(idx)%name) // ' not supported.') endif ! Real data else ! int_or_real - if (trim(diag(idx)%mask) == 'positive_flux') then + if_mask: if (trim(diag(idx)%mask) == 'positive_flux') then !--- albedos are actually a ratio of two radiation surface properties var2(1:nx,1:ny) = 0._kind_phys do j = 1, ny @@ -1408,7 +412,7 @@ subroutine fv3atm_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & enddo enddo elseif (trim(Diag(idx)%mask) == 'pseudo_ps') then - if ( use_wrtgridcomp_output ) then + if ( hist%use_wrtgridcomp_output ) then do j = 1, ny jj = j + jsc -1 do i = 1, nx @@ -1439,11 +443,11 @@ subroutine fv3atm_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & var2(i,j) = Diag(idx)%data(nb)%var2(ix)*lcnvfac enddo enddo - endif + endif if_mask endif int_or_real ! used=send_data(Diag(idx)%id, var2, Time) ! print *,'in phys, after store_data, idx=',idx,' var=', trim(Diag(idx)%name) - call store_data(Diag(idx)%id, var2, Time, idx, Diag(idx)%intpl_method, Diag(idx)%name) + call hist%store_data(Diag(idx)%id, var2, Time, idx, Diag(idx)%intpl_method, Diag(idx)%name) ! if(trim(Diag(idx)%name) == 'totprcp_ave' ) print *,'in gfs_io, totprcp=',Diag(idx)%data(1)%var2(1:3), & ! ' lcnvfac=', lcnvfac elseif (Diag(idx)%axes == 3) then @@ -1451,8 +455,8 @@ subroutine fv3atm_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & !--- skipping other 3D variables with the following else statement !--- ! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. 3D fields, idx=',idx,'varname=',trim(diag(idx)%name), & -! 'lcnvfac=',lcnvfac, 'levo=',levo,'nx=',nx,'ny=',ny - do k=1, levo +! 'lcnvfac=',lcnvfac, 'hist%levo=',hist%levo,'nx=',nx,'ny=',ny + do k=1, hist%levo do j = 1, ny jj = j + jsc -1 do i = 1, nx @@ -1461,75 +465,26 @@ subroutine fv3atm_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & ix = Atm_block%ixp(ii,jj) ! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io,sze(Diag(idx)%data(nb)%var3)=', & ! size(Diag(idx)%data(nb)%var3,1),size(Diag(idx)%data(nb)%var3,2) - var3(i,j,k) = Diag(idx)%data(nb)%var3(ix,levo-k+1)*lcnvfac + var3(i,j,k) = Diag(idx)%data(nb)%var3(ix,hist%levo-k+1)*lcnvfac enddo enddo enddo - call store_data3D(Diag(idx)%id, var3, Time, idx, Diag(idx)%intpl_method, Diag(idx)%name) -#ifdef JUNK - else - !--- temperature tendency - if (trim(Diag(idx)%name) == 'dtemp_dt') then - var3(1:nx,1:ny,1:levs) = RESHAPE(Statein%tgrs(1:ngptc,levs:1:-1), (/nx,ny,levs/)) - var3(1:nx,1:ny,1:levs) = (RESHAPE(Stateout%gt0(1:ngptc,levs:1:-1), (/nx,ny,levs/)) & - - var3(1:nx,1:ny,1:levs))*rdt - used=send_data(Diag(idx)%id, var3, Time, is_in=is_in, js_in=js_in, ks_in=1) - endif - !--- horizontal wind component tendency - if (trim(Diag(idx)%name) == 'du_dt') then - var3(1:nx,1:ny,1:levs) = RESHAPE(Statein%ugrs(1:ngptc,levs:1:-1), (/nx,ny,levs/)) - var3(1:nx,1:ny,1:levs) = (RESHAPE(Stateout%gu0(1:ngptc,levs:1:-1), (/nx,ny,levs/)) & - - var3(1:nx,1:ny,1:levs))*rdt - used=send_data(Diag(idx)%id, var3, Time, is_in=is_in, js_in=js_in, ks_in=1) - endif - !--- meridional wind component tendency - if (trim(Diag(idx)%name) == 'dv_dt') then - var3(1:nx,1:ny,1:levs) = RESHAPE(Statein%vgrs(1:ngptc,levs:1:-1), (/nx,ny,levs/)) - var3(1:nx,1:ny,1:levs) = (RESHAPE(Stateout%gv0(1:ngptc,levs:1:-1), (/nx,ny,levs/)) & - - var3(1:nx,1:ny,1:levs))*rdt - used=send_data(Diag(idx)%id, var3, Time, is_in=is_in, js_in=js_in, ks_in=1) - endif - !--- specific humidity tendency - if (trim(Diag(idx)%name) == 'dsphum_dt') then - var3(1:nx,1:ny,1:levs) = RESHAPE(Statein%qgrs(1:ngptc,levs:1:-1,1:1), (/nx,ny,levs/)) - var3(1:nx,1:ny,1:levs) = (RESHAPE(Stateout%gq0(1:ngptc,levs:1:-1,1:1), (/nx,ny,levs/)) & - - var3(1:nx,1:ny,1:levs))*rdt - used=send_data(Diag(idx)%id, var3, Time, is_in=is_in, js_in=js_in, ks_in=1) - endif - !--- cloud water mixing ration tendency - if (trim(Diag(idx)%name) == 'dclwmr_dt') then - var3(1:nx,1:ny,1:levs) = RESHAPE(Statein%qgrs(1:ngptc,levs:1:-1,ntcw:ntcw), (/nx,ny,levs/)) - var3(1:nx,1:ny,1:levs) = (RESHAPE(Stateout%gq0(1:ngptc,levs:1:-1,ntcw:ntcw), (/nx,ny,levs/)) & - - var3(1:nx,1:ny,1:levs))*rdt - used=send_data(Diag(idx)%id, var3, Time, is_in=is_in, js_in=js_in, ks_in=1) - endif - !--- ozone mixing ration tendency -#ifdef MULTI_GASES - if (trim(Diag(idx)%name) == 'dspo3_dt') then -#else - if (trim(Diag(idx)%name) == 'do3mr_dt') then -#endif - var3(1:nx,1:ny,1:levs) = RESHAPE(Statein%qgrs(1:ngptc,levs:1:-1,ntoz:ntoz), (/nx,ny,levs/)) - var3(1:nx,1:ny,1:levs) = (RESHAPE(Stateout%gq0(1:ngptc,levs:1:-1,ntoz:ntoz), (/nx,ny,levs/)) & - - var3(1:nx,1:ny,1:levs))*rdt - used=send_data(Diag(idx)%id, var3, Time, is_in=is_in, js_in=js_in, ks_in=1) - endif -#endif - endif - endif - enddo - - - end subroutine fv3atm_diag_output -! + call hist%store_data3D(Diag(idx)%id, var3, Time, idx, Diag(idx)%intpl_method, Diag(idx)%name) + endif if_2d + endif has_id + end do history_loop + end subroutine history_type_output + ! !------------------------------------------------------------------------- - subroutine store_data(id, work, Time, idx, intpl_method, fldname) + subroutine history_type_store_data(hist,id, work, Time, idx, intpl_method, fldname) + implicit none + class(history_type) :: hist integer, intent(in) :: id integer, intent(in) :: idx #ifdef CCPP_32BIT real, intent(in) :: work(:,:) #else - real(kind=kind_phys), intent(in) :: work(ieco-isco+1,jeco-jsco+1) + real(kind=kind_phys), intent(in) :: work(hist%ieco-hist%isco+1,hist%jeco-hist%jsco+1) #endif type(time_type), intent(in) :: Time character(*), intent(in) :: intpl_method @@ -1539,81 +494,83 @@ subroutine store_data(id, work, Time, idx, intpl_method, fldname) integer k,j,i,kb,nv,i1,j1 logical used ! - if( id > 0 ) then - if( use_wrtgridcomp_output ) then - if( trim(intpl_method) == 'bilinear') then + if_has_id: if( id > 0 ) then + if_gridcomp: if( hist%use_wrtgridcomp_output ) then + if_interp: if( trim(intpl_method) == 'bilinear') then !$omp parallel do default(shared) private(i,j) - do j= jsco,jeco - do i= isco,ieco - buffer_phys_bl(i,j,nstt(idx)) = work(i-isco+1,j-jsco+1) + do j= hist%jsco,hist%jeco + do i= hist%isco,hist%ieco + hist%buffer_phys_bl(i,j,hist%nstt(idx)) = work(i-hist%isco+1,j-hist%jsco+1) enddo enddo else if(trim(intpl_method) == 'nearest_stod') then !$omp parallel do default(shared) private(i,j) - do j= jsco,jeco - do i= isco,ieco - buffer_phys_nb(i,j,nstt(idx)) = work(i-isco+1,j-jsco+1) + do j= hist%jsco,hist%jeco + do i= hist%isco,hist%ieco + hist%buffer_phys_nb(i,j,hist%nstt(idx)) = work(i-hist%isco+1,j-hist%jsco+1) enddo enddo else if(trim(intpl_method) == 'vector_bilinear') then !first save the data !$omp parallel do default(shared) private(i,j) - do j= jsco,jeco - do i= isco,ieco - buffer_phys_bl(i,j,nstt(idx)) = work(i-isco+1,j-jsco+1) + do j= hist%jsco,hist%jeco + do i= hist%isco,hist%ieco + hist%buffer_phys_bl(i,j,hist%nstt(idx)) = work(i-hist%isco+1,j-hist%jsco+1) enddo enddo - if( fldname(1:1) == 'u' .or. fldname(1:1) == 'U') then - if(.not.allocated(uwork)) allocate(uwork(isco:ieco,jsco:jeco)) + if_u_wind: if( fldname(1:1) == 'u' .or. fldname(1:1) == 'U') then + if(.not.associated(hist%uwork)) allocate(hist%uwork(hist%isco:hist%ieco,hist%jsco:hist%jeco)) !$omp parallel do default(shared) private(i,j) - do j= jsco,jeco - do i= isco,ieco - uwork(i,j) = work(i-isco+1,j-jsco+1) + do j= hist%jsco,hist%jeco + do i= hist%isco,hist%ieco + hist%uwork(i,j) = work(i-hist%isco+1,j-hist%jsco+1) enddo enddo - uwindname = fldname - uwork_set = .true. - endif - if( fldname(1:1) == 'v' .or. fldname(1:1) == 'V') then + hist%uwindname = fldname + hist%uwork_set = .true. + endif if_u_wind + if_v_wind: if( fldname(1:1) == 'v' .or. fldname(1:1) == 'V') then !set up wind vector - if( uwork_set .and. trim(uwindname(2:)) == trim(fldname(2:))) then - nv = nstt_vctbl(idx) + if( hist%uwork_set .and. trim(hist%uwindname(2:)) == trim(fldname(2:))) then + nv = hist%nstt_vctbl(idx) !$omp parallel do default(shared) private(i,j,i1,j1,sinlat,sinlon,coslon) - do j= jsco,jeco - j1 = j-jsco+1 - do i= isco,ieco - i1 = i-isco+1 - sinlat = sin(lat(i,j)) - sinlon = sin(lon(i,j)) - coslon = cos(lon(i,j)) - buffer_phys_windvect(1,i,j,nv) = uwork(i,j)*coslon - work(i1,j1)*sinlat*sinlon - buffer_phys_windvect(2,i,j,nv) = uwork(i,j)*sinlon + work(i1,j1)*sinlat*coslon - buffer_phys_windvect(3,i,j,nv) = work(i1,j1)*cos(lat(i,j)) + do j= hist%jsco,hist%jeco + j1 = j-hist%jsco+1 + do i= hist%isco,hist%ieco + i1 = i-hist%isco+1 + sinlat = sin(hist%lat(i,j)) + sinlon = sin(hist%lon(i,j)) + coslon = cos(hist%lon(i,j)) + hist%buffer_phys_windvect(1,i,j,nv) = hist%uwork(i,j)*coslon - work(i1,j1)*sinlat*sinlon + hist%buffer_phys_windvect(2,i,j,nv) = hist%uwork(i,j)*sinlon + work(i1,j1)*sinlat*coslon + hist%buffer_phys_windvect(3,i,j,nv) = work(i1,j1)*cos(hist%lat(i,j)) enddo enddo endif - uwork = zero - uwindname = '' - uwork_set = .false. - endif + hist%uwork = zero + hist%uwindname = '' + hist%uwork_set = .false. + endif if_v_wind - endif + endif if_interp else used = send_data(id, work, Time) - endif - endif + endif if_gridcomp + endif if_has_id ! - end subroutine store_data + end subroutine history_type_store_data ! !------------------------------------------------------------------------- ! - subroutine store_data3D(id, work, Time, idx, intpl_method, fldname) + subroutine history_type_store_data3D(hist, id, work, Time, idx, intpl_method, fldname) + implicit none + class(history_type) :: hist integer, intent(in) :: id integer, intent(in) :: idx #ifdef CCPP_32BIT real, intent(in) :: work(:,:,:) #else - real(kind=kind_phys), intent(in) :: work(ieco-isco+1,jeco-jsco+1,levo) + real(kind=kind_phys), intent(in) :: work(hist%ieco-hist%isco+1,hist%jeco-hist%jsco+1,hist%levo) #endif type(time_type), intent(in) :: Time character(*), intent(in) :: intpl_method @@ -1624,82 +581,82 @@ subroutine store_data3D(id, work, Time, idx, intpl_method, fldname) logical used ! if( id > 0 ) then - if( use_wrtgridcomp_output ) then + if( hist%use_wrtgridcomp_output ) then if( trim(intpl_method) == 'bilinear') then !$omp parallel do default(shared) private(i,j,k) - do k= 1,levo - do j= jsco,jeco - do i= isco,ieco - buffer_phys_bl(i,j,nstt(idx)+k-1) = work(i-isco+1,j-jsco+1,k) + do k= 1,hist%levo + do j= hist%jsco,hist%jeco + do i= hist%isco,hist%ieco + hist%buffer_phys_bl(i,j,hist%nstt(idx)+k-1) = work(i-hist%isco+1,j-hist%jsco+1,k) enddo enddo enddo else if(trim(intpl_method) == 'nearest_stod') then !$omp parallel do default(shared) private(i,j,k) - do k= 1,levo - do j= jsco,jeco - do i= isco,ieco - buffer_phys_nb(i,j,nstt(idx)+k-1) = work(i-isco+1,j-jsco+1,k) + do k= 1,hist%levo + do j= hist%jsco,hist%jeco + do i= hist%isco,hist%ieco + hist%buffer_phys_nb(i,j,hist%nstt(idx)+k-1) = work(i-hist%isco+1,j-hist%jsco+1,k) enddo enddo enddo else if(trim(intpl_method) == 'vector_bilinear') then !first save the data !$omp parallel do default(shared) private(i,j,k) - do k= 1,levo - do j= jsco,jeco - do i= isco,ieco - buffer_phys_bl(i,j,nstt(idx)+k-1) = work(i-isco+1,j-jsco+1,k) + do k= 1,hist%levo + do j= hist%jsco,hist%jeco + do i= hist%isco,hist%ieco + hist%buffer_phys_bl(i,j,hist%nstt(idx)+k-1) = work(i-hist%isco+1,j-hist%jsco+1,k) enddo enddo enddo if( fldname(1:1) == 'u' .or. fldname(1:1) == 'U') then - if(.not.allocated(uwork3d)) allocate(uwork3d(isco:ieco,jsco:jeco,levo)) + if(.not.associated(hist%uwork3d)) allocate(hist%uwork3d(hist%isco:hist%ieco,hist%jsco:hist%jeco,hist%levo)) !$omp parallel do default(shared) private(i,j,k) - do k= 1, levo - do j= jsco,jeco - do i= isco,ieco - uwork3d(i,j,k) = work(i-isco+1,j-jsco+1,k) + do k= 1, hist%levo + do j= hist%jsco,hist%jeco + do i= hist%isco,hist%ieco + hist%uwork3d(i,j,k) = work(i-hist%isco+1,j-hist%jsco+1,k) enddo enddo enddo - uwindname = fldname - uwork_set = .true. + hist%uwindname = fldname + hist%uwork_set = .true. endif if( fldname(1:1) == 'v' .or. fldname(1:1) == 'V') then !set up wind vector - if( uwork_set .and. trim(uwindname(2:)) == trim(fldname(2:))) then - allocate (sinlon(isco:ieco,jsco:jeco), coslon(isco:ieco,jsco:jeco), & - sinlat(isco:ieco,jsco:jeco), coslat(isco:ieco,jsco:jeco)) + if( hist%uwork_set .and. trim(hist%uwindname(2:)) == trim(fldname(2:))) then + allocate (sinlon(hist%isco:hist%ieco,hist%jsco:hist%jeco), coslon(hist%isco:hist%ieco,hist%jsco:hist%jeco), & + sinlat(hist%isco:hist%ieco,hist%jsco:hist%jeco), coslat(hist%isco:hist%ieco,hist%jsco:hist%jeco)) !$omp parallel do default(shared) private(i,j) - do j= jsco,jeco - do i= isco,ieco - sinlon(i,j) = sin(lon(i,j)) - coslon(i,j) = cos(lon(i,j)) - sinlat(i,j) = sin(lat(i,j)) - coslat(i,j) = cos(lat(i,j)) + do j= hist%jsco,hist%jeco + do i= hist%isco,hist%ieco + sinlon(i,j) = sin(hist%lon(i,j)) + coslon(i,j) = cos(hist%lon(i,j)) + sinlat(i,j) = sin(hist%lat(i,j)) + coslat(i,j) = cos(hist%lat(i,j)) enddo enddo !$omp parallel do default(shared) private(i,j,k,nv,i1,j1) - do k= 1, levo - nv = nstt_vctbl(idx)+k-1 - do j= jsco,jeco - j1 = j-jsco+1 - do i= isco,ieco - i1 = i-isco+1 - buffer_phys_windvect(1,i,j,nv) = uwork3d(i,j,k)*coslon(i,j) & + do k= 1, hist%levo + nv = hist%nstt_vctbl(idx)+k-1 + do j= hist%jsco,hist%jeco + j1 = j-hist%jsco+1 + do i= hist%isco,hist%ieco + i1 = i-hist%isco+1 + hist%buffer_phys_windvect(1,i,j,nv) = hist%uwork3d(i,j,k)*coslon(i,j) & - work(i1,j1,k)*sinlat(i,j)*sinlon(i,j) - buffer_phys_windvect(2,i,j,nv) = uwork3d(i,j,k)*sinlon(i,j) & + hist%buffer_phys_windvect(2,i,j,nv) = hist%uwork3d(i,j,k)*sinlon(i,j) & + work(i1,j1,k)*sinlat(i,j)*coslon(i,j) - buffer_phys_windvect(3,i,j,nv) = work(i1,j1,k)*coslat(i,j) + hist%buffer_phys_windvect(3,i,j,nv) = work(i1,j1,k)*coslat(i,j) enddo enddo enddo deallocate (sinlon, coslon, sinlat, coslat) endif - uwork3d = zero - uwindname = '' - uwork_set = .false. + hist%uwork3d = zero + hist%uwindname = '' + hist%uwork_set = .false. endif endif @@ -1708,7 +665,7 @@ subroutine store_data3D(id, work, Time, idx, intpl_method, fldname) endif endif ! - end subroutine store_data3D + end subroutine history_type_store_data3D ! !------------------------------------------------------------------------- ! @@ -1732,6 +689,25 @@ subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nb logical,intent(in) :: quilting integer, intent(in) :: nbdlphys integer,intent(out) :: rc + + call shared_history_data%bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nbdlphys, rc) + end subroutine fv_phys_bundle_setup + + subroutine history_type_bundle_setup(hist, Diag, axes, phys_bundle, fcst_grid, quilting, nbdlphys, rc) +! set esmf bundle for phys output fields + use esmf + use diag_data_mod, ONLY: diag_atttype +! + implicit none +! + class(history_type) :: hist + type(GFS_externaldiag_type),intent(in) :: Diag(:) + integer, intent(in) :: axes(:) + type(ESMF_FieldBundle),intent(inout) :: phys_bundle(:) + type(ESMF_Grid),intent(inout) :: fcst_grid + logical,intent(in) :: quilting + integer, intent(in) :: nbdlphys + integer,intent(out) :: rc ! !*** local variables @@ -1754,13 +730,14 @@ subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nb logical isPresent integer udimCount character(80),dimension(:),allocatable :: udimList + character(20),dimension(:), allocatable :: axis_name_vert ! !------------------------------------------------------------ !--- use wrte grid component for output - use_wrtgridcomp_output = quilting -! if(mpp_pe()==mpp_root_pe())print *,'in fv_phys bundle,use_wrtgridcomp_output=',use_wrtgridcomp_output, & -! print *,'in fv_phys bundle,use_wrtgridcomp_output=',use_wrtgridcomp_output, & -! 'isco=',isco,ieco,'jsco=',jsco,jeco,'tot_diag_idx=',tot_diag_idx + hist%use_wrtgridcomp_output = quilting +! if(mpp_pe()==mpp_root_pe())print *,'in fv_phys bundle,use_wrtgridcomp_output=',hist%use_wrtgridcomp_output, & +! print *,'in fv_phys bundle,use_wrtgridcomp_output=',hist%use_wrtgridcomp_output, & +! 'hist%isco=',hist%isco,hist%ieco,'hist%jsco=',hist%jsco,hist%jeco,'hist%tot_diag_idx=',hist%tot_diag_idx ! !------------------------------------------------------------ !*** add attributes to the bundle such as subdomain limtis, @@ -1799,43 +776,43 @@ subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nb if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & - name="fhzero", value=fhzero, rc=rc) + name="fhzero", value=hist%fhzero, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & - name="ncld", value=ncld, rc=rc) + name="ncld", value=hist%ncld, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & - name="nsoil", value=nsoil, rc=rc) + name="nsoil", value=hist%nsoil, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & - name="imp_physics", value=imp_physics, rc=rc) + name="imp_physics", value=hist%imp_physics, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & - name="dtp", value=dtp, rc=rc) -! print *,'in fcst gfdl diag, dtp=',dtp,' ibdl=',ibdl + name="dtp", value=hist%dtp, rc=rc) +! print *,'in fcst gfdl diag, hist%dtp=',hist%dtp,' ibdl=',ibdl if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & - name="landsfcmdl", value=landsfcmdl, rc=rc) + name="landsfcmdl", value=hist%landsfcmdl, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return !end ibdl enddo ! !*** get axis names - allocate(axis_name(num_axes_phys)) - do id = 1,num_axes_phys - call get_diag_axis_name( axes(id), axis_name(id)) + allocate(hist%axis_name(hist%num_axes_phys)) + do id = 1,hist%num_axes_phys + call get_diag_axis_name( axes(id), hist%axis_name(id)) enddo isPresent = .false. - if( num_axes_phys>2 ) then - allocate(axis_name_vert(num_axes_phys-2)) - do id=3,num_axes_phys - axis_name_vert(id-2) = axis_name(id) + if( hist%num_axes_phys>2 ) then + allocate(axis_name_vert(hist%num_axes_phys-2)) + do id=3,hist%num_axes_phys + axis_name_vert(id-2) = hist%axis_name(id) enddo ! call ESMF_AttributeGet(fcst_grid, convention="NetCDF", purpose="FV3", & @@ -1843,7 +820,7 @@ subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nb itemCount=udimCount, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - if (isPresent .and. (udimCount>num_axes_phys-2) ) then + if (isPresent .and. (udimCount>hist%num_axes_phys-2) ) then allocate(udimList(udimCount)) call ESMF_AttributeGet(fcst_grid, convention="NetCDF", purpose="FV3", & name="vertical_dim_labels", valueList=udimList, rc=rc) @@ -1866,52 +843,55 @@ subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nb endif !*** add attributes - if(allocated(all_axes)) deallocate(all_axes) - allocate(all_axes(num_axes_phys)) - all_axes(1:num_axes_phys) = axes(1:num_axes_phys) - if (.not. isPresent .or. (udimCount2 ) then ! if(mpp_pe()==mpp_root_pe()) print *,' in dyn add grid, axis_name=', & -! trim(axis_name(id)),'axis_data=',axis_data +! trim(hist%axis_name(id)),'axis_data=',axis_data if(trim(edgesS)/='') then call ESMF_AttributeAdd(fcst_grid, convention="NetCDF", purpose="FV3", & - attrList=(/trim(axis_name(id)),trim(axis_name(id))//":long_name", & - trim(axis_name(id))//":units", trim(axis_name(id))//":cartesian_axis", & - trim(axis_name(id))//":positive", trim(axis_name(id))//":edges"/), rc=rc) + attrList=(/trim(hist%axis_name(id)),trim(hist%axis_name(id))//":long_name", & + trim(hist%axis_name(id))//":units", trim(hist%axis_name(id))//":cartesian_axis", & + trim(hist%axis_name(id))//":positive", trim(hist%axis_name(id))//":edges"/), rc=rc) else call ESMF_AttributeAdd(fcst_grid, convention="NetCDF", purpose="FV3", & - attrList=(/trim(axis_name(id)),trim(axis_name(id))//":long_name", & - trim(axis_name(id))//":units", trim(axis_name(id))//":cartesian_axis", & - trim(axis_name(id))//":positive"/), rc=rc) + attrList=(/trim(hist%axis_name(id)),trim(hist%axis_name(id))//":long_name", & + trim(hist%axis_name(id))//":units", trim(hist%axis_name(id))//":cartesian_axis", & + trim(hist%axis_name(id))//":positive"/), rc=rc) endif if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & - name=trim(axis_name(id)), valueList=axis_data, rc=rc) + name=trim(hist%axis_name(id)), valueList=axis_data, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & - name=trim(axis_name(id))//":long_name", value=trim(long_name), rc=rc) + name=trim(hist%axis_name(id))//":long_name", value=trim(long_name), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & - name=trim(axis_name(id))//":units", value=trim(units), rc=rc) + name=trim(hist%axis_name(id))//":units", value=trim(units), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & - name=trim(axis_name(id))//":cartesian_axis", value=trim(cart_name), rc=rc) + name=trim(hist%axis_name(id))//":cartesian_axis", value=trim(cart_name), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if(direction > 0) then @@ -1920,12 +900,12 @@ subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nb axis_direct = "down" endif call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & - name=trim(axis_name(id))//":positive", value=trim(axis_direct), rc=rc) + name=trim(hist%axis_name(id))//":positive", value=trim(axis_direct), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if(trim(edgesS)/='') then call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & - name=trim(axis_name(id))//":edges", value=trim(edgesS), rc=rc) + name=trim(hist%axis_name(id))//":edges", value=trim(edgesS), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return endif @@ -1934,13 +914,13 @@ subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nb deallocate(axis_data) enddo endif -! print *,'in setup fieldbundle_phys, num_axes_phys=',num_axes_phys,'tot_diag_idx=',tot_diag_idx, & +! print *,'in setup fieldbundle_phys, hist%num_axes_phys=',hist%num_axes_phys,'hist%tot_diag_idx=',hist%tot_diag_idx, & ! 'nbdlphys=',nbdlphys ! !----------------------------------------------------------------------------------------- !*** add esmf fields ! - do idx= 1,tot_diag_idx + do idx= 1,hist%tot_diag_idx lput2physbdl = .false. do ibdl = 1, nbdlphys @@ -1948,21 +928,21 @@ subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nb if( index(trim(Diag(idx)%intpl_method),trim(bdl_intplmethod(ibdl))) > 0) then lput2physbdl = .true. if( Diag(idx)%id > 0 ) then - call find_output_name(trim(Diag(idx)%mod_name),trim(Diag(idx)%name),output_name) + call hist%find_output_name(trim(Diag(idx)%mod_name),trim(Diag(idx)%name),output_name) !add origin field - call add_field_to_phybundle(trim(output_name),trim(Diag(idx)%desc),trim(Diag(idx)%unit), "time: point", & - axes(1:Diag(idx)%axes), fcst_grid, nstt(idx), phys_bundle(ibdl), outputfile(ibdl), & + call hist%add_field_to_phybundle(trim(output_name),trim(Diag(idx)%desc),trim(Diag(idx)%unit), "time: point", & + axes(1:Diag(idx)%axes), fcst_grid, hist%nstt(idx), phys_bundle(ibdl), outputfile(ibdl), & bdl_intplmethod(ibdl), rcd=rc) ! if( mpp_pe() == mpp_root_pe()) print *,'phys, add field,',trim(Diag(idx)%name),'idx=',idx,'ibdl=',ibdl ! if( index(trim(Diag(idx)%intpl_method), "vector") > 0) then l2dvector = .true. - if (nstt_vctbl(idx) > 0) then + if (hist%nstt_vctbl(idx) > 0) then output_name = 'wind'//trim(output_name)//'vector' outputfile1 = 'none' - call add_field_to_phybundle(trim(output_name),trim(Diag(idx)%desc),trim(Diag(idx)%unit), "time: point", & - axes(1:Diag(idx)%axes), fcst_grid, nstt_vctbl(idx),phys_bundle(ibdl), outputfile1, & + call hist%add_field_to_phybundle(trim(output_name),trim(Diag(idx)%desc),trim(Diag(idx)%unit), "time: point", & + axes(1:Diag(idx)%axes), fcst_grid, hist%nstt_vctbl(idx),phys_bundle(ibdl), outputfile1, & bdl_intplmethod(ibdl),l2dvector=l2dvector, rcd=rc) ! if( mpp_pe() == mpp_root_pe()) print *,'in phys, add vector field,',trim(Diag(idx)%name),' idx=',idx,' ibdl=',ibdl endif @@ -1977,19 +957,21 @@ subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nb endif enddo - deallocate(axis_name) - deallocate(all_axes) + deallocate(hist%axis_name) + deallocate(hist%all_axes) + nullify(hist%axis_name) + nullify(hist%all_axes) - end subroutine fv_phys_bundle_setup + end subroutine history_type_bundle_setup ! !----------------------------------------------------------------------------------------- - subroutine add_field_to_phybundle(var_name,long_name,units,cell_methods, axes,phys_grid, & + subroutine history_type_add_field_to_phybundle(hist,var_name,long_name,units,cell_methods, axes,phys_grid, & kstt,phys_bundle,output_file,intpl_method,range,l2dvector,rcd) ! use esmf ! implicit none - + class(history_type) :: hist character(*), intent(in) :: var_name, long_name, units, cell_methods character(*), intent(in) :: output_file, intpl_method integer, intent(in) :: axes(:) @@ -2018,7 +1000,7 @@ subroutine add_field_to_phybundle(var_name,long_name,units,cell_methods, axes,ph ! !*** create esmf field if (l2dvector_local .and. size(axes)==2) then - temp_r3d => buffer_phys_windvect(1:3,isco:ieco,jsco:jeco,kstt) + temp_r3d => hist%buffer_phys_windvect(1:3,hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt) ! if( mpp_root_pe() == 0) print *,'phys, create wind vector esmf field' call ESMF_LogWrite('bf create winde vector esmf field '//trim(var_name), ESMF_LOGMSG_INFO, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return @@ -2053,14 +1035,14 @@ subroutine add_field_to_phybundle(var_name,long_name,units,cell_methods, axes,ph return else if( trim(intpl_method) == 'nearest_stod' ) then if(size(axes) == 2) then - temp_r2d => buffer_phys_nb(isco:ieco,jsco:jeco,kstt) + temp_r2d => hist%buffer_phys_nb(hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt) field = ESMF_FieldCreate(phys_grid, temp_r2d, datacopyflag=copyflag, & name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) else if(size(axes) == 3) then - temp_r3d => buffer_phys_nb(isco:ieco,jsco:jeco,kstt:kstt+levo-1) + temp_r3d => hist%buffer_phys_nb(hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt:kstt+hist%levo-1) field = ESMF_FieldCreate(phys_grid, temp_r3d, datacopyflag=copyflag, & name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & @@ -2070,13 +1052,13 @@ subroutine add_field_to_phybundle(var_name,long_name,units,cell_methods, axes,ph endif else if( trim(intpl_method) == 'bilinear' ) then if(size(axes) == 2) then - temp_r2d => buffer_phys_bl(isco:ieco,jsco:jeco,kstt) + temp_r2d => hist%buffer_phys_bl(hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt) field = ESMF_FieldCreate(phys_grid, temp_r2d, datacopyflag=copyflag, & name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) else if(size(axes) == 3) then - temp_r3d => buffer_phys_bl(isco:ieco,jsco:jeco,kstt:kstt+levo-1) + temp_r3d => hist%buffer_phys_bl(hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt:kstt+hist%levo-1) field = ESMF_FieldCreate(phys_grid, temp_r3d, datacopyflag=copyflag, & name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & @@ -2151,8 +1133,8 @@ subroutine add_field_to_phybundle(var_name,long_name,units,cell_methods, axes,ph if( size(axes) > 2) then do i=3,size(axes) idx=0 - do j=1,size(all_axes) - if (axes(i)==all_axes(j)) then + do j=1,size(hist%all_axes) + if (axes(i)==hist%all_axes(j)) then idx=j exit endif @@ -2162,7 +1144,7 @@ subroutine add_field_to_phybundle(var_name,long_name,units,cell_methods, axes,ph attrList=(/"ESMF:ungridded_dim_labels"/), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & - name="ESMF:ungridded_dim_labels", valueList=(/trim(axis_name(idx))/), rc=rc) + name="ESMF:ungridded_dim_labels", valueList=(/trim(hist%axis_name(idx))/), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return endif enddo @@ -2174,10 +1156,12 @@ subroutine add_field_to_phybundle(var_name,long_name,units,cell_methods, axes,ph ! call ESMF_LogWrite('phys field add to fieldbundle '//trim(var_name), ESMF_LOGMSG_INFO, rc=rc) - end subroutine add_field_to_phybundle + end subroutine history_type_add_field_to_phybundle ! ! - subroutine find_output_name(module_name,field_name,output_name) + subroutine history_type_find_output_name(hist,module_name,field_name,output_name) + implicit none + class(history_type) :: hist character(*), intent(in) :: module_name character(*), intent(in) :: field_name character(*), intent(out) :: output_name @@ -2199,7 +1183,7 @@ subroutine find_output_name(module_name,field_name,output_name) print *,'Error, cant find out put name' endif - end subroutine find_output_name + end subroutine history_type_find_output_name #endif !------------------------------------------------------------------------- diff --git a/io/fv3atm_restart_io.F90 b/io/fv3atm_restart_io.F90 index 712c86516..6cffb7c46 100644 --- a/io/fv3atm_restart_io.F90 +++ b/io/fv3atm_restart_io.F90 @@ -2,268 +2,1328 @@ module fv3atm_restart_io_mod use esmf use block_control_mod, only: block_control_type - use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys + use mpp_mod, only: mpp_error, mpp_pe, mpp_root_pe, & + mpp_chksum, NOTE, FATAL + use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys, GFS_data_type use GFS_restart, only: GFS_restart_type - use fv3atm_sfc_io + 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 fv3atm_common_io, only: create_2d_field_and_add_to_bundle, & - create_3d_field_and_add_to_bundle, add_zaxis_to_field + create_3d_field_and_add_to_bundle, add_zaxis_to_field, copy_from_gfs_data + use fv3atm_sfc_io use fv3atm_rrfs_sd_io use fv3atm_clm_lake_io + use fv3atm_oro_io implicit none private + public fv3atm_checksum + public fv3atm_restart_read + public fv3atm_restart_write + public phy_data_type + public fv3atm_restart_register + public fv_phy_restart_output + public fv_phy_restart_bundle_setup + public fv_sfc_restart_output + public fv_sfc_restart_bundle_setup + + type phy_data_type + real(kind=kind_phys), pointer, dimension(:,:,:) :: var2 => null() + real(kind=kind_phys), pointer, dimension(:,:,:,:) :: var3 => null() + character(len=32),dimension(:),pointer :: var2_names => null() + character(len=32),dimension(:),pointer :: var3_names => null() + integer :: nvar2d = 0, nvar3d = 0, npz = 0 + end type phy_data_type + + !--- GFDL filenames + character(len=32), parameter :: fn_oro = 'oro_data.nc' + character(len=32), parameter :: fn_oro_ls = 'oro_data_ls.nc' + character(len=32), parameter :: fn_oro_ss = 'oro_data_ss.nc' + character(len=32), parameter :: fn_srf = 'sfc_data.nc' + character(len=32), parameter :: fn_phy = 'phy_data.nc' + character(len=32), parameter :: fn_dust12m= 'dust12m_data.nc' + character(len=32), parameter :: fn_emi = 'emi_data.nc' + character(len=32), parameter :: fn_rrfssd = 'SMOKE_RRFS_data.nc' + real(kind_phys), parameter:: zero = 0.0, one = 1.0 - integer, parameter :: r8 = kind_phys - integer :: nvar2d, nvar3d, npz - real(kind=kind_phys), allocatable, target, dimension(:,:,:) :: phy_var2 - real(kind=kind_phys), allocatable, target, dimension(:,:,:,:) :: phy_var3 - character(len=32),dimension(:),allocatable :: phy_var2_names, phy_var3_names + type(phy_data_type) :: phy_quilt + type(clm_lake_data_type) :: clm_lake_quilt + type(Sfc_io_data_type) :: sfc_quilt + type(rrfs_sd_state_type) :: rrfs_sd_quilt - type(rrfs_sd_state_type) :: rrfs_sd - type(clm_lake_data_type) :: clm_lake - type(Sfc_io_data_type) :: sfc - type(ESMF_FieldBundle) :: phy_bundle, sfc_bundle +contains - public fv3atm_restart_register + !---------------- + ! fv3atm_checksum + !---------------- + subroutine fv3atm_checksum (Model, GFS_Data, Atm_block) + implicit none + !--- interface variables + type(GFS_control_type), intent(in) :: Model + type(GFS_data_type), intent(in) :: GFS_Data(:) + type (block_control_type), intent(in) :: Atm_block + !--- local variables + integer :: outunit, j, i, ix, nb, isc, iec, jsc, jec, lev, ct, l, ntr, k + integer :: nsfcprop2d, idx_opt, nt + real(kind=kind_phys), allocatable :: temp2d(:,:,:) + real(kind=kind_phys), allocatable :: temp3d(:,:,:,:) + real(kind=kind_phys), allocatable :: temp3dlevsp1(:,:,:,:) + integer, allocatable :: ii1(:), jj1(:) + character(len=32) :: name - public fv_phy_restart_output - public fv_phy_restart_bundle_setup + isc = Model%isc + iec = Model%isc+Model%nx-1 + jsc = Model%jsc + jec = Model%jsc+Model%ny-1 + lev = Model%levs - public fv_sfc_restart_output - public fv_sfc_restart_bundle_setup + ntr = size(GFS_Data(1)%Statein%qgrs,3) + + nsfcprop2d = 93 + if (Model%lsm == Model%lsm_noahmp) then + nsfcprop2d = nsfcprop2d + 49 + if (Model%use_cice_alb) then + nsfcprop2d = nsfcprop2d + 4 + endif + elseif (Model%lsm == Model%lsm_ruc) then + nsfcprop2d = nsfcprop2d + 4 + 12 + if (Model%rdlai) then + nsfcprop2d = nsfcprop2d + 1 + endif + else + if (Model%use_cice_alb) then + nsfcprop2d = nsfcprop2d + 4 + endif + endif + + if (Model%nstf_name(1) > 0) then + nsfcprop2d = nsfcprop2d + 16 + endif + + if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_flake) then + nsfcprop2d = nsfcprop2d + 10 + endif + + allocate (temp2d(isc:iec,jsc:jec,nsfcprop2d+Model%ntot2d+Model%nctp)) + allocate (temp3d(isc:iec,jsc:jec,1:lev,14+Model%ntot3d+2*ntr)) + allocate (temp3dlevsp1(isc:iec,jsc:jec,1:lev+1,3)) + + temp2d = zero + temp3d = zero + temp3dlevsp1 = zero + + !$omp parallel do default(shared) private(i, j, k, nb, ix, nt, ii1, jj1) + block_loop: do nb = 1, Atm_block%nblks + allocate(ii1(Atm_block%blksz(nb))) + allocate(jj1(Atm_block%blksz(nb))) + ii1=Atm_block%index(nb)%ii - isc + 1 + jj1=Atm_block%index(nb)%jj - jsc + 1 + + ! Copy into temp2d + nt=0 + + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Statein%pgr) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%slmsk) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tsfc) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tisfc) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snowd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%zorl) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%fice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%hprime(:,1)) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sncovr) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snoalb) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%alvsf) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%alnsf) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%alvwf) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%alnwf) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%facsf) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%facwf) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%slope) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%shdmin) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%shdmax) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tg3) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%vfrac) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%vtype) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%stype) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%uustar) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%oro) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%oro_uf) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%hice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%weasd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%canopy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%ffmm) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%ffhh) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%f10m) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tprcp) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%srflag) + lsm_choice: if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%slc) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%smc) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%stc) + elseif (Model%lsm == Model%lsm_ruc) then + do k=1,3 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sh2o(:,k)) + enddo + ! Combine levels 4 to lsoil_lsm (9 for RUC) into one + nt=nt+1 + do ix=1,Atm_block%blksz(nb) + temp2d(ii1(ix),jj1(ix),nt) = sum(GFS_Data(nb)%Sfcprop%sh2o(ix,4:Model%lsoil_lsm)) + enddo + do k=1,3 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%smois(:,k)) + enddo + ! Combine levels 4 to lsoil_lsm (9 for RUC) into one + nt=nt+1 + do ix=1,Atm_block%blksz(nb) + temp2d(ii1(ix),jj1(ix),nt) = sum(GFS_Data(nb)%Sfcprop%smois(ix,4:Model%lsoil_lsm)) + enddo + do k=1,3 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tslb(:,k)) + enddo + ! Combine levels 4 to lsoil_lsm (9 for RUC) into one + nt=nt+1 + do ix=1,Atm_block%blksz(nb) + temp2d(ii1(ix),jj1(ix),nt) = sum(GFS_Data(nb)%Sfcprop%tslb(ix,4:Model%lsoil_lsm)) + enddo + endif lsm_choice + + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%t2m) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%q2m) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%nirbmdi) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%nirdfdi) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%visbmdi) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%visdfdi) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%nirbmui) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%nirdfui) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%visbmui) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%visdfui) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%sfcdsw) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%sfcnsw) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Coupling%sfcdlw) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%xlon) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%xlat) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%xlat_d) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%sinlat) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%coslat) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%area) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%dx) + if (Model%ntoz > 0) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%ddy_o3) + endif + if (Model%h2o_phys) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Grid%ddy_h) + endif + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Cldprop%cv) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Cldprop%cvt) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Cldprop%cvb) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Radtend%sfalb) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Radtend%coszen) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Radtend%tsflw) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Radtend%semis) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Radtend%coszdg) + + ! Radtend%sfcfsw is an array of derived type, so we copy all + ! eight elements of the type in one loop + do ix=1,Atm_block%blksz(nb) + temp2d(ii1(ix),jj1(ix),nt+1) = GFS_Data(nb)%Radtend%sfcfsw(ix)%upfxc + temp2d(ii1(ix),jj1(ix),nt+2) = GFS_Data(nb)%Radtend%sfcfsw(ix)%upfx0 + temp2d(ii1(ix),jj1(ix),nt+3) = GFS_Data(nb)%Radtend%sfcfsw(ix)%dnfxc + temp2d(ii1(ix),jj1(ix),nt+4) = GFS_Data(nb)%Radtend%sfcfsw(ix)%dnfx0 + temp2d(ii1(ix),jj1(ix),nt+5) = GFS_Data(nb)%Radtend%sfcflw(ix)%upfxc + temp2d(ii1(ix),jj1(ix),nt+6) = GFS_Data(nb)%Radtend%sfcflw(ix)%upfx0 + temp2d(ii1(ix),jj1(ix),nt+7) = GFS_Data(nb)%Radtend%sfcflw(ix)%dnfxc + temp2d(ii1(ix),jj1(ix),nt+8) = GFS_Data(nb)%Radtend%sfcflw(ix)%dnfx0 + enddo + nt = nt + 8 + + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tiice(:,1)) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tiice(:,2)) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdirvis_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdirnir_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdifvis_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdifnir_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%emis_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%emis_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sncovr_ice) + + if (Model%use_cice_alb .or. Model%lsm == Model%lsm_ruc) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdirvis_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdirnir_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdifvis_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%albdifnir_ice) + endif + + lsm_choice_2: if (Model%lsm == Model%lsm_noahmp) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snowxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tvxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tgxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%canicexy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%canliqxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%eahxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tahxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%cmxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%chxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%fwetxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sneqvoxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%alboldxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%qsnowxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%wslakexy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%zwtxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%waxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%wtxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%lfmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%rtmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%stmassxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%woodxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%stblcpxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%fastcpxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xsaixy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xlaixy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%taussxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%smcwtdxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%deeprechxy) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%rechxy) + + ! These five arrays use bizarre indexing, so we use loops: + do k=-2,0 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snicexy(:,k)) + enddo + + do k=-2,0 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snliqxy(:,k)) + enddo + + do k=-2,0 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tsnoxy(:,k)) + enddo + + do k=1,4 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%smoiseq(:,k)) + enddo + + do k=-2,4 + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%zsnsoxy(:,k)) + enddo + elseif (Model%lsm == Model%lsm_ruc) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%wetness) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%clw_surf_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%clw_surf_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%qwv_surf_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%qwv_surf_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tsnow_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tsnow_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snowfallac_land) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%snowfallac_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sfalb_lnd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sfalb_lnd_bck) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%sfalb_ice) + if (Model%rdlai) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xlaixy) + endif + endif lsm_choice_2 + + nstf_name_choice: if (Model%nstf_name(1) > 0) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%tref) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%z_c) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%c_0) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%c_d) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%w_0) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%w_d) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xt) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xs) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xu) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xz) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%zm) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xtts) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%xzts) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%ifd) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%dt_cool) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%qrain) + endif nstf_name_choice + + ! Flake + if (Model%lkm > 0 .and. Model%iopt_lake==Model%iopt_lake_flake) then + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%T_snow) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%T_ice) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%h_ML) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%t_ML) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%t_mnw) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%h_talb) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%t_talb) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%t_bot1) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%t_bot2) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Sfcprop%c_t) + endif + + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Tbd%phy_f2d) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp2d,GFS_Data(nb)%Tbd%phy_fctd) + + ! Copy to temp3dlevsp1 + nt=0 + + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3dlevsp1, GFS_Data(nb)%Statein%phii) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3dlevsp1, GFS_Data(nb)%Statein%prsi) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3dlevsp1, GFS_Data(nb)%Statein%prsik) + + ! Copy to temp3d + nt=0 + + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%phil) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%prsl) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%prslk) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%ugrs) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%vgrs) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%vvl) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%tgrs) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Stateout%gu0) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Stateout%gv0) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Stateout%gt0) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Radtend%htrsw) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Radtend%htrlw) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Radtend%swhc) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Radtend%lwhc) + do l = 1,Model%ntot3d + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Tbd%phy_f3d(:,:,l)) + enddo + do l = 1,ntr + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%qgrs(:,:,l)) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Stateout%gq0(:,:,l)) + enddo + enddo block_loop + + + outunit = stdout() + do i = 1,nsfcprop2d+Model%ntot2d+Model%nctp + write (name, '(i3.3,3x,4a)') i, ' 2d ' + write(outunit,100) name, mpp_chksum(temp2d(:,:,i:i)) + enddo + do i = 1,3 + write (name, '(i2.2,3x,4a)') i, ' 3d levsp1' + write(outunit,100) name, mpp_chksum(temp3dlevsp1(:,:,:,i:i)) + enddo + do i = 1,14+Model%ntot3d+2*ntr + write (name, '(i2.2,3x,4a)') i, ' 3d levs' + write(outunit,100) name, mpp_chksum(temp3d(:,:,:,i:i)) + enddo +100 format("CHECKSUM::",A32," = ",Z20) + + deallocate(temp2d) + deallocate(temp3d) + deallocate(temp3dlevsp1) + end subroutine fv3atm_checksum + + !-------------------- + ! fv3atm_restart_read + !-------------------- + subroutine fv3atm_restart_read (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) + implicit none + type(GFS_data_type), intent(inout) :: GFS_Data(:) + type(GFS_restart_type), intent(inout) :: GFS_Restart + type(block_control_type), intent(in) :: Atm_block + type(GFS_control_type), intent(inout) :: Model + type(domain2d), intent(in) :: fv_domain + logical, intent(in) :: warm_start + logical, intent(in) :: ignore_rst_cksum + + !--- read in surface data from chgres + call sfc_prop_restart_read (GFS_Data%Sfcprop, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) + + !--- read in physics restart data + call phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_rst_cksum) + + end subroutine fv3atm_restart_read + + !--------------------- + ! fv3atm_restart_write + !--------------------- + subroutine fv3atm_restart_write (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, timestamp) + implicit none + type(GFS_data_type), intent(inout) :: GFS_Data(:) + type(GFS_restart_type), intent(inout) :: GFS_Restart + type(block_control_type), intent(in) :: Atm_block + 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 + 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) + + end subroutine fv3atm_restart_write + + + + !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + ! + ! PRIVATE SUBROUTINES + ! + !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + !---------------------------------------------------------------------- + ! sfc_prop_restart_read + !---------------------------------------------------------------------- + ! creates and populates a data type which is then used to "register" + ! restart variables with the GFDL FMS restart subsystem. + ! calls a GFDL FMS routine to restore the data from a restart file. + ! calculates sncovr if it is not present in the restart file. + ! + ! 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, ignore_rst_cksum) + use fv3atm_rrfs_sd_io + implicit none + !--- interface variable definitions + type(GFS_sfcprop_type), intent(inout) :: Sfcprop(:) + type (block_control_type), intent(in) :: Atm_block + type(GFS_control_type), intent(inout) :: Model + type (domain2d), intent(in) :: fv_domain + logical, intent(in) :: warm_start + logical, intent(in) :: ignore_rst_cksum + !--- local variables + integer :: i, j, k, ix, lsoil, num, nb, i_start, j_start, i_end, j_end, nt, n + integer :: isc, iec, jsc, jec, nx, ny + integer :: id_restart + integer :: isnow + integer, allocatable :: ii1(:), jj1(:) + real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() + real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() + 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() + real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_fr => NULL() + !--- local variables for sncovr calculation + 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 :: override_frac_grid + + type(clm_lake_data_type) :: clm_lake + type(rrfs_sd_state_type) :: rrfs_sd_state + type(rrfs_sd_emissions_type) :: rrfs_sd_emis + type(Oro_scale_io_data_type) :: oro_ss + type(Oro_scale_io_data_type) :: oro_ls + type(Sfc_io_data_type) :: sfc + type(Oro_io_data_type) :: oro + + type(FmsNetcdfDomainFile_t) :: Oro_restart, Sfc_restart, dust12m_restart, emi_restart, rrfssd_restart + type(FmsNetcdfDomainFile_t) :: Oro_ls_restart, Oro_ss_restart + + isc = Atm_block%isc + iec = Atm_block%iec + jsc = Atm_block%jsc + jec = Atm_block%jec + 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) ) + + call oro%register(Model,Oro_restart,Atm_block) + + !--- read the orography restart/data + call mpp_error(NOTE,'reading topographic/orographic information from INPUT/oro_data.tile*.nc') + call read_restart(Oro_restart, ignore_checksum=ignore_rst_cksum) + call close_file(Oro_restart) + + !--- copy data into GFS containers + call oro%copy(Model, Sfcprop, Atm_block) + + if_smoke: if(Model%rrfs_sd) then ! for RRFS-SD + + !--- Dust input FILE + !--- open file + infile=trim(indir)//'/'//trim(fn_dust12m) + amiopen=open_file(dust12m_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) ) + + !--- Register axes and variables, allocate memory: + call rrfs_sd_emis%register_dust12m(dust12m_restart, Atm_block) + + !--- read new GSL created dust12m restart/data + call mpp_error(NOTE,'reading dust12m information from INPUT/dust12m_data.tile*.nc') + call read_restart(dust12m_restart) + call close_file(dust12m_restart) + + !--- Copy to Sfcprop and free temporary arrays: + call rrfs_sd_emis%copy_dust12m(Sfcprop, Atm_block) + + !---------------------------------------------- + + !--- open anthropogenic emission file + infile=trim(indir)//'/'//trim(fn_emi) + amiopen=open_file(emi_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) ) + + ! Register axes and variables, allocate memory + call rrfs_sd_emis%register_emi(emi_restart, Atm_block) + + !--- read anthropogenic emi restart/data + call mpp_error(NOTE,'reading emi information from INPUT/emi_data.tile*.nc') + call read_restart(emi_restart) + call close_file(emi_restart) + + !--- Copy to Sfcprop and free temporary arrays: + call rrfs_sd_emis%copy_emi(Sfcprop, Atm_block) + + !---------------------------------------------- + + !--- Dust input FILE + !--- open file + infile=trim(indir)//'/'//trim(fn_rrfssd) + amiopen=open_file(rrfssd_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) ) + + ! Register axes and variables, allocate memory + call rrfs_sd_emis%register_fire(rrfssd_restart, Atm_block) + + !--- read new GSL created rrfssd restart/data + call mpp_error(NOTE,'reading rrfssd information from INPUT/SMOKE_RRFS_data.nc') + call read_restart(rrfssd_restart) + call close_file(rrfssd_restart) + + !--- Copy to Sfcprop and free temporary arrays: + call rrfs_sd_emis%copy_fire(Sfcprop, Atm_block) + + endif if_smoke ! RRFS_SD + + !--- 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 + + if ( (Model%gwd_opt==3 .or. Model%gwd_opt==33) .or. & + ( (Model%gwd_opt==2 .or. Model%gwd_opt==22) .and. & + Model%do_gsl_drag_ls_bl ) ) 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) ) + call oro_ls%register(Model,Oro_ls_restart,Atm_block) + !--- read new GSL created orography restart/data + call mpp_error(NOTE,'reading topographic/orographic information from & + &INPUT/oro_data_ls.tile*.nc') + call read_restart(Oro_ls_restart, ignore_checksum=ignore_rst_cksum) + call close_file(Oro_ls_restart) + call oro_ls%copy(Sfcprop,Atm_block,1) + endif + + !--- 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) ) + call oro_ss%register(Model,Oro_ss_restart,Atm_block) + call mpp_error(NOTE,'reading topographic/orographic information from & + &INPUT/oro_data_ss.tile*.nc') + call read_restart(Oro_ss_restart, ignore_checksum=ignore_rst_cksum) + call close_file(Oro_ss_restart) + call oro_ss%copy(Sfcprop,Atm_block,15) + 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)) + + if(sfc%allocate_arrays(Model, Atm_block, .true., warm_start)) then + call sfc%fill_2d_names(Model, warm_start) + call sfc%register_axes(Model, Sfc_restart, .true., warm_start) + + ! Tell CLM Lake to allocate data, and register its axes and fields + if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then + call clm_lake%allocate_data(Model) + call clm_lake%copy_from_grid(Model,Atm_block,Sfcprop) + call clm_lake%register_axes(Model, Sfc_restart) + call clm_lake%register_fields(Sfc_restart) + endif + + if(Model%rrfs_sd) then + call rrfs_sd_state%allocate_data(Model) + call rrfs_sd_state%fill_data(Model, Atm_block, Sfcprop) + call rrfs_sd_state%register_axis(Model, Sfc_restart) + call rrfs_sd_state%register_fields(Sfc_restart) + endif + + call sfc%register_2d_fields(Model,Sfc_restart,.true.,warm_start) + endif ! if not allocated + + call sfc%fill_3d_names(Model,warm_start) + call sfc%register_3d_fields(Model,Sfc_restart,.true.,warm_start) + call sfc%init_fields(Model) + + !--- read the surface restart/data + call mpp_error(NOTE,'reading surface properties data from INPUT/sfc_data.tile*.nc') + call read_restart(Sfc_restart, ignore_checksum=ignore_rst_cksum) + call close_file(Sfc_restart) + + ! Tell clm_lake to copy data to temporary arrays + if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then + call clm_lake%copy_to_grid(Model,Atm_block,Sfcprop) + endif + + if(Model%rrfs_sd) then + call rrfs_sd_state%copy_to_grid(Model,Atm_block,Sfcprop) + end if + + ! 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)) + ! write(0,*)' sfc%var2=',sfc%var2(:,:,12) + + !--- place the data into the block GFS containers + override_frac_grid=Model%frac_grid + call sfc%copy_to_grid(Model, Atm_block, Sfcprop, warm_start, override_frac_grid) + Model%frac_grid=override_frac_grid + + call mpp_error(NOTE, 'gfs_driver:: - after put to container ') + + call sfc%apply_safeguards(Model, Atm_block, Sfcprop) + + ! A standard-compliant Fortran 2003 compiler will call clm_lake_final and rrfs_sd_final here. + + end subroutine sfc_prop_restart_read + + + !---------------------------------------------------------------------- + ! sfc_prop_restart_write + !---------------------------------------------------------------------- + ! routine to write out GFS surface restarts via the GFDL FMS restart + ! subsystem. + ! takes an optional argument to append timestamps for intermediate + ! restarts. + ! + ! calls: register_restart_field, save_restart + !---------------------------------------------------------------------- + subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timestamp) + use fv3atm_rrfs_sd_io + implicit none + !--- interface variable definitions + type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) + type(block_control_type), intent(in) :: Atm_block + type(GFS_control_type), intent(in) :: Model + type(domain2d), intent(in) :: fv_domain + character(len=32), optional, intent(in) :: timestamp + !--- local variables + integer :: i, j, k, nb, ix, lsoil, num, nt + integer :: isc, iec, jsc, jec, nx, ny + integer :: id_restart + logical :: mand + integer, allocatable :: ii1(:), jj1(:) + character(len=32) :: fn_srf = 'sfc_data.nc' + real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() + real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() + 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() + real(kind_phys) :: ice + !--- 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 + + type(clm_lake_data_type), target :: clm_lake + type(rrfs_sd_state_type) :: rrfs_sd_state + type(Sfc_io_data_type) :: sfc + + type(FmsNetcdfDomainFile_t) :: Sfc_restart + + isc = Atm_block%isc + iec = Atm_block%iec + jsc = Atm_block%jsc + jec = Atm_block%jec + nx = (iec - isc + 1) + ny = (jec - jsc + 1) + + !--- 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: if( amiopen ) then + call sfc%register_axes(Model, Sfc_restart, .false., .true.) + call sfc%write_axes(Model, Sfc_restart) + else + call mpp_error(FATAL, 'Error in opening file'//trim(infile) ) + end if if_amiopen + + ! Tell clm_lake to allocate data, register its axes, and call write_data for each axis's variable + if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then + call clm_lake%allocate_data(Model) + call clm_lake%register_axes(Model, Sfc_restart) + call clm_lake%write_axes(Model, Sfc_restart) + endif + + if(Model%rrfs_sd) then + call rrfs_sd_state%allocate_data(Model) + call rrfs_sd_state%register_axis(Model,Sfc_restart) + call rrfs_sd_state%write_axis(Model,Sfc_restart) + end if + + if (sfc%allocate_arrays(Model, Atm_block, .false., .true.)) then + call sfc%fill_2d_names(Model,.true.) + end if - contains - - subroutine fv3atm_restart_register (Sfcprop, GFS_restart, Atm_block, Model) - - ! this subroutine must allocate all data buffers and set the variable names - ! for both 'phy' and 'sfc' restart bundles - - implicit none - - type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) - type(GFS_restart_type), intent(in) :: GFS_Restart - type(block_control_type), intent(in) :: Atm_block - type(GFS_control_type), intent(in) :: Model - - logical was_changed - integer :: isc, iec, jsc, jec, nx, ny - integer :: num - - isc = Atm_block%isc - iec = Atm_block%iec - jsc = Atm_block%jsc - jec = Atm_block%jec - npz = Atm_block%npz - nx = (iec - isc + 1) - ny = (jec - jsc + 1) - - !--------------- phy - nvar2d = GFS_Restart%num2d - nvar3d = GFS_Restart%num3d - - allocate (phy_var2(nx,ny,nvar2d), phy_var2_names(nvar2d)) - allocate (phy_var3(nx,ny,npz,nvar3d), phy_var3_names(nvar3d)) - phy_var2 = zero - phy_var3 = zero - do num = 1,nvar2d - phy_var2_names(num) = trim(GFS_Restart%name2d(num)) - enddo - do num = 1,nvar3d - phy_var3_names(num) = trim(GFS_Restart%name3d(num)) - enddo - - !--------------- sfc - was_changed = sfc%allocate_arrays(Model, Atm_block, .false., .true.) - call sfc%fill_2d_names(Model, .true.) - call sfc%fill_3d_names(Model, .true.) - - if(Model%iopt_lake == 2 .and. Model%lkm > 0) then - call clm_lake%allocate_data(Model) - endif - - if(Model%rrfs_sd) then - call rrfs_sd%allocate_data(Model) - endif - - end subroutine fv3atm_restart_register - - subroutine fv_phy_restart_output(GFS_Restart, Atm_block) - - implicit none - - type(GFS_restart_type), intent(in) :: GFS_Restart - type(block_control_type), intent(in) :: Atm_block - -!*** local variables - integer :: i, j, k, n - integer :: nb, ix, num - integer :: isc, iec, jsc, jec, npz, nx, ny - integer(8) :: rchk - - isc = Atm_block%isc - iec = Atm_block%iec - jsc = Atm_block%jsc - jec = Atm_block%jec - npz = Atm_block%npz - nx = (iec - isc + 1) - ny = (jec - jsc + 1) - - !--- register the restart fields - if (.not. allocated(phy_var2)) then - write(0,*)'phy_var2 must be allocated' - endif - if (.not. allocated(phy_var3)) then - write(0,*)'phy_var3 must be allocated' - endif - - !--- 2D variables - do num = 1,nvar2d + if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then + ! Tell clm_lake to register all of its fields + call clm_lake%register_fields(Sfc_restart) + endif + + if(Model%rrfs_sd) then + call rrfs_sd_state%register_fields(Sfc_restart) + endif + + ! Register 2D surface property fields (except lake, smoke, and dust) + call sfc%register_2d_fields(Model, Sfc_restart, .false., .true.) + + ! Determine list of 3D surface property fields names: + call sfc%fill_3d_names(Model, .true.) + + ! Register 3D surface property fields (except lake, smoke, and dust) + call sfc%register_3d_fields(Model, Sfc_restart, .false., .true.) + + ! Tell clm_lake to copy Sfcprop data to its internal temporary arrays. + if(Model%lkm>0 .and. Model%iopt_lake==Model%iopt_lake_clm) then + call clm_lake%copy_from_grid(Model,Atm_block,Sfcprop) + endif + + if(Model%rrfs_sd) then + call rrfs_sd_state%copy_from_grid(Model,Atm_block,Sfcprop) + endif + + call sfc%copy_from_grid(Model, Atm_block, Sfcprop) + + call write_restart(Sfc_restart) + call close_file(Sfc_restart) + + ! A standard-compliant Fortran 2003 compiler will call rrfs_sd_final and clm_lake_final here + + end subroutine sfc_prop_restart_write + + !---------------------------------------------------------------------- + ! phys_restart_read + !---------------------------------------------------------------------- + ! creates and populates a data type which is then used to "register" + ! restart variables with the GFDL FMS restart subsystem. + ! calls a GFDL FMS routine to restore the data from a restart file. + ! calculates sncovr if it is not present in the restart file. + ! + ! calls: register_restart_field, restart_state, free_restart + ! + ! opens: phys_data.tile?.nc + ! + !---------------------------------------------------------------------- + subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_rst_cksum) + implicit none + !--- interface variable definitions + type(GFS_restart_type), intent(in) :: GFS_Restart + type(block_control_type), intent(in) :: Atm_block + type(GFS_control_type), intent(in) :: Model + type(domain2d), intent(in) :: fv_domain + logical, intent(in) :: ignore_rst_cksum + !--- local variables + integer :: i, j, k, nb, ix, num + integer :: isc, iec, jsc, jec, nx, ny + integer :: id_restart + integer :: fdiag, ldiag + 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 + + type(phy_data_type) :: phy + type(FmsNetcdfDomainFile_t) :: Phy_restart + + isc = Atm_block%isc + iec = Atm_block%iec + jsc = Atm_block%jsc + jec = Atm_block%jec + nx = (iec - isc + 1) + ny = (jec - jsc + 1) + + phy%npz = Atm_block%npz + phy%nvar2d = GFS_Restart%num2d + phy%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', phy%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. associated(phy%var2)) then + allocate (phy%var2(nx,ny,phy%nvar2d), phy%var2_names(phy%nvar2d)) + allocate (phy%var3(nx,ny,phy%npz,phy%nvar3d), phy%var3_names(phy%nvar3d)) + phy%var2 = zero + phy%var3 = zero + do num = 1,phy%nvar2d + phy%var2_names(num) = trim(GFS_Restart%name2d(num)) + enddo + do num = 1,phy%nvar3d + phy%var3_names(num) = trim(GFS_Restart%name3d(num)) + enddo + + do num = 1,phy%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,phy%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) + 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, ignore_checksum=ignore_rst_cksum) + 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) + do num = 1,phy%nvar2d do nb = 1,Atm_block%nblks 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) + GFS_Restart%data(nb,num)%var2p(ix) = phy%var2(i,j,num) enddo enddo enddo + !-- if restart from init time, reset accumulated diag fields + if( Model%phour < 1.e-7) then + do num = fdiag,ldiag + !$omp parallel do default(shared) private(i, j, nb, ix) + do nb = 1,Atm_block%nblks + 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 + GFS_Restart%data(nb,num)%var2p(ix) = zero + enddo + enddo + enddo + endif + do num = 1,phy%nvar3d + !$omp parallel do default(shared) private(i, j, k, nb, ix) + do nb = 1,Atm_block%nblks + do k=1,phy%npz + 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 + GFS_Restart%data(nb,num)%var3p(ix,k) = phy%var3(i,j,k,num) + enddo + enddo + enddo + enddo + + end subroutine phys_restart_read + + + !---------------------------------------------------------------------- + ! phys_restart_write + !---------------------------------------------------------------------- + ! routine to write out GFS surface restarts via the GFDL FMS restart + ! subsystem. + ! takes an optional argument to append timestamps for intermediate + ! restarts. + ! + ! calls: register_restart_field, save_restart + !---------------------------------------------------------------------- + subroutine phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timestamp) + implicit none + !--- interface variable definitions + type(GFS_restart_type), intent(in) :: GFS_Restart + type(block_control_type), intent(in) :: Atm_block + type(GFS_control_type), intent(in) :: Model + type(domain2d), intent(in) :: fv_domain + character(len=32), optional, intent(in) :: timestamp + !--- local variables + integer :: i, j, k, nb, ix, num + integer :: isc, iec, jsc, jec, nx, ny + integer :: id_restart + 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 + + type(phy_data_type) :: phy + type(FmsNetcdfDomainFile_t) :: Phy_restart + + isc = Atm_block%isc + iec = Atm_block%iec + jsc = Atm_block%jsc + jec = Atm_block%jec + nx = (iec - isc + 1) + ny = (jec - jsc + 1) + + phy%npz = Atm_block%npz + phy%nvar2d = GFS_Restart%num2d + phy%nvar3d = GFS_Restart%num3d + + !--- 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', phy%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(phy%npz) ) + do i=1, phy%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. associated(phy%var2)) then + allocate (phy%var2(nx,ny,phy%nvar2d), phy%var2_names(phy%nvar2d)) + allocate (phy%var3(nx,ny,phy%npz,phy%nvar3d), phy%var3_names(phy%nvar3d)) + phy%var2 = zero + phy%var3 = zero + do num = 1,phy%nvar2d + phy%var2_names(num) = trim(GFS_Restart%name2d(num)) + enddo + do num = 1,phy%nvar3d + phy%var3_names(num) = trim(GFS_Restart%name3d(num)) + enddo + endif + + do num = 1,phy%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,phy%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,phy%nvar2d + do nb = 1,Atm_block%nblks + 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) + enddo + enddo + enddo !--- 3D variables - do num = 1,nvar3d + !$omp parallel do default(shared) private(i, j, k, num, nb, ix) + do num = 1,phy%nvar3d do nb = 1,Atm_block%nblks - do k=1,npz + do k=1,phy%npz 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) + phy%var3(i,j,k,num) = GFS_Restart%data(nb,num)%var3p(ix,k) enddo enddo enddo enddo - end subroutine fv_phy_restart_output + call write_restart(Phy_restart) + call close_file(Phy_restart) - subroutine fv_sfc_restart_output(Sfcprop, Atm_block, Model) - !--- interface variable definitions - implicit none + end subroutine phys_restart_write + + subroutine fv3atm_restart_register (Sfcprop, GFS_restart, Atm_block, Model) + + ! this subroutine must allocate all data buffers and set the variable names + ! for both 'phy' and 'sfc' restart bundles + + implicit none type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) + type(GFS_restart_type), intent(in) :: GFS_Restart type(block_control_type), intent(in) :: Atm_block type(GFS_control_type), intent(in) :: Model - call sfc%copy_from_grid(Model, Atm_block, Sfcprop) + logical was_changed + integer :: isc, iec, jsc, jec, nx, ny + integer :: num + + isc = Atm_block%isc + iec = Atm_block%iec + jsc = Atm_block%jsc + jec = Atm_block%jec + phy_quilt%npz = Atm_block%npz + nx = (iec - isc + 1) + ny = (jec - jsc + 1) + + !--------------- phy + phy_quilt%nvar2d = GFS_Restart%num2d + phy_quilt%nvar3d = GFS_Restart%num3d + + allocate (phy_quilt%var2(nx,ny,phy_quilt%nvar2d), phy_quilt%var2_names(phy_quilt%nvar2d)) + allocate (phy_quilt%var3(nx,ny,phy_quilt%npz,phy_quilt%nvar3d), phy_quilt%var3_names(phy_quilt%nvar3d)) + phy_quilt%var2 = zero + phy_quilt%var3 = zero + do num = 1,phy_quilt%nvar2d + phy_quilt%var2_names(num) = trim(GFS_Restart%name2d(num)) + enddo + do num = 1,phy_quilt%nvar3d + phy_quilt%var3_names(num) = trim(GFS_Restart%name3d(num)) + enddo + + !--------------- sfc + was_changed = sfc_quilt%allocate_arrays(Model, Atm_block, .false., .true.) + call sfc_quilt%fill_2d_names(Model, .true.) + call sfc_quilt%fill_3d_names(Model, .true.) + if(Model%iopt_lake == 2 .and. Model%lkm > 0) then - call clm_lake%copy_from_grid(Model, Atm_block, Sfcprop) + call clm_lake_quilt%allocate_data(Model) endif + if(Model%rrfs_sd) then - call rrfs_sd%copy_from_grid(Model, Atm_block, Sfcprop) + call rrfs_sd_quilt%allocate_data(Model) endif - end subroutine fv_sfc_restart_output + end subroutine fv3atm_restart_register + + subroutine fv_phy_restart_output(GFS_Restart, Atm_block) + + implicit none + + type(GFS_restart_type), intent(in) :: GFS_Restart + type(block_control_type), intent(in) :: Atm_block + + !*** local variables + integer :: i, j, k, n + integer :: nb, ix, num + integer :: isc, iec, jsc, jec, nx, ny + integer(8) :: rchk + + isc = Atm_block%isc + iec = Atm_block%iec + jsc = Atm_block%jsc + jec = Atm_block%jec + phy_quilt%npz = Atm_block%npz + nx = (iec - isc + 1) + ny = (jec - jsc + 1) + + !--- register the restart fields + if (.not. associated(phy_quilt%var2)) then + write(0,*)'phy_quilt%var2 must be allocated' + endif + if (.not. associated(phy_quilt%var3)) then + write(0,*)'phy_quilt%var3 must be allocated' + endif + + !--- 2D variables + do num = 1,phy_quilt%nvar2d + do nb = 1,Atm_block%nblks + 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_quilt%var2(i,j,num) = GFS_Restart%data(nb,num)%var2p(ix) + enddo + enddo + enddo + + !--- 3D variables + do num = 1,phy_quilt%nvar3d + do nb = 1,Atm_block%nblks + do k=1,phy_quilt%npz + 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_quilt%var3(i,j,k,num) = GFS_Restart%data(nb,num)%var3p(ix,k) + enddo + enddo + enddo + enddo + + end subroutine fv_phy_restart_output + + subroutine fv_sfc_restart_output(Sfcprop, Atm_block, Model) + !--- interface variable definitions + implicit none - subroutine fv_phy_restart_bundle_setup(bundle, grid, rc) -! -!------------------------------------------------------------- -!*** set esmf bundle for phys restart fields -!------------------------------------------------------------ -! - use esmf + type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) + type(block_control_type), intent(in) :: Atm_block + type(GFS_control_type), intent(in) :: Model - implicit none + call sfc_quilt%copy_from_grid(Model, Atm_block, Sfcprop) + if(Model%iopt_lake == 2 .and. Model%lkm > 0) then + call clm_lake_quilt%copy_from_grid(Model, Atm_block, Sfcprop) + endif + if(Model%rrfs_sd) then + call rrfs_sd_quilt%copy_from_grid(Model, Atm_block, Sfcprop) + endif - type(ESMF_FieldBundle),intent(inout) :: bundle - type(ESMF_Grid),intent(inout) :: grid - integer,intent(out) :: rc + end subroutine fv_sfc_restart_output -!*** local variables - integer i, j, k, n - character(128) :: bdl_name - type(ESMF_Field) :: field - character(128) :: outputfile - real(kind_phys),dimension(:,:),pointer :: temp_r2d - real(kind_phys),dimension(:,:,:),pointer :: temp_r3d - integer :: num - real(kind_phys), allocatable :: axis_values(:) + subroutine fv_phy_restart_bundle_setup(bundle, grid, rc) + ! + !------------------------------------------------------------- + !*** set esmf bundle for phys restart fields + !------------------------------------------------------------ + ! + use esmf - if (.not. allocated(phy_var2)) then - write(0,*)'ERROR phy_var2, NOT allocated' - endif - if (.not. allocated(phy_var3)) then - write(0,*)'ERROR phy_var3 NOT allocated' - endif + implicit none - phy_bundle = bundle + type(ESMF_FieldBundle),intent(inout) :: bundle + type(ESMF_Grid),intent(inout) :: grid + integer,intent(out) :: rc - call ESMF_FieldBundleGet(bundle, name=bdl_name,rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + !*** local variables + integer i, j, k, n + character(128) :: bdl_name + type(ESMF_Field) :: field + character(128) :: outputfile + real(kind_phys),dimension(:,:),pointer :: temp_r2d + real(kind_phys),dimension(:,:,:),pointer :: temp_r3d + integer :: num + real(kind_phys), allocatable :: axis_values(:) - outputfile = trim(bdl_name) + if (.not. associated(phy_quilt%var2)) then + write(0,*)'ERROR phy_quilt%var2, NOT allocated' + endif + if (.not. associated(phy_quilt%var3)) then + write(0,*)'ERROR phy_quilt%var3 NOT allocated' + endif + + call ESMF_FieldBundleGet(bundle, name=bdl_name,rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return -!*** add esmf fields + outputfile = trim(bdl_name) - do num = 1,nvar2d - temp_r2d => phy_var2(:,:,num) - call create_2d_field_and_add_to_bundle(temp_r2d, trim(phy_var2_names(num)), trim(outputfile), grid, bundle) - enddo + !*** add esmf fields - allocate(axis_values(npz)) - axis_values = (/ (i, i=1,npz) /) + do num = 1,phy_quilt%nvar2d + temp_r2d => phy_quilt%var2(:,:,num) + call create_2d_field_and_add_to_bundle(temp_r2d, trim(phy_quilt%var2_names(num)), trim(outputfile), grid, bundle) + enddo - do num = 1,nvar3d - temp_r3d => phy_var3(:,:,:,num) - call create_3d_field_and_add_to_bundle(temp_r3d, trim(phy_var3_names(num)), "zaxis_1", axis_values, trim(outputfile), grid, bundle) - enddo + allocate(axis_values(phy_quilt%npz)) + axis_values = (/ (i, i=1,phy_quilt%npz) /) - deallocate(axis_values) + do num = 1,phy_quilt%nvar3d + temp_r3d => phy_quilt%var3(:,:,:,num) + call create_3d_field_and_add_to_bundle(temp_r3d, trim(phy_quilt%var3_names(num)), "zaxis_1", axis_values, trim(outputfile), grid, bundle) + enddo - end subroutine fv_phy_restart_bundle_setup + deallocate(axis_values) - subroutine fv_sfc_restart_bundle_setup(bundle, grid, Model, rc) -! -!------------------------------------------------------------- -!*** set esmf bundle for sfc restart fields -!------------------------------------------------------------ -! - use esmf + end subroutine fv_phy_restart_bundle_setup - implicit none + subroutine fv_sfc_restart_bundle_setup(bundle, grid, Model, rc) + ! + !------------------------------------------------------------- + !*** set esmf bundle for sfc restart fields + !------------------------------------------------------------ + ! + use esmf - type(ESMF_FieldBundle),intent(inout) :: bundle - type(ESMF_Grid),intent(inout) :: grid - type(GFS_control_type), intent(in) :: Model - integer,intent(out) :: rc + implicit none -!*** local variables - integer i, j, k, n - character(128) :: sfcbdl_name - type(ESMF_Field) :: field - character(128) :: outputfile - real(kind_phys),dimension(:,:),pointer :: temp_r2d - real(kind_phys),dimension(:,:,:),pointer :: temp_r3d + type(ESMF_FieldBundle),intent(inout) :: bundle + type(ESMF_Grid),intent(inout) :: grid + type(GFS_control_type), intent(in) :: Model + integer,intent(out) :: rc - integer :: num + !*** local variables + integer i, j, k, n + character(128) :: sfcbdl_name + type(ESMF_Field) :: field + character(128) :: outputfile + real(kind_phys),dimension(:,:),pointer :: temp_r2d + real(kind_phys),dimension(:,:,:),pointer :: temp_r3d - sfc_bundle = bundle + integer :: num - call ESMF_FieldBundleGet(bundle, name=sfcbdl_name,rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + call ESMF_FieldBundleGet(bundle, name=sfcbdl_name,rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - outputfile = trim(sfcbdl_name) + outputfile = trim(sfcbdl_name) -!*** add esmf fields + !*** add esmf fields - call sfc%bundle_2d_fields(bundle, grid, Model, outputfile) - call sfc%bundle_3d_fields(bundle, grid, Model, outputfile) + call sfc_quilt%bundle_2d_fields(bundle, grid, Model, outputfile) + call sfc_quilt%bundle_3d_fields(bundle, grid, Model, outputfile) - if(Model%iopt_lake == 2 .and. Model%lkm > 0) then - call clm_lake%bundle_fields(bundle, grid, Model, outputfile) - endif - if(Model%rrfs_sd) then - call rrfs_sd%bundle_fields(bundle, grid, Model, outputfile) - endif + if(Model%iopt_lake == 2 .and. Model%lkm > 0) then + call clm_lake_quilt%bundle_fields(bundle, grid, Model, outputfile) + endif + if(Model%rrfs_sd) then + call rrfs_sd_quilt%bundle_fields(bundle, grid, Model, outputfile) + endif - end subroutine fv_sfc_restart_bundle_setup + end subroutine fv_sfc_restart_bundle_setup end module fv3atm_restart_io_mod From 9e7d86bc4d7bc55731ce5c3185db18f0aa308d48 Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Tue, 30 May 2023 15:48:42 +0000 Subject: [PATCH 23/27] more cleanup --- io/fv3atm_common_io.F90 | 4 +- io/fv3atm_history_io.F90 | 1657 +++++++++++++++++++------------------- io/fv3atm_restart_io.F90 | 503 +++++------- io/fv3atm_sfc_io.F90 | 3 +- 4 files changed, 1048 insertions(+), 1119 deletions(-) diff --git a/io/fv3atm_common_io.F90 b/io/fv3atm_common_io.F90 index 4ce7c5a2a..c237ceb90 100644 --- a/io/fv3atm_common_io.F90 +++ b/io/fv3atm_common_io.F90 @@ -24,6 +24,8 @@ module fv3atm_common_io public :: create_3d_field_and_add_to_bundle public :: add_zaxis_to_field + public :: get_nx_ny_from_atm + interface copy_from_GFS_Data module procedure copy_from_GFS_Data_2d_phys2phys, & copy_from_GFS_Data_3d_phys2phys, & @@ -51,8 +53,6 @@ module fv3atm_common_io GFS_data_transfer_2d_stack_phys2phys end interface GFS_data_transfer - public :: get_nx_ny_from_atm - contains pure subroutine get_nx_ny_from_atm(Atm_block, nx, ny) diff --git a/io/fv3atm_history_io.F90 b/io/fv3atm_history_io.F90 index 43cb33b60..7d1467050 100644 --- a/io/fv3atm_history_io.F90 +++ b/io/fv3atm_history_io.F90 @@ -1,50 +1,50 @@ module fv3atm_history_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 -! atmospheric time tendencies for use by other components, namely -! the atmospheric dynamical core. -! -! NOTE: This module currently supports only the operational GFS -! parameterizations as of September 2015. Further development -! is needed to support the full suite of physical -! parameterizations present in the GFS physics package. -!----------------------------------------------------------------------- -! -!--- FMS/GFDL modules + !----------------------------------------------------------------------- + ! 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 + ! atmospheric time tendencies for use by other components, namely + ! the atmospheric dynamical core. + ! + ! NOTE: This module currently supports only the operational GFS + ! parameterizations as of September 2015. Further development + ! is needed to support the full suite of physical + ! parameterizations present in the GFS physics package. + !----------------------------------------------------------------------- + ! + !--- FMS/GFDL modules use block_control_mod, only: block_control_type use mpp_mod, only: mpp_error, mpp_pe, mpp_root_pe, & - mpp_chksum, NOTE, FATAL + mpp_chksum, NOTE, FATAL 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 + 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 use diag_axis_mod, only: get_axis_global_length, get_diag_axis, & - get_diag_axis_name + get_diag_axis_name use diag_data_mod, only: output_fields, max_output_fields use diag_util_mod, only: find_input_field use constants_mod, only: grav, rdgas use physcons, only: con_tice !saltwater freezing temp (K) use fv3atm_clm_lake_io, only: clm_lake_data_type -! -!--- GFS_typedefs + ! + !--- GFS_typedefs use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, & - GFS_data_type, kind_phys + GFS_data_type, kind_phys use GFS_restart, only: GFS_restart_type use GFS_diagnostics, only: GFS_externaldiag_type use fv3atm_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data -! -!----------------------------------------------------------------------- + ! + !----------------------------------------------------------------------- implicit none private @@ -97,24 +97,24 @@ module fv3atm_history_io_mod type(history_type) :: shared_history_data - CONTAINS - -!------------------------------------------------------------------------- -!--- gfdl_diag_register --- -!------------------------------------------------------------------------- -! creates and populates a data type which is then used to "register" -! GFS physics diagnostic variables with the GFDL FMS diagnostic manager. -! includes short & long names, units, conversion factors, etc. -! there is no copying of data, but instead a clever use of pointers. -! calls a GFDL FMS routine to register diagnositcs and compare against -! the diag_table to determine what variables are to be output. -! -! calls: register_diag_field -!------------------------------------------------------------------------- +CONTAINS + + !------------------------------------------------------------------------- + !--- gfdl_diag_register --- + !------------------------------------------------------------------------- + ! creates and populates a data type which is then used to "register" + ! GFS physics diagnostic variables with the GFDL FMS diagnostic manager. + ! includes short & long names, units, conversion factors, etc. + ! there is no copying of data, but instead a clever use of pointers. + ! calls a GFDL FMS routine to register diagnositcs and compare against + ! the diag_table to determine what variables are to be output. + ! + ! calls: register_diag_field + !------------------------------------------------------------------------- subroutine fv3atm_diag_register(Diag, Time, Atm_block, Model, xlon, xlat, axes) use physcons, only: con_g implicit none -!--- subroutine interface variable definitions + !--- subroutine interface variable definitions type(GFS_externaldiag_type), intent(inout) :: Diag(:) type(time_type), intent(in) :: Time type (block_control_type), intent(in) :: Atm_block @@ -126,10 +126,64 @@ subroutine fv3atm_diag_register(Diag, Time, Atm_block, Model, xlon, xlat, axes) call shared_history_data%register(Diag, Time, Atm_block, Model, xlon, xlat, axes) end subroutine fv3atm_diag_register + !------------------------------------------------------------------------- + !--- gfs_diag_output --- + !------------------------------------------------------------------------- + ! routine to transfer the diagnostic data to the gfdl fms diagnostic + ! manager for eventual output to the history files. + ! + ! calls: send_data + !------------------------------------------------------------------------- + subroutine fv3atm_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & + dt, time_int, time_intfull, time_radsw, time_radlw) + !--- subroutine interface variable definitions + type(time_type), intent(in) :: time + type(GFS_externaldiag_type), intent(in) :: diag(:) + type (block_control_type), intent(in) :: atm_block + integer, intent(in) :: nx, ny, levs, ntcw, ntoz + real(kind=kind_phys), intent(in) :: dt + real(kind=kind_phys), intent(in) :: time_int + real(kind=kind_phys), intent(in) :: time_intfull + real(kind=kind_phys), intent(in) :: time_radsw + real(kind=kind_phys), intent(in) :: time_radlw + + call shared_history_data%output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & + dt, time_int, time_intfull, time_radsw, time_radlw) + + end subroutine fv3atm_diag_output + +#ifdef use_WRTCOMP + subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nbdlphys, rc) + ! + !------------------------------------------------------------- + !*** set esmf bundle for phys output fields + !------------------------------------------------------------ + ! + use esmf + use diag_data_mod, ONLY: diag_atttype + ! + implicit none + ! + type(GFS_externaldiag_type),intent(in) :: Diag(:) + integer, intent(in) :: axes(:) + type(ESMF_FieldBundle),intent(inout) :: phys_bundle(:) + type(ESMF_Grid),intent(inout) :: fcst_grid + logical,intent(in) :: quilting + integer, intent(in) :: nbdlphys + integer,intent(out) :: rc + + call shared_history_data%bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nbdlphys, rc) + end subroutine fv_phys_bundle_setup +#endif + ! + !--------------------------------------------------------------------- + !*** Private subroutines + !--------------------------------------------------------------------- + ! subroutine history_type_register(hist, Diag, Time, Atm_block, Model, xlon, xlat, axes) use physcons, only: con_g implicit none -!--- subroutine interface variable definitions + !--- subroutine interface variable definitions class(history_type) :: hist type(GFS_externaldiag_type), intent(inout) :: Diag(:) type(time_type), intent(in) :: Time @@ -138,9 +192,8 @@ subroutine history_type_register(hist, Diag, Time, Atm_block, Model, xlon, xlat, real(kind=kind_phys), intent(in) :: xlon(:,:) real(kind=kind_phys), intent(in) :: xlat(:,:) integer, dimension(4), intent(in) :: axes -!--- local variables + !--- local variables integer :: idx, nrgst_bl, nrgst_nb, nrgst_vctbl - integer :: total_outputlevel = 0 hist%isco = Atm_block%isc hist%ieco = Atm_block%iec @@ -148,16 +201,16 @@ subroutine history_type_register(hist, Diag, Time, Atm_block, Model, xlon, xlat, hist%jeco = Atm_block%jec hist%levo = model%levs hist%fhzero = nint(Model%fhzero) -! hist%ncld = Model%ncld + ! hist%ncld = Model%ncld hist%ncld = Model%imp_physics hist%nsoil = Model%lsoil hist%dtp = Model%dtp hist%imp_physics = Model%imp_physics hist%landsfcmdl = Model%lsm -! print *,'in fv3atm_diag_register,hist%ncld=',Model%ncld,Model%lsoil,Model%imp_physics, & -! ' hist%dtp=',hist%dtp,' hist%landsfcmdl=',Model%lsm -! -!save lon/lat for vector interpolation + ! print *,'in fv3atm_diag_register,hist%ncld=',Model%ncld,Model%lsoil,Model%imp_physics, & + ! ' hist%dtp=',hist%dtp,' hist%landsfcmdl=',Model%lsm + ! + !save lon/lat for vector interpolation allocate(hist%lon(hist%isco:hist%ieco,hist%jsco:hist%jeco)) allocate(hist%lat(hist%isco:hist%ieco,hist%jsco:hist%jeco)) hist%lon = xlon @@ -184,46 +237,45 @@ subroutine history_type_register(hist, Diag, Time, Atm_block, Model, xlon, xlat, call mpp_error(fatal, 'gfs_driver::gfs_diag_register - attempt to register an undefined variable') endif Diag(idx)%id = register_diag_field (trim(Diag(idx)%mod_name), trim(Diag(idx)%name), & - axes(1:Diag(idx)%axes), Time, trim(Diag(idx)%desc), & - trim(Diag(idx)%unit), missing_value=real(missing_value)) + axes(1:Diag(idx)%axes), Time, trim(Diag(idx)%desc), & + trim(Diag(idx)%unit), missing_value=real(missing_value)) if(Diag(idx)%id > 0) then if (Diag(idx)%axes == 2) then - if( index(trim(Diag(idx)%intpl_method),'bilinear') > 0 ) then - nrgst_bl = nrgst_bl + 1 - hist%nstt(idx) = nrgst_bl - else if (trim(Diag(idx)%intpl_method) == 'nearest_stod' ) then - nrgst_nb = nrgst_nb + 1 - hist%nstt(idx) = nrgst_nb - endif - if(trim(Diag(idx)%intpl_method) == 'vector_bilinear') then - if(Diag(idx)%name(1:1) == 'v' .or. Diag(idx)%name(1:1) == 'V') then - nrgst_vctbl = nrgst_vctbl + 1 - hist%nstt_vctbl(idx) = nrgst_vctbl -! print *,'in phy_setup, vector_bilinear, name=', trim(Diag(idx)%name),' nstt_vctbl=', hist%nstt_vctbl(idx), 'idx=',idx - endif - endif + if( index(trim(Diag(idx)%intpl_method),'bilinear') > 0 ) then + nrgst_bl = nrgst_bl + 1 + hist%nstt(idx) = nrgst_bl + else if (trim(Diag(idx)%intpl_method) == 'nearest_stod' ) then + nrgst_nb = nrgst_nb + 1 + hist%nstt(idx) = nrgst_nb + endif + if(trim(Diag(idx)%intpl_method) == 'vector_bilinear') then + if(Diag(idx)%name(1:1) == 'v' .or. Diag(idx)%name(1:1) == 'V') then + nrgst_vctbl = nrgst_vctbl + 1 + hist%nstt_vctbl(idx) = nrgst_vctbl + ! print *,'in phy_setup, vector_bilinear, name=', trim(Diag(idx)%name),' nstt_vctbl=', hist%nstt_vctbl(idx), 'idx=',idx + endif + endif else if (diag(idx)%axes == 3) then - if( index(trim(diag(idx)%intpl_method),'bilinear') > 0 ) then - hist%nstt(idx) = nrgst_bl + 1 - nrgst_bl = nrgst_bl + hist%levo - else if (trim(diag(idx)%intpl_method) == 'nearest_stod' ) then - hist%nstt(idx) = nrgst_nb + 1 - nrgst_nb = nrgst_nb + hist%levo - endif - if(trim(diag(idx)%intpl_method) == 'vector_bilinear') then - if(diag(idx)%name(1:1) == 'v' .or. diag(idx)%name(1:1) == 'V') then - hist%nstt_vctbl(idx) = nrgst_vctbl + 1 - nrgst_vctbl = nrgst_vctbl + hist%levo -! print *,'in phy_setup, vector_bilinear, name=', trim(diag(idx)%name),' nstt_vctbl=', hist%nstt_vctbl(idx), 'idx=',idx - endif - endif - hist%num_axes_phys = 3 + if( index(trim(diag(idx)%intpl_method),'bilinear') > 0 ) then + hist%nstt(idx) = nrgst_bl + 1 + nrgst_bl = nrgst_bl + hist%levo + else if (trim(diag(idx)%intpl_method) == 'nearest_stod' ) then + hist%nstt(idx) = nrgst_nb + 1 + nrgst_nb = nrgst_nb + hist%levo + endif + if(trim(diag(idx)%intpl_method) == 'vector_bilinear') then + if(diag(idx)%name(1:1) == 'v' .or. diag(idx)%name(1:1) == 'V') then + hist%nstt_vctbl(idx) = nrgst_vctbl + 1 + nrgst_vctbl = nrgst_vctbl + hist%levo + ! print *,'in phy_setup, vector_bilinear, name=', trim(diag(idx)%name),' nstt_vctbl=', hist%nstt_vctbl(idx), 'idx=',idx + endif + endif + hist%num_axes_phys = 3 endif endif enddo - total_outputlevel = nrgst_bl + nrgst_nb allocate(hist%buffer_phys_bl(hist%isco:hist%ieco,hist%jsco:hist%jeco,nrgst_bl)) allocate(hist%buffer_phys_nb(hist%isco:hist%ieco,hist%jsco:hist%jeco,nrgst_nb)) allocate(hist%buffer_phys_windvect(3,hist%isco:hist%ieco,hist%jsco:hist%jeco,nrgst_vctbl)) @@ -231,41 +283,15 @@ subroutine history_type_register(hist, Diag, Time, Atm_block, Model, xlon, xlat, hist%buffer_phys_nb = zero hist%buffer_phys_windvect = zero if(mpp_pe() == mpp_root_pe()) print *,'in fv3atm_diag_register, nrgst_bl=',nrgst_bl,' nrgst_nb=',nrgst_nb, & - ' nrgst_vctbl=',nrgst_vctbl, 'hist%isco=',hist%isco,hist%ieco,'hist%jsco=',hist%jsco,hist%jeco,' hist%num_axes_phys=', hist%num_axes_phys + ' nrgst_vctbl=',nrgst_vctbl, 'hist%isco=',hist%isco,hist%ieco,'hist%jsco=',hist%jsco,hist%jeco,' hist%num_axes_phys=', hist%num_axes_phys end subroutine history_type_register -!------------------------------------------------------------------------- - - -!------------------------------------------------------------------------- -!--- gfs_diag_output --- -!------------------------------------------------------------------------- -! routine to transfer the diagnostic data to the gfdl fms diagnostic -! manager for eventual output to the history files. -! -! calls: send_data -!------------------------------------------------------------------------- - subroutine fv3atm_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & - dt, time_int, time_intfull, time_radsw, time_radlw) -!--- subroutine interface variable definitions - type(time_type), intent(in) :: time - type(GFS_externaldiag_type), intent(in) :: diag(:) - type (block_control_type), intent(in) :: atm_block - integer, intent(in) :: nx, ny, levs, ntcw, ntoz - real(kind=kind_phys), intent(in) :: dt - real(kind=kind_phys), intent(in) :: time_int - real(kind=kind_phys), intent(in) :: time_intfull - real(kind=kind_phys), intent(in) :: time_radsw - real(kind=kind_phys), intent(in) :: time_radlw - call shared_history_data%output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & - dt, time_int, time_intfull, time_radsw, time_radlw) - - end subroutine fv3atm_diag_output + !------------------------------------------------------------------------- subroutine history_type_output(hist, time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & - dt, time_int, time_intfull, time_radsw, time_radlw) -!--- subroutine interface variable definitions + dt, time_int, time_intfull, time_radsw, time_radlw) + !--- subroutine interface variable definitions class(history_type) :: hist type(time_type), intent(in) :: time type(GFS_externaldiag_type), intent(in) :: diag(:) @@ -276,206 +302,193 @@ subroutine history_type_output(hist, time, diag, atm_block, nx, ny, levs, ntcw, real(kind=kind_phys), intent(in) :: time_intfull real(kind=kind_phys), intent(in) :: time_radsw real(kind=kind_phys), intent(in) :: time_radlw -!--- local variables - integer :: i, j, k, idx, nblks, nb, ix, ii, jj - integer :: is_in, js_in, isc, jsc + !--- local variables + integer :: i, j, k, idx, nb, ix, ii, jj character(len=2) :: xtra #ifdef CCPP_32BIT - real, dimension(nx*ny) :: var2p - real, dimension(nx*ny,levs) :: var3p real, dimension(nx,ny) :: var2 real, dimension(nx,ny,levs) :: var3 #else - real(kind=kind_phys), dimension(nx*ny) :: var2p - real(kind=kind_phys), dimension(nx*ny,levs) :: var3p real(kind=kind_phys), dimension(nx,ny) :: var2 real(kind=kind_phys), dimension(nx,ny,levs) :: var3 #endif - real(kind=kind_phys) :: rdt, rtime_int, rtime_intfull, lcnvfac + real(kind=kind_phys) :: rtime_int, rtime_intfull, lcnvfac real(kind=kind_phys) :: rtime_radsw, rtime_radlw - logical :: used - - nblks = atm_block%nblks - rdt = one/dt - rtime_int = one/time_int - rtime_intfull = one/time_intfull - rtime_radsw = one/time_radsw - rtime_radlw = one/time_radlw - - isc = atm_block%isc - jsc = atm_block%jsc - is_in = atm_block%isc - js_in = atm_block%jsc - -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. time avg, time_int=',time_int - history_loop: do idx = 1,hist%tot_diag_idx - has_id: if (diag(idx)%id > 0) then - lcnvfac = diag(idx)%cnvfac - if (diag(idx)%time_avg) then - if ( trim(diag(idx)%time_avg_kind) == 'full' ) then - lcnvfac = lcnvfac*rtime_intfull -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. full time avg, field=',trim(Diag(idx)%name),' time=',time_intfull - else if ( trim(diag(idx)%time_avg_kind) == 'rad_lw' ) then - lcnvfac = lcnvfac*min(rtime_radlw,rtime_int) -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. rad longwave avg, field=',trim(Diag(idx)%name),' time=',time_radlw - else if ( trim(diag(idx)%time_avg_kind) == 'rad_sw' ) then - lcnvfac = lcnvfac*min(rtime_radsw,rtime_int) -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. rad shortwave avg, field=',trim(Diag(idx)%name),' time=',time_radsw - else if ( trim(diag(idx)%time_avg_kind) == 'rad_swlw_min' ) then - lcnvfac = lcnvfac*min(max(rtime_radsw,rtime_radlw),rtime_int) -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. rad swlw min avg, field=',trim(Diag(idx)%name),' time=',time_radlw,time_radsw,time_int - else - lcnvfac = lcnvfac*rtime_int - endif - endif - if_2d: if (diag(idx)%axes == 2) then - ! Integer data - int_or_real: if (associated(Diag(idx)%data(1)%int2)) then - if (trim(Diag(idx)%intpl_method) == 'nearest_stod') then - var2(1:nx,1:ny) = 0._kind_phys - do j = 1, ny - jj = j + jsc -1 - do i = 1, nx - ii = i + isc -1 - nb = Atm_block%blkno(ii,jj) - ix = Atm_block%ixp(ii,jj) - var2(i,j) = real(Diag(idx)%data(nb)%int2(ix), kind=kind_phys) - enddo - enddo - call hist%store_data(Diag(idx)%id, var2, Time, idx, Diag(idx)%intpl_method, Diag(idx)%name) - else - call mpp_error(FATAL, 'Interpolation method ' // trim(Diag(idx)%intpl_method) // ' for integer variable ' & - // trim(Diag(idx)%name) // ' not supported.') - endif - ! Real data - else ! int_or_real - if_mask: if (trim(diag(idx)%mask) == 'positive_flux') then - !--- albedos are actually a ratio of two radiation surface properties - var2(1:nx,1:ny) = 0._kind_phys - do j = 1, ny - jj = j + jsc -1 - do i = 1, nx - ii = i + isc -1 - nb = Atm_block%blkno(ii,jj) - ix = Atm_block%ixp(ii,jj) - if (Diag(idx)%data(nb)%var21(ix) > 0._kind_phys) & - var2(i,j) = max(0._kind_phys,min(1._kind_phys,Diag(idx)%data(nb)%var2(ix)/Diag(idx)%data(nb)%var21(ix)))*lcnvfac - enddo - enddo - elseif (trim(Diag(idx)%mask) == 'land_ice_only') then - !--- need to "mask" gflux to output valid data over land/ice only - var2(1:nx,1:ny) = missing_value - do j = 1, ny - jj = j + jsc -1 - do i = 1, nx - ii = i + isc -1 - nb = Atm_block%blkno(ii,jj) - ix = Atm_block%ixp(ii,jj) - if (Diag(idx)%data(nb)%var21(ix) /= 0) var2(i,j) = Diag(idx)%data(nb)%var2(ix)*lcnvfac - enddo - enddo - elseif (trim(Diag(idx)%mask) == 'land_only') then - !--- need to "mask" soilm to have value only over land - var2(1:nx,1:ny) = missing_value - do j = 1, ny - jj = j + jsc -1 - do i = 1, nx - ii = i + isc -1 - nb = Atm_block%blkno(ii,jj) - ix = Atm_block%ixp(ii,jj) - if (Diag(idx)%data(nb)%var21(ix) == 1) var2(i,j) = Diag(idx)%data(nb)%var2(ix)*lcnvfac - enddo - enddo - elseif (trim(Diag(idx)%mask) == 'cldmask') then - !--- need to "mask" soilm to have value only over land - var2(1:nx,1:ny) = missing_value - do j = 1, ny - jj = j + jsc -1 - do i = 1, nx - ii = i + isc -1 - nb = Atm_block%blkno(ii,jj) - ix = Atm_block%ixp(ii,jj) - if (Diag(idx)%data(nb)%var21(ix)*100. > 0.5) var2(i,j) = Diag(idx)%data(nb)%var2(ix)*lcnvfac - enddo - enddo - elseif (trim(Diag(idx)%mask) == 'cldmask_ratio') then - !--- need to "mask" soilm to have value only over land - var2(1:nx,1:ny) = missing_value - do j = 1, ny - jj = j + jsc -1 - do i = 1, nx - ii = i + isc -1 - nb = Atm_block%blkno(ii,jj) - ix = Atm_block%ixp(ii,jj) - if (Diag(idx)%data(nb)%var21(ix)*100.*lcnvfac > 0.5) var2(i,j) = Diag(idx)%data(nb)%var2(ix)/ & + + rtime_int = one/time_int + rtime_intfull = one/time_intfull + rtime_radsw = one/time_radsw + rtime_radlw = one/time_radlw + + ! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. time avg, time_int=',time_int + history_loop: do idx = 1,hist%tot_diag_idx + has_id: if (diag(idx)%id > 0) then + lcnvfac = diag(idx)%cnvfac + if (diag(idx)%time_avg) then + if ( trim(diag(idx)%time_avg_kind) == 'full' ) then + lcnvfac = lcnvfac*rtime_intfull + ! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. full time avg, field=',trim(Diag(idx)%name),' time=',time_intfull + else if ( trim(diag(idx)%time_avg_kind) == 'rad_lw' ) then + lcnvfac = lcnvfac*min(rtime_radlw,rtime_int) + ! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. rad longwave avg, field=',trim(Diag(idx)%name),' time=',time_radlw + else if ( trim(diag(idx)%time_avg_kind) == 'rad_sw' ) then + lcnvfac = lcnvfac*min(rtime_radsw,rtime_int) + ! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. rad shortwave avg, field=',trim(Diag(idx)%name),' time=',time_radsw + else if ( trim(diag(idx)%time_avg_kind) == 'rad_swlw_min' ) then + lcnvfac = lcnvfac*min(max(rtime_radsw,rtime_radlw),rtime_int) + ! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. rad swlw min avg, field=',trim(Diag(idx)%name),' time=',time_radlw,time_radsw,time_int + else + lcnvfac = lcnvfac*rtime_int + endif + endif + if_2d: if (diag(idx)%axes == 2) then + ! Integer data + int_or_real: if (associated(Diag(idx)%data(1)%int2)) then + if (trim(Diag(idx)%intpl_method) == 'nearest_stod') then + var2(1:nx,1:ny) = 0._kind_phys + do j = 1, ny + jj = j + Atm_block%jsc -1 + do i = 1, nx + ii = i + Atm_block%isc -1 + nb = Atm_block%blkno(ii,jj) + ix = Atm_block%ixp(ii,jj) + var2(i,j) = real(Diag(idx)%data(nb)%int2(ix), kind=kind_phys) + enddo + enddo + call hist%store_data(Diag(idx)%id, var2, Time, idx, Diag(idx)%intpl_method, Diag(idx)%name) + else + call mpp_error(FATAL, 'Interpolation method ' // trim(Diag(idx)%intpl_method) // ' for integer variable ' & + // trim(Diag(idx)%name) // ' not supported.') + endif + ! Real data + else ! int_or_real + if_mask: if (trim(diag(idx)%mask) == 'positive_flux') then + !--- albedos are actually a ratio of two radiation surface properties + var2(1:nx,1:ny) = 0._kind_phys + do j = 1, ny + jj = j + Atm_block%jsc -1 + do i = 1, nx + ii = i + Atm_block%isc -1 + nb = Atm_block%blkno(ii,jj) + ix = Atm_block%ixp(ii,jj) + if (Diag(idx)%data(nb)%var21(ix) > 0._kind_phys) & + var2(i,j) = max(0._kind_phys,min(1._kind_phys,Diag(idx)%data(nb)%var2(ix)/Diag(idx)%data(nb)%var21(ix)))*lcnvfac + enddo + enddo + elseif (trim(Diag(idx)%mask) == 'land_ice_only') then + !--- need to "mask" gflux to output valid data over land/ice only + var2(1:nx,1:ny) = missing_value + do j = 1, ny + jj = j + Atm_block%jsc -1 + do i = 1, nx + ii = i + Atm_block%isc -1 + nb = Atm_block%blkno(ii,jj) + ix = Atm_block%ixp(ii,jj) + if (Diag(idx)%data(nb)%var21(ix) /= 0) var2(i,j) = Diag(idx)%data(nb)%var2(ix)*lcnvfac + enddo + enddo + elseif (trim(Diag(idx)%mask) == 'land_only') then + !--- need to "mask" soilm to have value only over land + var2(1:nx,1:ny) = missing_value + do j = 1, ny + jj = j + Atm_block%jsc -1 + do i = 1, nx + ii = i + Atm_block%isc -1 + nb = Atm_block%blkno(ii,jj) + ix = Atm_block%ixp(ii,jj) + if (Diag(idx)%data(nb)%var21(ix) == 1) var2(i,j) = Diag(idx)%data(nb)%var2(ix)*lcnvfac + enddo + enddo + elseif (trim(Diag(idx)%mask) == 'cldmask') then + !--- need to "mask" soilm to have value only over land + var2(1:nx,1:ny) = missing_value + do j = 1, ny + jj = j + Atm_block%jsc -1 + do i = 1, nx + ii = i + Atm_block%isc -1 + nb = Atm_block%blkno(ii,jj) + ix = Atm_block%ixp(ii,jj) + if (Diag(idx)%data(nb)%var21(ix)*100. > 0.5) var2(i,j) = Diag(idx)%data(nb)%var2(ix)*lcnvfac + enddo + enddo + elseif (trim(Diag(idx)%mask) == 'cldmask_ratio') then + !--- need to "mask" soilm to have value only over land + var2(1:nx,1:ny) = missing_value + do j = 1, ny + jj = j + Atm_block%jsc -1 + do i = 1, nx + ii = i + Atm_block%isc -1 + nb = Atm_block%blkno(ii,jj) + ix = Atm_block%ixp(ii,jj) + if (Diag(idx)%data(nb)%var21(ix)*100.*lcnvfac > 0.5) var2(i,j) = Diag(idx)%data(nb)%var2(ix)/ & Diag(idx)%data(nb)%var21(ix) - enddo - enddo - elseif (trim(Diag(idx)%mask) == 'pseudo_ps') then - if ( hist%use_wrtgridcomp_output ) then - do j = 1, ny - jj = j + jsc -1 - do i = 1, nx - ii = i + isc -1 - nb = Atm_block%blkno(ii,jj) - ix = Atm_block%ixp(ii,jj) - var2(i,j) = (Diag(idx)%data(nb)%var2(ix)/stndrd_atmos_ps)**(rdgas/grav*stndrd_atmos_lapse) - enddo - enddo - else - do j = 1, ny - jj = j + jsc -1 - do i = 1, nx - ii = i + isc -1 - nb = Atm_block%blkno(ii,jj) - ix = Atm_block%ixp(ii,jj) - var2(i,j) = Diag(idx)%data(nb)%var2(ix) - enddo - enddo - endif - elseif (trim(Diag(idx)%mask) == '') then - do j = 1, ny - jj = j + jsc -1 - do i = 1, nx - ii = i + isc -1 - nb = Atm_block%blkno(ii,jj) - ix = Atm_block%ixp(ii,jj) - var2(i,j) = Diag(idx)%data(nb)%var2(ix)*lcnvfac - enddo - enddo - endif if_mask - endif int_or_real -! used=send_data(Diag(idx)%id, var2, Time) -! print *,'in phys, after store_data, idx=',idx,' var=', trim(Diag(idx)%name) - call hist%store_data(Diag(idx)%id, var2, Time, idx, Diag(idx)%intpl_method, Diag(idx)%name) -! if(trim(Diag(idx)%name) == 'totprcp_ave' ) print *,'in gfs_io, totprcp=',Diag(idx)%data(1)%var2(1:3), & -! ' lcnvfac=', lcnvfac - elseif (Diag(idx)%axes == 3) then - !--- - !--- skipping other 3D variables with the following else statement - !--- -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. 3D fields, idx=',idx,'varname=',trim(diag(idx)%name), & -! 'lcnvfac=',lcnvfac, 'hist%levo=',hist%levo,'nx=',nx,'ny=',ny - do k=1, hist%levo - do j = 1, ny - jj = j + jsc -1 - do i = 1, nx - ii = i + isc -1 - nb = Atm_block%blkno(ii,jj) - ix = Atm_block%ixp(ii,jj) -! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io,sze(Diag(idx)%data(nb)%var3)=', & -! size(Diag(idx)%data(nb)%var3,1),size(Diag(idx)%data(nb)%var3,2) - var3(i,j,k) = Diag(idx)%data(nb)%var3(ix,hist%levo-k+1)*lcnvfac - enddo - enddo - enddo - call hist%store_data3D(Diag(idx)%id, var3, Time, idx, Diag(idx)%intpl_method, Diag(idx)%name) - endif if_2d - endif has_id - end do history_loop - end subroutine history_type_output + enddo + enddo + elseif (trim(Diag(idx)%mask) == 'pseudo_ps') then + if ( hist%use_wrtgridcomp_output ) then + do j = 1, ny + jj = j + Atm_block%jsc -1 + do i = 1, nx + ii = i + Atm_block%isc -1 + nb = Atm_block%blkno(ii,jj) + ix = Atm_block%ixp(ii,jj) + var2(i,j) = (Diag(idx)%data(nb)%var2(ix)/stndrd_atmos_ps)**(rdgas/grav*stndrd_atmos_lapse) + enddo + enddo + else + do j = 1, ny + jj = j + Atm_block%jsc -1 + do i = 1, nx + ii = i + Atm_block%isc -1 + nb = Atm_block%blkno(ii,jj) + ix = Atm_block%ixp(ii,jj) + var2(i,j) = Diag(idx)%data(nb)%var2(ix) + enddo + enddo + endif + elseif (trim(Diag(idx)%mask) == '') then + do j = 1, ny + jj = j + Atm_block%jsc -1 + do i = 1, nx + ii = i + Atm_block%isc -1 + nb = Atm_block%blkno(ii,jj) + ix = Atm_block%ixp(ii,jj) + var2(i,j) = Diag(idx)%data(nb)%var2(ix)*lcnvfac + enddo + enddo + endif if_mask + endif int_or_real + ! used=send_data(Diag(idx)%id, var2, Time) + ! print *,'in phys, after store_data, idx=',idx,' var=', trim(Diag(idx)%name) + call hist%store_data(Diag(idx)%id, var2, Time, idx, Diag(idx)%intpl_method, Diag(idx)%name) + ! if(trim(Diag(idx)%name) == 'totprcp_ave' ) print *,'in gfs_io, totprcp=',Diag(idx)%data(1)%var2(1:3), & + ! ' lcnvfac=', lcnvfac + elseif (Diag(idx)%axes == 3) then + !--- + !--- skipping other 3D variables with the following else statement + !--- + ! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io. 3D fields, idx=',idx,'varname=',trim(diag(idx)%name), & + ! 'lcnvfac=',lcnvfac, 'hist%levo=',hist%levo,'nx=',nx,'ny=',ny + do k=1, hist%levo + do j = 1, ny + jj = j + Atm_block%jsc -1 + do i = 1, nx + ii = i + Atm_block%isc -1 + nb = Atm_block%blkno(ii,jj) + ix = Atm_block%ixp(ii,jj) + ! if(mpp_pe()==mpp_root_pe())print *,'in,fv3atm_io,sze(Diag(idx)%data(nb)%var3)=', & + ! size(Diag(idx)%data(nb)%var3,1),size(Diag(idx)%data(nb)%var3,2) + var3(i,j,k) = Diag(idx)%data(nb)%var3(ix,hist%levo-k+1)*lcnvfac + enddo + enddo + enddo + call hist%store_data3D(Diag(idx)%id, var3, Time, idx, Diag(idx)%intpl_method, Diag(idx)%name) + endif if_2d + endif has_id + end do history_loop + end subroutine history_type_output ! -!------------------------------------------------------------------------- + !------------------------------------------------------------------------- subroutine history_type_store_data(hist,id, work, Time, idx, intpl_method, fldname) implicit none class(history_type) :: hist @@ -489,30 +502,30 @@ subroutine history_type_store_data(hist,id, work, Time, idx, intpl_method, fldna type(time_type), intent(in) :: Time character(*), intent(in) :: intpl_method character(*), intent(in) :: fldname -! + ! real(kind=kind_phys) :: sinlat, sinlon, coslon - integer k,j,i,kb,nv,i1,j1 + integer j,i,nv,i1,j1 logical used -! + ! if_has_id: if( id > 0 ) then if_gridcomp: if( hist%use_wrtgridcomp_output ) then if_interp: if( trim(intpl_method) == 'bilinear') then -!$omp parallel do default(shared) private(i,j) + !$omp parallel do default(shared) private(i,j) do j= hist%jsco,hist%jeco do i= hist%isco,hist%ieco hist%buffer_phys_bl(i,j,hist%nstt(idx)) = work(i-hist%isco+1,j-hist%jsco+1) enddo enddo else if(trim(intpl_method) == 'nearest_stod') then -!$omp parallel do default(shared) private(i,j) + !$omp parallel do default(shared) private(i,j) do j= hist%jsco,hist%jeco do i= hist%isco,hist%ieco hist%buffer_phys_nb(i,j,hist%nstt(idx)) = work(i-hist%isco+1,j-hist%jsco+1) enddo enddo else if(trim(intpl_method) == 'vector_bilinear') then -!first save the data -!$omp parallel do default(shared) private(i,j) + !first save the data + !$omp parallel do default(shared) private(i,j) do j= hist%jsco,hist%jeco do i= hist%isco,hist%ieco hist%buffer_phys_bl(i,j,hist%nstt(idx)) = work(i-hist%isco+1,j-hist%jsco+1) @@ -520,7 +533,7 @@ subroutine history_type_store_data(hist,id, work, Time, idx, intpl_method, fldna enddo if_u_wind: if( fldname(1:1) == 'u' .or. fldname(1:1) == 'U') then if(.not.associated(hist%uwork)) allocate(hist%uwork(hist%isco:hist%ieco,hist%jsco:hist%jeco)) -!$omp parallel do default(shared) private(i,j) + !$omp parallel do default(shared) private(i,j) do j= hist%jsco,hist%jeco do i= hist%isco,hist%ieco hist%uwork(i,j) = work(i-hist%isco+1,j-hist%jsco+1) @@ -530,10 +543,10 @@ subroutine history_type_store_data(hist,id, work, Time, idx, intpl_method, fldna hist%uwork_set = .true. endif if_u_wind if_v_wind: if( fldname(1:1) == 'v' .or. fldname(1:1) == 'V') then -!set up wind vector + !set up wind vector if( hist%uwork_set .and. trim(hist%uwindname(2:)) == trim(fldname(2:))) then nv = hist%nstt_vctbl(idx) -!$omp parallel do default(shared) private(i,j,i1,j1,sinlat,sinlon,coslon) + !$omp parallel do default(shared) private(i,j,i1,j1,sinlat,sinlon,coslon) do j= hist%jsco,hist%jeco j1 = j-hist%jsco+1 do i= hist%isco,hist%ieco @@ -557,11 +570,11 @@ subroutine history_type_store_data(hist,id, work, Time, idx, intpl_method, fldna used = send_data(id, work, Time) endif if_gridcomp endif if_has_id -! + ! end subroutine history_type_store_data -! -!------------------------------------------------------------------------- -! + ! + !------------------------------------------------------------------------- + ! subroutine history_type_store_data3D(hist, id, work, Time, idx, intpl_method, fldname) implicit none class(history_type) :: hist @@ -575,15 +588,15 @@ subroutine history_type_store_data3D(hist, id, work, Time, idx, intpl_method, fl type(time_type), intent(in) :: Time character(*), intent(in) :: intpl_method character(*), intent(in) :: fldname -! + ! real(kind=kind_phys), allocatable, dimension(:,:) :: sinlon, coslon, sinlat, coslat - integer k,j,i,kb,nv,i1,j1 + integer k,j,i,nv,i1,j1 logical used -! + ! if( id > 0 ) then if( hist%use_wrtgridcomp_output ) then if( trim(intpl_method) == 'bilinear') then -!$omp parallel do default(shared) private(i,j,k) + !$omp parallel do default(shared) private(i,j,k) do k= 1,hist%levo do j= hist%jsco,hist%jeco do i= hist%isco,hist%ieco @@ -592,7 +605,7 @@ subroutine history_type_store_data3D(hist, id, work, Time, idx, intpl_method, fl enddo enddo else if(trim(intpl_method) == 'nearest_stod') then -!$omp parallel do default(shared) private(i,j,k) + !$omp parallel do default(shared) private(i,j,k) do k= 1,hist%levo do j= hist%jsco,hist%jeco do i= hist%isco,hist%ieco @@ -601,8 +614,8 @@ subroutine history_type_store_data3D(hist, id, work, Time, idx, intpl_method, fl enddo enddo else if(trim(intpl_method) == 'vector_bilinear') then -!first save the data -!$omp parallel do default(shared) private(i,j,k) + !first save the data + !$omp parallel do default(shared) private(i,j,k) do k= 1,hist%levo do j= hist%jsco,hist%jeco do i= hist%isco,hist%ieco @@ -612,7 +625,7 @@ subroutine history_type_store_data3D(hist, id, work, Time, idx, intpl_method, fl enddo if( fldname(1:1) == 'u' .or. fldname(1:1) == 'U') then if(.not.associated(hist%uwork3d)) allocate(hist%uwork3d(hist%isco:hist%ieco,hist%jsco:hist%jeco,hist%levo)) -!$omp parallel do default(shared) private(i,j,k) + !$omp parallel do default(shared) private(i,j,k) do k= 1, hist%levo do j= hist%jsco,hist%jeco do i= hist%isco,hist%ieco @@ -624,11 +637,11 @@ subroutine history_type_store_data3D(hist, id, work, Time, idx, intpl_method, fl hist%uwork_set = .true. endif if( fldname(1:1) == 'v' .or. fldname(1:1) == 'V') then -!set up wind vector + !set up wind vector if( hist%uwork_set .and. trim(hist%uwindname(2:)) == trim(fldname(2:))) then allocate (sinlon(hist%isco:hist%ieco,hist%jsco:hist%jeco), coslon(hist%isco:hist%ieco,hist%jsco:hist%jeco), & - sinlat(hist%isco:hist%ieco,hist%jsco:hist%jeco), coslat(hist%isco:hist%ieco,hist%jsco:hist%jeco)) -!$omp parallel do default(shared) private(i,j) + sinlat(hist%isco:hist%ieco,hist%jsco:hist%jeco), coslat(hist%isco:hist%ieco,hist%jsco:hist%jeco)) + !$omp parallel do default(shared) private(i,j) do j= hist%jsco,hist%jeco do i= hist%isco,hist%ieco sinlon(i,j) = sin(hist%lon(i,j)) @@ -637,7 +650,7 @@ subroutine history_type_store_data3D(hist, id, work, Time, idx, intpl_method, fl coslat(i,j) = cos(hist%lat(i,j)) enddo enddo -!$omp parallel do default(shared) private(i,j,k,nv,i1,j1) + !$omp parallel do default(shared) private(i,j,k,nv,i1,j1) do k= 1, hist%levo nv = hist%nstt_vctbl(idx)+k-1 do j= hist%jsco,hist%jeco @@ -645,9 +658,9 @@ subroutine history_type_store_data3D(hist, id, work, Time, idx, intpl_method, fl do i= hist%isco,hist%ieco i1 = i-hist%isco+1 hist%buffer_phys_windvect(1,i,j,nv) = hist%uwork3d(i,j,k)*coslon(i,j) & - - work(i1,j1,k)*sinlat(i,j)*sinlon(i,j) + - work(i1,j1,k)*sinlat(i,j)*sinlon(i,j) hist%buffer_phys_windvect(2,i,j,nv) = hist%uwork3d(i,j,k)*sinlon(i,j) & - + work(i1,j1,k)*sinlat(i,j)*coslon(i,j) + + work(i1,j1,k)*sinlat(i,j)*coslon(i,j) hist%buffer_phys_windvect(3,i,j,nv) = work(i1,j1,k)*coslat(i,j) enddo enddo @@ -664,527 +677,501 @@ subroutine history_type_store_data3D(hist, id, work, Time, idx, intpl_method, fl used = send_data(id, work, Time) endif endif -! + ! end subroutine history_type_store_data3D -! -!------------------------------------------------------------------------- -! + ! + !------------------------------------------------------------------------- + ! #ifdef use_WRTCOMP - subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nbdlphys, rc) -! -!------------------------------------------------------------- -!*** set esmf bundle for phys output fields -!------------------------------------------------------------ -! - use esmf - use diag_data_mod, ONLY: diag_atttype -! - implicit none -! - type(GFS_externaldiag_type),intent(in) :: Diag(:) - integer, intent(in) :: axes(:) - type(ESMF_FieldBundle),intent(inout) :: phys_bundle(:) - type(ESMF_Grid),intent(inout) :: fcst_grid - logical,intent(in) :: quilting - integer, intent(in) :: nbdlphys - integer,intent(out) :: rc - - call shared_history_data%bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nbdlphys, rc) - end subroutine fv_phys_bundle_setup - - subroutine history_type_bundle_setup(hist, Diag, axes, phys_bundle, fcst_grid, quilting, nbdlphys, rc) -! set esmf bundle for phys output fields - use esmf - use diag_data_mod, ONLY: diag_atttype -! - implicit none -! - class(history_type) :: hist - type(GFS_externaldiag_type),intent(in) :: Diag(:) - integer, intent(in) :: axes(:) - type(ESMF_FieldBundle),intent(inout) :: phys_bundle(:) - type(ESMF_Grid),intent(inout) :: fcst_grid - logical,intent(in) :: quilting - integer, intent(in) :: nbdlphys - integer,intent(out) :: rc - -! -!*** local variables - integer i, j, k, n, idx, ibdl, nbdl - integer id, axis_length, direction, edges, axis_typ - integer num_attributes, num_field_dyn - integer currdate(6) - character(2) axis_id - character(255) :: units, long_name, cart_name, axis_direct, edgesS - character(128) :: output_name, physbdl_name, outputfile1 - logical :: lput2physbdl, loutputfile, l2dvector - type(domain1d) :: Domain - type(domainUG) :: DomainU - type(ESMF_Field) :: field - real,dimension(:),allocatable :: axis_data - character(128),dimension(:), allocatable :: bdl_intplmethod, outputfile - type(diag_atttype),dimension(:),allocatable :: attributes - real(4),dimension(:,:),pointer :: dataPtr2d -! - logical isPresent - integer udimCount - character(80),dimension(:),allocatable :: udimList - character(20),dimension(:), allocatable :: axis_name_vert -! -!------------------------------------------------------------ -!--- use wrte grid component for output - hist%use_wrtgridcomp_output = quilting -! if(mpp_pe()==mpp_root_pe())print *,'in fv_phys bundle,use_wrtgridcomp_output=',hist%use_wrtgridcomp_output, & -! print *,'in fv_phys bundle,use_wrtgridcomp_output=',hist%use_wrtgridcomp_output, & -! 'hist%isco=',hist%isco,hist%ieco,'hist%jsco=',hist%jsco,hist%jeco,'hist%tot_diag_idx=',hist%tot_diag_idx -! -!------------------------------------------------------------ -!*** add attributes to the bundle such as subdomain limtis, -!*** axes, output time, etc -!------------------------------------------------------------ -! - allocate(bdl_intplmethod(nbdlphys), outputfile(nbdlphys)) - if(mpp_pe()==mpp_root_pe()) print *,'in fv_phys bundle,nbdl=',nbdlphys - do ibdl = 1, nbdlphys - loutputfile = .false. - call ESMF_FieldBundleGet(phys_bundle(ibdl), name=physbdl_name,rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - idx = index(physbdl_name,'_bilinear') - if(idx > 0) then - outputfile(ibdl) = physbdl_name(1:idx-1) - bdl_intplmethod(ibdl) = 'bilinear' - loutputfile = .true. - endif - idx = index(physbdl_name,'_nearest_stod') - if(idx > 0) then - outputfile(ibdl) = physbdl_name(1:idx-1) - bdl_intplmethod(ibdl) = 'nearest_stod' - loutputfile = .true. - endif - if( .not. loutputfile) then - outputfile(ibdl) = 'phy' - bdl_intplmethod(ibdl) = 'nearest_stod' - endif -! print *,'in fv_phys bundle,i=',ibdl,'outputfile=',trim(outputfile(ibdl)), & -! 'bdl_intplmethod=',trim(bdl_intplmethod(ibdl)) - - call ESMF_AttributeAdd(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & - attrList=(/"fhzero ", "ncld ", "nsoil ",& - "imp_physics", "dtp ", "landsfcmdl "/), rc=rc) - - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & - name="fhzero", value=hist%fhzero, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & - name="ncld", value=hist%ncld, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & - name="nsoil", value=hist%nsoil, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & - name="imp_physics", value=hist%imp_physics, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & - name="dtp", value=hist%dtp, rc=rc) -! print *,'in fcst gfdl diag, hist%dtp=',hist%dtp,' ibdl=',ibdl - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & - name="landsfcmdl", value=hist%landsfcmdl, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - -!end ibdl - enddo -! -!*** get axis names - allocate(hist%axis_name(hist%num_axes_phys)) - do id = 1,hist%num_axes_phys - call get_diag_axis_name( axes(id), hist%axis_name(id)) - enddo - isPresent = .false. - if( hist%num_axes_phys>2 ) then - allocate(axis_name_vert(hist%num_axes_phys-2)) - do id=3,hist%num_axes_phys - axis_name_vert(id-2) = hist%axis_name(id) - enddo -! - call ESMF_AttributeGet(fcst_grid, convention="NetCDF", purpose="FV3", & - name="vertical_dim_labels", isPresent=isPresent, & - itemCount=udimCount, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - if (isPresent .and. (udimCount>hist%num_axes_phys-2) ) then - allocate(udimList(udimCount)) - call ESMF_AttributeGet(fcst_grid, convention="NetCDF", purpose="FV3", & - name="vertical_dim_labels", valueList=udimList, rc=rc) -! if(mpp_pe()==mpp_root_pe()) print *,'in fv3atmio, vertical -! list=',udimList(1:udimCount),'rc=',rc - - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - else - - if(mpp_pe()==mpp_root_pe()) print *,'in fv_dyn bundle,axis_name_vert=',axis_name_vert - call ESMF_AttributeAdd(fcst_grid, convention="NetCDF", purpose="FV3", & - attrList=(/"vertical_dim_labels"/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & - name="vertical_dim_labels", valueList=axis_name_vert, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - endif - deallocate(axis_name_vert) - endif - -!*** add attributes - if(associated(hist%all_axes)) then - deallocate(hist%all_axes) - nullify(hist%all_axes) - endif - allocate(hist%all_axes(hist%num_axes_phys)) - hist%all_axes(1:hist%num_axes_phys) = axes(1:hist%num_axes_phys) - if (.not. isPresent .or. (udimCount2 ) then -! if(mpp_pe()==mpp_root_pe()) print *,' in dyn add grid, axis_name=', & -! trim(hist%axis_name(id)),'axis_data=',axis_data - if(trim(edgesS)/='') then - call ESMF_AttributeAdd(fcst_grid, convention="NetCDF", purpose="FV3", & - attrList=(/trim(hist%axis_name(id)),trim(hist%axis_name(id))//":long_name", & - trim(hist%axis_name(id))//":units", trim(hist%axis_name(id))//":cartesian_axis", & - trim(hist%axis_name(id))//":positive", trim(hist%axis_name(id))//":edges"/), rc=rc) - else - call ESMF_AttributeAdd(fcst_grid, convention="NetCDF", purpose="FV3", & - attrList=(/trim(hist%axis_name(id)),trim(hist%axis_name(id))//":long_name", & - trim(hist%axis_name(id))//":units", trim(hist%axis_name(id))//":cartesian_axis", & - trim(hist%axis_name(id))//":positive"/), rc=rc) - endif - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & - name=trim(hist%axis_name(id)), valueList=axis_data, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & - name=trim(hist%axis_name(id))//":long_name", value=trim(long_name), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & - name=trim(hist%axis_name(id))//":units", value=trim(units), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & - name=trim(hist%axis_name(id))//":cartesian_axis", value=trim(cart_name), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - if(direction > 0) then - axis_direct = "up" - else - axis_direct = "down" - endif - call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & - name=trim(hist%axis_name(id))//":positive", value=trim(axis_direct), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - - if(trim(edgesS)/='') then - call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & - name=trim(hist%axis_name(id))//":edges", value=trim(edgesS), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - endif + subroutine history_type_bundle_setup(hist, Diag, axes, phys_bundle, fcst_grid, quilting, nbdlphys, rc) + ! set esmf bundle for phys output fields + use esmf + use diag_data_mod, ONLY: diag_atttype + ! + implicit none + ! + class(history_type) :: hist + type(GFS_externaldiag_type),intent(in) :: Diag(:) + integer, intent(in) :: axes(:) + type(ESMF_FieldBundle),intent(inout) :: phys_bundle(:) + type(ESMF_Grid),intent(inout) :: fcst_grid + logical,intent(in) :: quilting + integer, intent(in) :: nbdlphys + integer,intent(out) :: rc + + ! + !*** local variables + integer i, idx, ibdl + integer id, axis_length, direction, edges + integer num_attributes + character(255) :: units, long_name, cart_name, axis_direct, edgesS + character(128) :: output_name, physbdl_name, outputfile1 + logical :: lput2physbdl, loutputfile, l2dvector + type(domain1d) :: Domain + type(domainUG) :: DomainU + real,dimension(:),allocatable :: axis_data + character(128),dimension(:), allocatable :: bdl_intplmethod, outputfile + type(diag_atttype),dimension(:),allocatable :: attributes + ! + logical isPresent + integer udimCount + character(80),dimension(:),allocatable :: udimList + character(20),dimension(:), allocatable :: axis_name_vert + ! + !------------------------------------------------------------ + !--- use wrte grid component for output + hist%use_wrtgridcomp_output = quilting + ! if(mpp_pe()==mpp_root_pe())print *,'in fv_phys bundle,use_wrtgridcomp_output=',hist%use_wrtgridcomp_output, & + ! print *,'in fv_phys bundle,use_wrtgridcomp_output=',hist%use_wrtgridcomp_output, & + ! 'hist%isco=',hist%isco,hist%ieco,'hist%jsco=',hist%jsco,hist%jeco,'hist%tot_diag_idx=',hist%tot_diag_idx + ! + !------------------------------------------------------------ + !*** add attributes to the bundle such as subdomain limtis, + !*** axes, output time, etc + !------------------------------------------------------------ + ! + allocate(bdl_intplmethod(nbdlphys), outputfile(nbdlphys)) + if(mpp_pe()==mpp_root_pe()) print *,'in fv_phys bundle,nbdl=',nbdlphys + do ibdl = 1, nbdlphys + loutputfile = .false. + call ESMF_FieldBundleGet(phys_bundle(ibdl), name=physbdl_name,rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + idx = index(physbdl_name,'_bilinear') + if(idx > 0) then + outputfile(ibdl) = physbdl_name(1:idx-1) + bdl_intplmethod(ibdl) = 'bilinear' + loutputfile = .true. + endif + idx = index(physbdl_name,'_nearest_stod') + if(idx > 0) then + outputfile(ibdl) = physbdl_name(1:idx-1) + bdl_intplmethod(ibdl) = 'nearest_stod' + loutputfile = .true. + endif + if( .not. loutputfile) then + outputfile(ibdl) = 'phy' + bdl_intplmethod(ibdl) = 'nearest_stod' + endif + ! print *,'in fv_phys bundle,i=',ibdl,'outputfile=',trim(outputfile(ibdl)), & + ! 'bdl_intplmethod=',trim(bdl_intplmethod(ibdl)) + + call ESMF_AttributeAdd(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & + attrList=(/"fhzero ", "ncld ", "nsoil ",& + "imp_physics", "dtp ", "landsfcmdl "/), rc=rc) + + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & + name="fhzero", value=hist%fhzero, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & + name="ncld", value=hist%ncld, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & + name="nsoil", value=hist%nsoil, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & + name="imp_physics", value=hist%imp_physics, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & + name="dtp", value=hist%dtp, rc=rc) + ! print *,'in fcst gfdl diag, hist%dtp=',hist%dtp,' ibdl=',ibdl + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + call ESMF_AttributeSet(phys_bundle(ibdl), convention="NetCDF", purpose="FV3", & + name="landsfcmdl", value=hist%landsfcmdl, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + !end ibdl + enddo + ! + !*** get axis names + allocate(hist%axis_name(hist%num_axes_phys)) + do id = 1,hist%num_axes_phys + call get_diag_axis_name( axes(id), hist%axis_name(id)) + enddo + isPresent = .false. + if( hist%num_axes_phys>2 ) then + allocate(axis_name_vert(hist%num_axes_phys-2)) + do id=3,hist%num_axes_phys + axis_name_vert(id-2) = hist%axis_name(id) + enddo + ! + call ESMF_AttributeGet(fcst_grid, convention="NetCDF", purpose="FV3", & + name="vertical_dim_labels", isPresent=isPresent, & + itemCount=udimCount, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + if (isPresent .and. (udimCount>hist%num_axes_phys-2) ) then + allocate(udimList(udimCount)) + call ESMF_AttributeGet(fcst_grid, convention="NetCDF", purpose="FV3", & + name="vertical_dim_labels", valueList=udimList, rc=rc) + ! if(mpp_pe()==mpp_root_pe()) print *,'in fv3atmio, vertical + ! list=',udimList(1:udimCount),'rc=',rc + + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + else + + if(mpp_pe()==mpp_root_pe()) print *,'in fv_dyn bundle,axis_name_vert=',axis_name_vert + call ESMF_AttributeAdd(fcst_grid, convention="NetCDF", purpose="FV3", & + attrList=(/"vertical_dim_labels"/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & + name="vertical_dim_labels", valueList=axis_name_vert, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + endif + deallocate(axis_name_vert) + endif + + !*** add attributes + if(associated(hist%all_axes)) then + deallocate(hist%all_axes) + nullify(hist%all_axes) + endif + allocate(hist%all_axes(hist%num_axes_phys)) + hist%all_axes(1:hist%num_axes_phys) = axes(1:hist%num_axes_phys) + if (.not. isPresent .or. (udimCount2 ) then + ! if(mpp_pe()==mpp_root_pe()) print *,' in dyn add grid, axis_name=', & + ! trim(hist%axis_name(id)),'axis_data=',axis_data + if(trim(edgesS)/='') then + call ESMF_AttributeAdd(fcst_grid, convention="NetCDF", purpose="FV3", & + attrList=(/trim(hist%axis_name(id)),trim(hist%axis_name(id))//":long_name", & + trim(hist%axis_name(id))//":units", trim(hist%axis_name(id))//":cartesian_axis", & + trim(hist%axis_name(id))//":positive", trim(hist%axis_name(id))//":edges"/), rc=rc) + else + call ESMF_AttributeAdd(fcst_grid, convention="NetCDF", purpose="FV3", & + attrList=(/trim(hist%axis_name(id)),trim(hist%axis_name(id))//":long_name", & + trim(hist%axis_name(id))//":units", trim(hist%axis_name(id))//":cartesian_axis", & + trim(hist%axis_name(id))//":positive"/), rc=rc) + endif + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & + name=trim(hist%axis_name(id)), valueList=axis_data, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & + name=trim(hist%axis_name(id))//":long_name", value=trim(long_name), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & + name=trim(hist%axis_name(id))//":units", value=trim(units), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & + name=trim(hist%axis_name(id))//":cartesian_axis", value=trim(cart_name), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + if(direction > 0) then + axis_direct = "up" + else + axis_direct = "down" + endif + call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & + name=trim(hist%axis_name(id))//":positive", value=trim(axis_direct), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + if(trim(edgesS)/='') then + call ESMF_AttributeSet(fcst_grid, convention="NetCDF", purpose="FV3", & + name=trim(hist%axis_name(id))//":edges", value=trim(edgesS), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + endif endif -! + ! deallocate(axis_data) enddo endif -! print *,'in setup fieldbundle_phys, hist%num_axes_phys=',hist%num_axes_phys,'hist%tot_diag_idx=',hist%tot_diag_idx, & -! 'nbdlphys=',nbdlphys -! -!----------------------------------------------------------------------------------------- -!*** add esmf fields -! - do idx= 1,hist%tot_diag_idx - - lput2physbdl = .false. - do ibdl = 1, nbdlphys - - if( index(trim(Diag(idx)%intpl_method),trim(bdl_intplmethod(ibdl))) > 0) then - lput2physbdl = .true. - if( Diag(idx)%id > 0 ) then - call hist%find_output_name(trim(Diag(idx)%mod_name),trim(Diag(idx)%name),output_name) - -!add origin field - call hist%add_field_to_phybundle(trim(output_name),trim(Diag(idx)%desc),trim(Diag(idx)%unit), "time: point", & - axes(1:Diag(idx)%axes), fcst_grid, hist%nstt(idx), phys_bundle(ibdl), outputfile(ibdl), & - bdl_intplmethod(ibdl), rcd=rc) -! if( mpp_pe() == mpp_root_pe()) print *,'phys, add field,',trim(Diag(idx)%name),'idx=',idx,'ibdl=',ibdl -! - if( index(trim(Diag(idx)%intpl_method), "vector") > 0) then - l2dvector = .true. - if (hist%nstt_vctbl(idx) > 0) then - output_name = 'wind'//trim(output_name)//'vector' - outputfile1 = 'none' - call hist%add_field_to_phybundle(trim(output_name),trim(Diag(idx)%desc),trim(Diag(idx)%unit), "time: point", & - axes(1:Diag(idx)%axes), fcst_grid, hist%nstt_vctbl(idx),phys_bundle(ibdl), outputfile1, & - bdl_intplmethod(ibdl),l2dvector=l2dvector, rcd=rc) -! if( mpp_pe() == mpp_root_pe()) print *,'in phys, add vector field,',trim(Diag(idx)%name),' idx=',idx,' ibdl=',ibdl - endif - endif - - endif - endif - enddo - if( .not. lput2physbdl ) then - if( mpp_pe() == mpp_root_pe()) print *,'WARNING: not matching interpolation method, field ',trim(Diag(idx)%name), & - ' is not added to phys bundle ' - endif - - enddo - deallocate(hist%axis_name) - deallocate(hist%all_axes) - nullify(hist%axis_name) - nullify(hist%all_axes) - - end subroutine history_type_bundle_setup -! -!----------------------------------------------------------------------------------------- - subroutine history_type_add_field_to_phybundle(hist,var_name,long_name,units,cell_methods, axes,phys_grid, & - kstt,phys_bundle,output_file,intpl_method,range,l2dvector,rcd) -! - use esmf -! - implicit none - class(history_type) :: hist - character(*), intent(in) :: var_name, long_name, units, cell_methods - character(*), intent(in) :: output_file, intpl_method - integer, intent(in) :: axes(:) - type(esmf_grid), intent(in) :: phys_grid - integer, intent(in) :: kstt - type(esmf_fieldbundle),intent(inout) :: phys_bundle - real, intent(in), optional :: range(2) - logical, intent(in), optional :: l2dvector - integer, intent(out), optional :: rcd -! -!*** local variable - type(ESMF_Field) :: field - type(ESMF_DataCopy_Flag) :: copyflag=ESMF_DATACOPY_REFERENCE - integer rc, i, j, idx - real(4),dimension(:,:),pointer :: temp_r2d - real(4),dimension(:,:,:),pointer :: temp_r3d - logical :: l2dvector_local -! - ! fix for non-standard compilers (e.g. PGI) - l2dvector_local = .false. - if (present(l2dvector)) then - if (l2dvector) then - l2dvector_local = .true. - end if - end if -! -!*** create esmf field - if (l2dvector_local .and. size(axes)==2) then - temp_r3d => hist%buffer_phys_windvect(1:3,hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt) -! if( mpp_root_pe() == 0) print *,'phys, create wind vector esmf field' - call ESMF_LogWrite('bf create winde vector esmf field '//trim(var_name), ESMF_LOGMSG_INFO, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - -!datacopyflag=ESMF_DATACOPY_VALUE, & - field = ESMF_FieldCreate(phys_grid, temp_r3d, datacopyflag=ESMF_DATACOPY_REFERENCE, & - gridToFieldMap=(/2,3/), ungriddedLBound=(/1/), ungriddedUBound=(/3/), & - name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) - - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - call ESMF_LogWrite('af winde vector esmf field create '//trim(var_name), ESMF_LOGMSG_INFO, rc=rc) - - call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & - attrList=(/"output_file"/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & - name='output_file',value=trim(output_file),rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_LogWrite('before winde vector esmf field add output_file', ESMF_LOGMSG_INFO, rc=rc) - -! if( mpp_root_pe() == 0)print *,'phys, aftercreate wind vector esmf field' - call ESMF_FieldBundleAdd(phys_bundle,(/field/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - if( present(rcd)) rcd=rc - call ESMF_LogWrite('aft winde vector esmf field add to fieldbundle'//trim(var_name), ESMF_LOGMSG_INFO, rc=rc) - return - else if( trim(intpl_method) == 'nearest_stod' ) then - if(size(axes) == 2) then - temp_r2d => hist%buffer_phys_nb(hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt) - field = ESMF_FieldCreate(phys_grid, temp_r2d, datacopyflag=copyflag, & - name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + ! print *,'in setup fieldbundle_phys, hist%num_axes_phys=',hist%num_axes_phys,'hist%tot_diag_idx=',hist%tot_diag_idx, & + ! 'nbdlphys=',nbdlphys + ! + !----------------------------------------------------------------------------------------- + !*** add esmf fields + ! + do idx= 1,hist%tot_diag_idx + + lput2physbdl = .false. + do ibdl = 1, nbdlphys + + if( index(trim(Diag(idx)%intpl_method),trim(bdl_intplmethod(ibdl))) > 0) then + lput2physbdl = .true. + if( Diag(idx)%id > 0 ) then + call hist%find_output_name(trim(Diag(idx)%mod_name),trim(Diag(idx)%name),output_name) + + !add origin field + call hist%add_field_to_phybundle(trim(output_name),trim(Diag(idx)%desc),trim(Diag(idx)%unit), "time: point", & + axes(1:Diag(idx)%axes), fcst_grid, hist%nstt(idx), phys_bundle(ibdl), outputfile(ibdl), & + bdl_intplmethod(ibdl), rcd=rc) + ! if( mpp_pe() == mpp_root_pe()) print *,'phys, add field,',trim(Diag(idx)%name),'idx=',idx,'ibdl=',ibdl + ! + if( index(trim(Diag(idx)%intpl_method), "vector") > 0) then + l2dvector = .true. + if (hist%nstt_vctbl(idx) > 0) then + output_name = 'wind'//trim(output_name)//'vector' + outputfile1 = 'none' + call hist%add_field_to_phybundle(trim(output_name),trim(Diag(idx)%desc),trim(Diag(idx)%unit), "time: point", & + axes(1:Diag(idx)%axes), fcst_grid, hist%nstt_vctbl(idx),phys_bundle(ibdl), outputfile1, & + bdl_intplmethod(ibdl),l2dvector=l2dvector, rcd=rc) + ! if( mpp_pe() == mpp_root_pe()) print *,'in phys, add vector field,',trim(Diag(idx)%name),' idx=',idx,' ibdl=',ibdl + endif + endif + + endif + endif + enddo + if( .not. lput2physbdl ) then + if( mpp_pe() == mpp_root_pe()) print *,'WARNING: not matching interpolation method, field ',trim(Diag(idx)%name), & + ' is not added to phys bundle ' + endif + + enddo + deallocate(hist%axis_name) + deallocate(hist%all_axes) + nullify(hist%axis_name) + nullify(hist%all_axes) + + end subroutine history_type_bundle_setup + ! + !----------------------------------------------------------------------------------------- + subroutine history_type_add_field_to_phybundle(hist,var_name,long_name,units,cell_methods, axes,phys_grid, & + kstt,phys_bundle,output_file,intpl_method,range,l2dvector,rcd) + ! + use esmf + ! + implicit none + class(history_type) :: hist + character(*), intent(in) :: var_name, long_name, units, cell_methods + character(*), intent(in) :: output_file, intpl_method + integer, intent(in) :: axes(:) + type(esmf_grid), intent(in) :: phys_grid + integer, intent(in) :: kstt + type(esmf_fieldbundle),intent(inout) :: phys_bundle + real, intent(in), optional :: range(2) + logical, intent(in), optional :: l2dvector + integer, intent(out), optional :: rcd + ! + !*** local variable + type(ESMF_Field) :: field + type(ESMF_DataCopy_Flag) :: copyflag=ESMF_DATACOPY_REFERENCE + integer rc, i, j, idx + real(4),dimension(:,:),pointer :: temp_r2d + real(4),dimension(:,:,:),pointer :: temp_r3d + logical :: l2dvector_local + ! + ! fix for non-standard compilers (e.g. PGI) + l2dvector_local = .false. + if (present(l2dvector)) then + if (l2dvector) then + l2dvector_local = .true. + end if + end if + ! + !*** create esmf field + if (l2dvector_local .and. size(axes)==2) then + temp_r3d => hist%buffer_phys_windvect(1:3,hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt) + ! if( mpp_root_pe() == 0) print *,'phys, create wind vector esmf field' + call ESMF_LogWrite('bf create winde vector esmf field '//trim(var_name), ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + !datacopyflag=ESMF_DATACOPY_VALUE, & + field = ESMF_FieldCreate(phys_grid, temp_r3d, datacopyflag=ESMF_DATACOPY_REFERENCE, & + gridToFieldMap=(/2,3/), ungriddedLBound=(/1/), ungriddedUBound=(/3/), & + name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) + + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + call ESMF_LogWrite('af winde vector esmf field create '//trim(var_name), ESMF_LOGMSG_INFO, rc=rc) + + call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & + attrList=(/"output_file"/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & + name='output_file',value=trim(output_file),rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_LogWrite('before winde vector esmf field add output_file', ESMF_LOGMSG_INFO, rc=rc) + + ! if( mpp_root_pe() == 0)print *,'phys, aftercreate wind vector esmf field' + call ESMF_FieldBundleAdd(phys_bundle,(/field/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + if( present(rcd)) rcd=rc + call ESMF_LogWrite('aft winde vector esmf field add to fieldbundle'//trim(var_name), ESMF_LOGMSG_INFO, rc=rc) + return + else if( trim(intpl_method) == 'nearest_stod' ) then + if(size(axes) == 2) then + temp_r2d => hist%buffer_phys_nb(hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt) + field = ESMF_FieldCreate(phys_grid, temp_r2d, datacopyflag=copyflag, & + name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + else if(size(axes) == 3) then + temp_r3d => hist%buffer_phys_nb(hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt:kstt+hist%levo-1) + field = ESMF_FieldCreate(phys_grid, temp_r3d, datacopyflag=copyflag, & + name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + if( mpp_pe() == mpp_root_pe()) print *,'add 3D field to after nearest_stod, fld=', trim(var_name) + endif + else if( trim(intpl_method) == 'bilinear' ) then + if(size(axes) == 2) then + temp_r2d => hist%buffer_phys_bl(hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt) + field = ESMF_FieldCreate(phys_grid, temp_r2d, datacopyflag=copyflag, & + name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + else if(size(axes) == 3) then + temp_r3d => hist%buffer_phys_bl(hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt:kstt+hist%levo-1) + field = ESMF_FieldCreate(phys_grid, temp_r3d, datacopyflag=copyflag, & + name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + if( mpp_pe() == mpp_root_pe()) print *,'add field to after bilinear, fld=', trim(var_name) + endif + endif + ! + !*** add field attributes + call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & + attrList=(/"long_name"/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - else if(size(axes) == 3) then - temp_r3d => hist%buffer_phys_nb(hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt:kstt+hist%levo-1) - field = ESMF_FieldCreate(phys_grid, temp_r3d, datacopyflag=copyflag, & - name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & + name='long_name',value=trim(long_name),rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - if( mpp_pe() == mpp_root_pe()) print *,'add 3D field to after nearest_stod, fld=', trim(var_name) - endif - else if( trim(intpl_method) == 'bilinear' ) then - if(size(axes) == 2) then - temp_r2d => hist%buffer_phys_bl(hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt) - field = ESMF_FieldCreate(phys_grid, temp_r2d, datacopyflag=copyflag, & - name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & + attrList=(/"units"/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - else if(size(axes) == 3) then - temp_r3d => hist%buffer_phys_bl(hist%isco:hist%ieco,hist%jsco:hist%jeco,kstt:kstt+hist%levo-1) - field = ESMF_FieldCreate(phys_grid, temp_r3d, datacopyflag=copyflag, & - name=var_name, indexFlag=ESMF_INDEX_DELOCAL, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & + name='units',value=trim(units),rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - if( mpp_pe() == mpp_root_pe()) print *,'add field to after bilinear, fld=', trim(var_name) - endif - endif -! -!*** add field attributes - call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & - attrList=(/"long_name"/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & - name='long_name',value=trim(long_name),rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & - attrList=(/"units"/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & - name='units',value=trim(units),rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & - attrList=(/"missing_value"/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & - name='missing_value',value=real(missing_value,kind=4),rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & - attrList=(/"_FillValue"/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & - name='_FillValue',value=real(missing_value,kind=4),rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & - attrList=(/"cell_methods"/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & - name='cell_methods',value=trim(cell_methods),rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) -! - call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & - attrList=(/"output_file"/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & - name='output_file',value=trim(output_file),rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - -! -!*** add vertical coord attribute: - if( size(axes) > 2) then - do i=3,size(axes) - idx=0 - do j=1,size(hist%all_axes) - if (axes(i)==hist%all_axes(j)) then - idx=j - exit - endif - enddo - if (idx>0) then - call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & - attrList=(/"ESMF:ungridded_dim_labels"/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & - name="ESMF:ungridded_dim_labels", valueList=(/trim(hist%axis_name(idx))/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - endif - enddo - endif - -!*** add field into bundle - call ESMF_FieldBundleAdd(phys_bundle,(/field/), rc=rc) - if( present(rcd)) rcd=rc -! - call ESMF_LogWrite('phys field add to fieldbundle '//trim(var_name), ESMF_LOGMSG_INFO, rc=rc) - - end subroutine history_type_add_field_to_phybundle -! -! - subroutine history_type_find_output_name(hist,module_name,field_name,output_name) - implicit none - class(history_type) :: hist - character(*), intent(in) :: module_name - character(*), intent(in) :: field_name - character(*), intent(out) :: output_name -! - integer i,in_num, out_num - integer tile_count -! - tile_count = 1 - in_num = find_input_field(module_name, field_name, tile_count) -! - output_name = '' - do i=1, max_output_fields - if(output_fields(i)%input_field == in_num) then - output_name = output_fields(i)%output_name - exit - endif - enddo - if(output_name == '') then - print *,'Error, cant find out put name' - endif - - end subroutine history_type_find_output_name + + call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & + attrList=(/"missing_value"/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & + name='missing_value',value=real(missing_value,kind=4),rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & + attrList=(/"_FillValue"/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & + name='_FillValue',value=real(missing_value,kind=4),rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & + attrList=(/"cell_methods"/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & + name='cell_methods',value=trim(cell_methods),rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + ! + call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & + attrList=(/"output_file"/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & + name='output_file',value=trim(output_file),rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + ! + !*** add vertical coord attribute: + if( size(axes) > 2) then + do i=3,size(axes) + idx=0 + do j=1,size(hist%all_axes) + if (axes(i)==hist%all_axes(j)) then + idx=j + exit + endif + enddo + if (idx>0) then + call ESMF_AttributeAdd(field, convention="NetCDF", purpose="FV3", & + attrList=(/"ESMF:ungridded_dim_labels"/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & + name="ESMF:ungridded_dim_labels", valueList=(/trim(hist%axis_name(idx))/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + endif + enddo + endif + + !*** add field into bundle + call ESMF_FieldBundleAdd(phys_bundle,(/field/), rc=rc) + if( present(rcd)) rcd=rc + ! + call ESMF_LogWrite('phys field add to fieldbundle '//trim(var_name), ESMF_LOGMSG_INFO, rc=rc) + + end subroutine history_type_add_field_to_phybundle + ! + ! + subroutine history_type_find_output_name(hist,module_name,field_name,output_name) + implicit none + class(history_type) :: hist + character(*), intent(in) :: module_name + character(*), intent(in) :: field_name + character(*), intent(out) :: output_name + ! + integer i,in_num + integer tile_count + ! + tile_count = 1 + in_num = find_input_field(module_name, field_name, tile_count) + ! + output_name = '' + do i=1, max_output_fields + if(output_fields(i)%input_field == in_num) then + output_name = output_fields(i)%output_name + exit + endif + enddo + if(output_name == '') then + print *,'Error, cant find out put name' + endif + + end subroutine history_type_find_output_name #endif -!------------------------------------------------------------------------- + !------------------------------------------------------------------------- end module fv3atm_history_io_mod diff --git a/io/fv3atm_restart_io.F90 b/io/fv3atm_restart_io.F90 index 6cffb7c46..b04bf7fff 100644 --- a/io/fv3atm_restart_io.F90 +++ b/io/fv3atm_restart_io.F90 @@ -1,6 +1,5 @@ module fv3atm_restart_io_mod - use esmf use block_control_mod, only: block_control_type use mpp_mod, only: mpp_error, mpp_pe, mpp_root_pe, & mpp_chksum, NOTE, FATAL @@ -27,7 +26,6 @@ module fv3atm_restart_io_mod public fv3atm_checksum public fv3atm_restart_read public fv3atm_restart_write - public phy_data_type public fv3atm_restart_register public fv_phy_restart_output public fv_phy_restart_bundle_setup @@ -40,6 +38,10 @@ module fv3atm_restart_io_mod character(len=32),dimension(:),pointer :: var2_names => null() character(len=32),dimension(:),pointer :: var3_names => null() integer :: nvar2d = 0, nvar3d = 0, npz = 0 + contains + procedure :: alloc => phy_data_alloc + procedure :: transfer_data => phy_data_transfer_data + final phy_data_final end type phy_data_type !--- GFDL filenames @@ -61,6 +63,47 @@ module fv3atm_restart_io_mod contains + !-------------------- + ! fv3atm_restart_read + !-------------------- + subroutine fv3atm_restart_read (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) + implicit none + type(GFS_data_type), intent(inout) :: GFS_Data(:) + type(GFS_restart_type), intent(inout) :: GFS_Restart + type(block_control_type), intent(in) :: Atm_block + type(GFS_control_type), intent(inout) :: Model + type(domain2d), intent(in) :: fv_domain + logical, intent(in) :: warm_start + logical, intent(in) :: ignore_rst_cksum + + !--- read in surface data from chgres + call sfc_prop_restart_read (GFS_Data%Sfcprop, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) + + !--- read in physics restart data + call phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_rst_cksum) + + end subroutine fv3atm_restart_read + + !--------------------- + ! fv3atm_restart_write + !--------------------- + subroutine fv3atm_restart_write (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, timestamp) + implicit none + type(GFS_data_type), intent(inout) :: GFS_Data(:) + type(GFS_restart_type), intent(inout) :: GFS_Restart + type(block_control_type), intent(in) :: Atm_block + 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 + 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) + + end subroutine fv3atm_restart_write + !---------------- ! fv3atm_checksum !---------------- @@ -71,8 +114,8 @@ subroutine fv3atm_checksum (Model, GFS_Data, Atm_block) type(GFS_data_type), intent(in) :: GFS_Data(:) type (block_control_type), intent(in) :: Atm_block !--- local variables - integer :: outunit, j, i, ix, nb, isc, iec, jsc, jec, lev, ct, l, ntr, k - integer :: nsfcprop2d, idx_opt, nt + integer :: outunit, i, ix, nb, isc, iec, jsc, jec, lev, ntr, k + integer :: nsfcprop2d, nt real(kind=kind_phys), allocatable :: temp2d(:,:,:) real(kind=kind_phys), allocatable :: temp3d(:,:,:,:) real(kind=kind_phys), allocatable :: temp3dlevsp1(:,:,:,:) @@ -120,7 +163,7 @@ subroutine fv3atm_checksum (Model, GFS_Data, Atm_block) temp3d = zero temp3dlevsp1 = zero - !$omp parallel do default(shared) private(i, j, k, nb, ix, nt, ii1, jj1) + !$omp parallel do default(shared) private(i, k, nb, ix, nt, ii1, jj1) block_loop: do nb = 1, Atm_block%nblks allocate(ii1(Atm_block%blksz(nb))) allocate(jj1(Atm_block%blksz(nb))) @@ -390,12 +433,12 @@ subroutine fv3atm_checksum (Model, GFS_Data, Atm_block) call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Radtend%htrlw) call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Radtend%swhc) call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Radtend%lwhc) - do l = 1,Model%ntot3d - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Tbd%phy_f3d(:,:,l)) + do k = 1,Model%ntot3d + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Tbd%phy_f3d(:,:,k)) enddo - do l = 1,ntr - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%qgrs(:,:,l)) - call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Stateout%gq0(:,:,l)) + do k = 1,ntr + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Statein%qgrs(:,:,k)) + call copy_from_GFS_Data(ii1,jj1,isc,jsc,nt,temp3d,GFS_Data(nb)%Stateout%gq0(:,:,k)) enddo enddo block_loop @@ -420,55 +463,6 @@ subroutine fv3atm_checksum (Model, GFS_Data, Atm_block) deallocate(temp3dlevsp1) end subroutine fv3atm_checksum - !-------------------- - ! fv3atm_restart_read - !-------------------- - subroutine fv3atm_restart_read (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) - implicit none - type(GFS_data_type), intent(inout) :: GFS_Data(:) - type(GFS_restart_type), intent(inout) :: GFS_Restart - type(block_control_type), intent(in) :: Atm_block - type(GFS_control_type), intent(inout) :: Model - type(domain2d), intent(in) :: fv_domain - logical, intent(in) :: warm_start - logical, intent(in) :: ignore_rst_cksum - - !--- read in surface data from chgres - call sfc_prop_restart_read (GFS_Data%Sfcprop, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) - - !--- read in physics restart data - call phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_rst_cksum) - - end subroutine fv3atm_restart_read - - !--------------------- - ! fv3atm_restart_write - !--------------------- - subroutine fv3atm_restart_write (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, timestamp) - implicit none - type(GFS_data_type), intent(inout) :: GFS_Data(:) - type(GFS_restart_type), intent(inout) :: GFS_Restart - type(block_control_type), intent(in) :: Atm_block - 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 - 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) - - end subroutine fv3atm_restart_write - - - - !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - ! - ! PRIVATE SUBROUTINES - ! - !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - !---------------------------------------------------------------------- ! sfc_prop_restart_read !---------------------------------------------------------------------- @@ -492,22 +486,6 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta type (domain2d), intent(in) :: fv_domain logical, intent(in) :: warm_start logical, intent(in) :: ignore_rst_cksum - !--- local variables - integer :: i, j, k, ix, lsoil, num, nb, i_start, j_start, i_end, j_end, nt, n - integer :: isc, iec, jsc, jec, nx, ny - integer :: id_restart - integer :: isnow - integer, allocatable :: ii1(:), jj1(:) - real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() - real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() - 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() - real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_fr => NULL() - !--- local variables for sncovr calculation - integer :: vegtyp - logical :: mand - real(kind=kind_phys) :: rsnow, tem, tem1 !--- directory of the input files character(5) :: indir='INPUT' character(37) :: infile @@ -526,13 +504,6 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta type(FmsNetcdfDomainFile_t) :: Oro_restart, Sfc_restart, dust12m_restart, emi_restart, rrfssd_restart type(FmsNetcdfDomainFile_t) :: Oro_ls_restart, Oro_ss_restart - isc = Atm_block%isc - iec = Atm_block%iec - jsc = Atm_block%jsc - jec = Atm_block%jec - nx = (iec - isc + 1) - ny = (jec - jsc + 1) - !--- OROGRAPHY FILE !--- open file @@ -724,41 +695,18 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta type(GFS_control_type), intent(in) :: Model type(domain2d), intent(in) :: fv_domain character(len=32), optional, intent(in) :: timestamp - !--- local variables - integer :: i, j, k, nb, ix, lsoil, num, nt - integer :: isc, iec, jsc, jec, nx, ny - integer :: id_restart - logical :: mand - integer, allocatable :: ii1(:), jj1(:) - character(len=32) :: fn_srf = 'sfc_data.nc' - real(kind=kind_phys), pointer, dimension(:,:) :: var2_p => NULL() - real(kind=kind_phys), pointer, dimension(:,:,:) :: var3_p => NULL() - 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() - real(kind_phys) :: ice !--- 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 type(clm_lake_data_type), target :: clm_lake type(rrfs_sd_state_type) :: rrfs_sd_state type(Sfc_io_data_type) :: sfc - type(FmsNetcdfDomainFile_t) :: Sfc_restart - isc = Atm_block%isc - iec = Atm_block%iec - jsc = Atm_block%jsc - jec = Atm_block%jec - nx = (iec - isc + 1) - ny = (jec - jsc + 1) - !--- set filename infile=trim(indir)//'/'//trim(fn_srf) if( present(timestamp) ) infile=trim(indir)//'/'//trim(timestamp)//'.'//trim(fn_srf) @@ -849,14 +797,12 @@ subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_r !--- local variables integer :: i, j, k, nb, ix, num integer :: isc, iec, jsc, jec, nx, ny - integer :: id_restart - integer :: fdiag, ldiag 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 + logical :: amiopen, was_allocated type(phy_data_type) :: phy type(FmsNetcdfDomainFile_t) :: Phy_restart @@ -868,12 +814,7 @@ subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_r nx = (iec - isc + 1) ny = (jec - jsc + 1) - phy%npz = Atm_block%npz - phy%nvar2d = GFS_Restart%num2d - phy%nvar3d = GFS_Restart%num3d - - fdiag = GFS_Restart%fdiag - ldiag = GFS_Restart%ldiag + was_allocated = phy%alloc(GFS_Restart, Atm_block) !--- open restart file and register axes fname = trim(indir)//'/'//trim(fn_phy) @@ -889,17 +830,7 @@ subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_r endif !--- register the restart fields - if (.not. associated(phy%var2)) then - allocate (phy%var2(nx,ny,phy%nvar2d), phy%var2_names(phy%nvar2d)) - allocate (phy%var3(nx,ny,phy%npz,phy%nvar3d), phy%var3_names(phy%nvar3d)) - phy%var2 = zero - phy%var3 = zero - do num = 1,phy%nvar2d - phy%var2_names(num) = trim(GFS_Restart%name2d(num)) - enddo - do num = 1,phy%nvar3d - phy%var3_names(num) = trim(GFS_Restart%name3d(num)) - enddo + if(was_allocated) then do num = 1,phy%nvar2d var2_p => phy%var2(:,:,num) @@ -919,43 +850,7 @@ subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_r call read_restart(Phy_restart, ignore_checksum=ignore_rst_cksum) 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) - do num = 1,phy%nvar2d - do nb = 1,Atm_block%nblks - 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 - GFS_Restart%data(nb,num)%var2p(ix) = phy%var2(i,j,num) - enddo - enddo - enddo - !-- if restart from init time, reset accumulated diag fields - if( Model%phour < 1.e-7) then - do num = fdiag,ldiag - !$omp parallel do default(shared) private(i, j, nb, ix) - do nb = 1,Atm_block%nblks - 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 - GFS_Restart%data(nb,num)%var2p(ix) = zero - enddo - enddo - enddo - endif - do num = 1,phy%nvar3d - !$omp parallel do default(shared) private(i, j, k, nb, ix) - do nb = 1,Atm_block%nblks - do k=1,phy%npz - 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 - GFS_Restart%data(nb,num)%var3p(ix,k) = phy%var3(i,j,k,num) - enddo - enddo - enddo - enddo + call phy%transfer_data(.true., GFS_Restart, Atm_block, Model) end subroutine phys_restart_read @@ -981,7 +876,6 @@ subroutine phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timesta !--- local variables integer :: i, j, k, nb, ix, num integer :: isc, iec, jsc, jec, nx, ny - integer :: id_restart 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 @@ -989,7 +883,7 @@ subroutine phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timesta integer, allocatable, dimension(:) :: buffer character(7) :: indir='RESTART' character(72) :: infile - logical :: amiopen + logical :: amiopen, allocated_something type(phy_data_type) :: phy type(FmsNetcdfDomainFile_t) :: Phy_restart @@ -1001,9 +895,8 @@ subroutine phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timesta nx = (iec - isc + 1) ny = (jec - jsc + 1) - phy%npz = Atm_block%npz - phy%nvar2d = GFS_Restart%num2d - phy%nvar3d = GFS_Restart%num3d + !--- register the restart fields + allocated_something = phy%alloc(GFS_Restart, Atm_block) !--- set file name infile=trim(indir)//'/'//trim(fn_phy) @@ -1043,20 +936,6 @@ subroutine phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timesta call mpp_error(FATAL, 'Error opening file '//trim(infile)) end if - !--- register the restart fields - if (.not. associated(phy%var2)) then - allocate (phy%var2(nx,ny,phy%nvar2d), phy%var2_names(phy%nvar2d)) - allocate (phy%var3(nx,ny,phy%npz,phy%nvar3d), phy%var3_names(phy%nvar3d)) - phy%var2 = zero - phy%var3 = zero - do num = 1,phy%nvar2d - phy%var2_names(num) = trim(GFS_Restart%name2d(num)) - enddo - do num = 1,phy%nvar3d - phy%var3_names(num) = trim(GFS_Restart%name3d(num)) - enddo - endif - do num = 1,phy%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 '/),& @@ -1070,30 +949,7 @@ subroutine phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timesta nullify(var2_p) nullify(var3_p) - !--- 2D variables - !$omp parallel do default(shared) private(i, j, num, nb, ix) - do num = 1,phy%nvar2d - do nb = 1,Atm_block%nblks - 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) - enddo - enddo - enddo - !--- 3D variables - !$omp parallel do default(shared) private(i, j, k, num, nb, ix) - do num = 1,phy%nvar3d - do nb = 1,Atm_block%nblks - do k=1,phy%npz - 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) - enddo - enddo - enddo - enddo + call phy%transfer_data(.false., GFS_Restart, Atm_block, Model) call write_restart(Phy_restart) call close_file(Phy_restart) @@ -1113,31 +969,9 @@ subroutine fv3atm_restart_register (Sfcprop, GFS_restart, Atm_block, Model) type(GFS_control_type), intent(in) :: Model logical was_changed - integer :: isc, iec, jsc, jec, nx, ny - integer :: num - - isc = Atm_block%isc - iec = Atm_block%iec - jsc = Atm_block%jsc - jec = Atm_block%jec - phy_quilt%npz = Atm_block%npz - nx = (iec - isc + 1) - ny = (jec - jsc + 1) !--------------- phy - phy_quilt%nvar2d = GFS_Restart%num2d - phy_quilt%nvar3d = GFS_Restart%num3d - - allocate (phy_quilt%var2(nx,ny,phy_quilt%nvar2d), phy_quilt%var2_names(phy_quilt%nvar2d)) - allocate (phy_quilt%var3(nx,ny,phy_quilt%npz,phy_quilt%nvar3d), phy_quilt%var3_names(phy_quilt%nvar3d)) - phy_quilt%var2 = zero - phy_quilt%var3 = zero - do num = 1,phy_quilt%nvar2d - phy_quilt%var2_names(num) = trim(GFS_Restart%name2d(num)) - enddo - do num = 1,phy_quilt%nvar3d - phy_quilt%var3_names(num) = trim(GFS_Restart%name3d(num)) - enddo + was_changed = phy_quilt%alloc(GFS_Restart, Atm_block) !--------------- sfc was_changed = sfc_quilt%allocate_arrays(Model, Atm_block, .false., .true.) @@ -1161,51 +995,7 @@ subroutine fv_phy_restart_output(GFS_Restart, Atm_block) type(GFS_restart_type), intent(in) :: GFS_Restart type(block_control_type), intent(in) :: Atm_block - !*** local variables - integer :: i, j, k, n - integer :: nb, ix, num - integer :: isc, iec, jsc, jec, nx, ny - integer(8) :: rchk - - isc = Atm_block%isc - iec = Atm_block%iec - jsc = Atm_block%jsc - jec = Atm_block%jec - phy_quilt%npz = Atm_block%npz - nx = (iec - isc + 1) - ny = (jec - jsc + 1) - - !--- register the restart fields - if (.not. associated(phy_quilt%var2)) then - write(0,*)'phy_quilt%var2 must be allocated' - endif - if (.not. associated(phy_quilt%var3)) then - write(0,*)'phy_quilt%var3 must be allocated' - endif - - !--- 2D variables - do num = 1,phy_quilt%nvar2d - do nb = 1,Atm_block%nblks - 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_quilt%var2(i,j,num) = GFS_Restart%data(nb,num)%var2p(ix) - enddo - enddo - enddo - - !--- 3D variables - do num = 1,phy_quilt%nvar3d - do nb = 1,Atm_block%nblks - do k=1,phy_quilt%npz - 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_quilt%var3(i,j,k,num) = GFS_Restart%data(nb,num)%var3p(ix,k) - enddo - enddo - enddo - enddo + call phy_quilt%transfer_data(.false., GFS_Restart, Atm_block) end subroutine fv_phy_restart_output @@ -1242,9 +1032,8 @@ subroutine fv_phy_restart_bundle_setup(bundle, grid, rc) integer,intent(out) :: rc !*** local variables - integer i, j, k, n + integer i character(128) :: bdl_name - type(ESMF_Field) :: field character(128) :: outputfile real(kind_phys),dimension(:,:),pointer :: temp_r2d real(kind_phys),dimension(:,:,:),pointer :: temp_r3d @@ -1298,14 +1087,8 @@ subroutine fv_sfc_restart_bundle_setup(bundle, grid, Model, rc) integer,intent(out) :: rc !*** local variables - integer i, j, k, n character(128) :: sfcbdl_name - type(ESMF_Field) :: field character(128) :: outputfile - real(kind_phys),dimension(:,:),pointer :: temp_r2d - real(kind_phys),dimension(:,:,:),pointer :: temp_r3d - - integer :: num call ESMF_FieldBundleGet(bundle, name=sfcbdl_name,rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return @@ -1326,4 +1109,162 @@ subroutine fv_sfc_restart_bundle_setup(bundle, grid, Model, rc) end subroutine fv_sfc_restart_bundle_setup + !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + ! + ! PRIVATE SUBROUTINES + ! + !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + logical function phy_data_alloc(phy, GFS_Restart, Atm_block) + use fv3atm_common_io, only: get_nx_ny_from_atm + implicit none + class(phy_data_type) :: phy + type(GFS_restart_type), intent(in) :: GFS_Restart + type(block_control_type), intent(in) :: Atm_block + + integer :: nx, ny, num + + phy_data_alloc = .false. + + if(associated(phy%var2)) return + + call get_nx_ny_from_atm(Atm_block, nx, ny) + + phy%npz = Atm_block%npz + phy%nvar2d = GFS_Restart%num2d + phy%nvar3d = GFS_Restart%num3d + + allocate (phy%var2(nx,ny,phy%nvar2d), phy%var2_names(phy%nvar2d)) + allocate (phy%var3(nx,ny,phy%npz,phy%nvar3d), phy%var3_names(phy%nvar3d)) + phy%var2 = zero + phy%var3 = zero + do num = 1,phy%nvar2d + phy%var2_names(num) = trim(GFS_Restart%name2d(num)) + enddo + do num = 1,phy%nvar3d + phy%var3_names(num) = trim(GFS_Restart%name3d(num)) + enddo + + phy_data_alloc = .true. + end function phy_data_alloc + + subroutine phy_data_transfer_data(phy, reading, GFS_Restart, Atm_block, Model) + use mpp_mod, only: FATAL, mpp_error + implicit none + class(phy_data_type) :: phy + logical, intent(in) :: reading + type(GFS_restart_type) :: GFS_Restart + type(block_control_type) :: Atm_block + type(GFS_control_type), optional, intent(in) :: Model + + integer :: i, j, k, num, nb, ix + + !--- register the restart fields + if (.not. associated(phy%var2)) then + call mpp_error(FATAL,'phy%var2 must be allocated') + return ! should never get here + endif + if (.not. associated(phy%var3)) then + call mpp_error(FATAL,'phy%var3 must be allocated') + return ! should never get here + endif + + ! Copy 2D Vars + + if(reading) then + !--- place the data into the block GFS containers + !--- phy%var* variables + do num = 1,phy%nvar2d + !$omp parallel do default(shared) private(i, j, nb, ix) + do nb = 1,Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + i = Atm_block%index(nb)%ii(ix) - Atm_block%isc + 1 + j = Atm_block%index(nb)%jj(ix) - Atm_block%jsc + 1 + GFS_Restart%data(nb,num)%var2p(ix) = phy%var2(i,j,num) + enddo + enddo + enddo + else + !--- 2D variables + do num = 1,phy%nvar2d + !$omp parallel do default(shared) private(i, j, nb, ix) + do nb = 1,Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + i = Atm_block%index(nb)%ii(ix) - Atm_block%isc + 1 + j = Atm_block%index(nb)%jj(ix) - Atm_block%jsc + 1 + phy%var2(i,j,num) = GFS_Restart%data(nb,num)%var2p(ix) + enddo + enddo + enddo + endif + + !-- if restart from init time, reset accumulated diag fields + + if(reading .and. present(Model)) then + if(Model%phour < 1.e-7) then + do num = GFS_Restart%fdiag,GFS_Restart%ldiag + !$omp parallel do default(shared) private(i, j, nb, ix) + do nb = 1,Atm_block%nblks + do ix = 1, Atm_block%blksz(nb) + i = Atm_block%index(nb)%ii(ix) - Atm_block%isc + 1 + j = Atm_block%index(nb)%jj(ix) - Atm_block%jsc + 1 + GFS_Restart%data(nb,num)%var2p(ix) = zero + enddo + enddo + enddo + endif + endif + + ! Copy 3D Vars + + if(reading) then + do num = 1,phy%nvar3d + !$omp parallel do default(shared) private(i, j, k, nb, ix) + do nb = 1,Atm_block%nblks + do k=1,phy%npz + do ix = 1, Atm_block%blksz(nb) + i = Atm_block%index(nb)%ii(ix) - Atm_block%isc + 1 + j = Atm_block%index(nb)%jj(ix) - Atm_block%jsc + 1 + GFS_Restart%data(nb,num)%var3p(ix,k) = phy%var3(i,j,k,num) + enddo + enddo + enddo + enddo + else + !--- 3D variables + do num = 1,phy%nvar3d + !$omp parallel do default(shared) private(i, j, k, nb, ix) + do nb = 1,Atm_block%nblks + do k=1,phy%npz + do ix = 1, Atm_block%blksz(nb) + i = Atm_block%index(nb)%ii(ix) - Atm_block%isc + 1 + j = Atm_block%index(nb)%jj(ix) - Atm_block%jsc + 1 + phy%var3(i,j,k,num) = GFS_Restart%data(nb,num)%var3p(ix,k) + enddo + enddo + enddo + enddo + endif + + end subroutine phy_data_transfer_data + + subroutine phy_data_final(phy) + implicit none + type(phy_data_type) :: phy + + ! This #define reduces code length by a lot +#define IF_ASSOC_DEALLOC_NULL(var) \ + if(associated(phy%var)) then ; \ + deallocate(phy%var) ; \ + nullify(phy%var) ; \ + endif + + IF_ASSOC_DEALLOC_NULL(var2) + IF_ASSOC_DEALLOC_NULL(var3) + IF_ASSOC_DEALLOC_NULL(var2_names) + IF_ASSOC_DEALLOC_NULL(var3_names) + +#undef IF_ASSOC_DEALLOC_NULL + end subroutine phy_data_final + end module fv3atm_restart_io_mod diff --git a/io/fv3atm_sfc_io.F90 b/io/fv3atm_sfc_io.F90 index 77c2bef10..2b9ce67c6 100644 --- a/io/fv3atm_sfc_io.F90 +++ b/io/fv3atm_sfc_io.F90 @@ -255,7 +255,8 @@ subroutine Sfc_io_register_axes(sfc, Model, Sfc_restart, reading, warm_start) if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp) then call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil) else if(Model%lsm == Model%lsm_ruc .and. reading) then - ! Possible bug. This is only defined on read, not write. + ! The RUC defines zaxis_1 for reading, so it can read a restart from a different LSM. + ! The lsm_ruc never writes zaxis_2. call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil_lsm) endif if(Model%lsm == Model%lsm_noahmp) then From ca65a7f7cc3f8ba18a410e04f38b2f946055dfd1 Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Tue, 30 May 2023 18:03:57 +0000 Subject: [PATCH 24/27] delete trailing whitespace --- io/fv3atm_clm_lake_io.F90 | 6 +++--- io/fv3atm_restart_io.F90 | 4 ++-- io/fv3atm_sfc_io.F90 | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/io/fv3atm_clm_lake_io.F90 b/io/fv3atm_clm_lake_io.F90 index 481485a12..e5cde522d 100644 --- a/io/fv3atm_clm_lake_io.F90 +++ b/io/fv3atm_clm_lake_io.F90 @@ -106,7 +106,7 @@ subroutine clm_lake_allocate_data(clm_lake,Model) allocate(clm_lake%lake_sndpth2d(nx,ny)) allocate(clm_lake%clm_lakedepth(nx,ny)) allocate(clm_lake%clm_lake_initialized(nx,ny)) - + allocate(clm_lake%lake_z3d(nx,ny,Model%nlevlake_clm_lake)) allocate(clm_lake%lake_dz3d(nx,ny,Model%nlevlake_clm_lake)) allocate(clm_lake%lake_soil_watsat3d(nx,ny,Model%nlevlake_clm_lake)) @@ -465,7 +465,7 @@ subroutine clm_lake_deallocate_data(clm_lake) deallocate(clm_lake%var) ; \ nullify(clm_lake%var) ; \ endif - + IF_ASSOC_DEALLOC_NULL(T_snow) IF_ASSOC_DEALLOC_NULL(T_ice) IF_ASSOC_DEALLOC_NULL(lake_snl2d) @@ -494,7 +494,7 @@ subroutine clm_lake_deallocate_data(clm_lake) IF_ASSOC_DEALLOC_NULL(lake_icefrac3d) IF_ASSOC_DEALLOC_NULL(lake_clay3d) IF_ASSOC_DEALLOC_NULL(lake_sand3d) - + #undef IF_ASSOC_DEALLOC_NULL end subroutine clm_lake_deallocate_data diff --git a/io/fv3atm_restart_io.F90 b/io/fv3atm_restart_io.F90 index b04bf7fff..8915354a1 100644 --- a/io/fv3atm_restart_io.F90 +++ b/io/fv3atm_restart_io.F90 @@ -806,7 +806,7 @@ subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_r type(phy_data_type) :: phy type(FmsNetcdfDomainFile_t) :: Phy_restart - + isc = Atm_block%isc iec = Atm_block%iec jsc = Atm_block%jsc @@ -1245,7 +1245,7 @@ subroutine phy_data_transfer_data(phy, reading, GFS_Restart, Atm_block, Model) enddo enddo endif - + end subroutine phy_data_transfer_data subroutine phy_data_final(phy) diff --git a/io/fv3atm_sfc_io.F90 b/io/fv3atm_sfc_io.F90 index 2b9ce67c6..a6370fd6b 100644 --- a/io/fv3atm_sfc_io.F90 +++ b/io/fv3atm_sfc_io.F90 @@ -619,7 +619,7 @@ subroutine Sfc_io_register_2d_fields(sfc,Model,Sfc_restart,reading,warm_start) do num = sfc%nvar_before_lake+1,sfc%nvar_before_lake+sfc%nvar2l var2_p => sfc%var2(:,:,num) if(sfc%is_lsoil) then - call register_restart_field(Sfc_restart, sfc%name2(num),var2_p,dimensions=(/'lat','lon'/), is_optional=.not.mand) + 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=time2d, is_optional=.not.mand) endif @@ -729,7 +729,7 @@ subroutine Sfc_io_transfer(sfc, reading, Model, Atm_block, Sfcprop, warm_start, ! "To" variable: ! to=.TRUE. means transfer sfc data TO Sfcprop grid - ! to=.FALSE. means transfer into sfc data FROM Sfcprop grid + ! to=.FALSE. means transfer into sfc data FROM Sfcprop grid isc = Atm_block%isc iec = Atm_block%iec @@ -933,7 +933,7 @@ subroutine Sfc_io_transfer(sfc, reading, Model, Atm_block, Sfcprop, warm_start, ! !--- NSSTM variables !tgs - the following line is a bug that will show if(Model%cplwav) = true - !nt = sfc%nvar2m + !nt = sfc%nvar2m if (Model%nstf_name(1) > 0) then if (reading .and. Model%nstf_name(2) == 1) then ! nsst spinup !--- nsstm tref From c9f1c0e05e2e77c33bbb98ea218ca53f878f09ae Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Tue, 30 May 2023 20:49:20 +0000 Subject: [PATCH 25/27] remove unneeded "use...only" --- io/fv3atm_clm_lake_io.F90 | 17 ++++++----------- io/fv3atm_common_io.F90 | 2 +- io/fv3atm_history_io.F90 | 20 +++----------------- io/fv3atm_oro_io.F90 | 11 ++--------- io/fv3atm_restart_io.F90 | 9 ++++----- io/fv3atm_rrfs_sd_io.F90 | 16 +++++----------- io/fv3atm_sfc_io.F90 | 18 +++++++----------- 7 files changed, 28 insertions(+), 65 deletions(-) diff --git a/io/fv3atm_clm_lake_io.F90 b/io/fv3atm_clm_lake_io.F90 index e5cde522d..bb80e9e01 100644 --- a/io/fv3atm_clm_lake_io.F90 +++ b/io/fv3atm_clm_lake_io.F90 @@ -1,16 +1,11 @@ module fv3atm_clm_lake_io - use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, & - GFS_data_type, kind_phys - use GFS_restart, only: GFS_restart_type - use GFS_diagnostics, only: GFS_externaldiag_type + use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys use block_control_mod, only: block_control_type - 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 fv3atm_common_io + use fms2_io_mod, only: FmsNetcdfDomainFile_t, register_axis, & + register_restart_field, write_data, & + register_variable_attribute, register_field + use fv3atm_common_io, only: create_2d_field_and_add_to_bundle, & + create_3d_field_and_add_to_bundle implicit none diff --git a/io/fv3atm_common_io.F90 b/io/fv3atm_common_io.F90 index c237ceb90..0fab618b8 100644 --- a/io/fv3atm_common_io.F90 +++ b/io/fv3atm_common_io.F90 @@ -1,6 +1,5 @@ module fv3atm_common_io use GFS_typedefs, only: kind_phys - use block_control_mod, only: block_control_type implicit none private @@ -56,6 +55,7 @@ module fv3atm_common_io contains pure subroutine get_nx_ny_from_atm(Atm_block, nx, ny) + use block_control_mod, only: block_control_type implicit none type(block_control_type), intent(in) :: Atm_block integer, intent(out), optional :: nx, ny diff --git a/io/fv3atm_history_io.F90 b/io/fv3atm_history_io.F90 index 7d1467050..1504e6971 100644 --- a/io/fv3atm_history_io.F90 +++ b/io/fv3atm_history_io.F90 @@ -15,16 +15,8 @@ module fv3atm_history_io_mod ! !--- FMS/GFDL modules 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: 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 mpp_mod, only: mpp_error, mpp_pe, mpp_root_pe, FATAL + use mpp_domains_mod, only: domain1d, domainUG use time_manager_mod, only: time_type use diag_manager_mod, only: register_diag_field, send_data use diag_axis_mod, only: get_axis_global_length, get_diag_axis, & @@ -32,17 +24,11 @@ module fv3atm_history_io_mod use diag_data_mod, only: output_fields, max_output_fields use diag_util_mod, only: find_input_field use constants_mod, only: grav, rdgas - use physcons, only: con_tice !saltwater freezing temp (K) - use fv3atm_clm_lake_io, only: clm_lake_data_type ! !--- GFS_typedefs - use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, & - GFS_data_type, kind_phys - use GFS_restart, only: GFS_restart_type + use GFS_typedefs, only: GFS_control_type, kind_phys use GFS_diagnostics, only: GFS_externaldiag_type - use fv3atm_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data - ! !----------------------------------------------------------------------- implicit none diff --git a/io/fv3atm_oro_io.F90 b/io/fv3atm_oro_io.F90 index 37f4e15b0..7cd60301e 100644 --- a/io/fv3atm_oro_io.F90 +++ b/io/fv3atm_oro_io.F90 @@ -1,17 +1,10 @@ module fv3atm_oro_io use block_control_mod, only: block_control_type - use fms2_io_mod, only: FmsNetcdfDomainFile_t, unlimited, & - register_axis, register_restart_field, & - register_variable_attribute, register_field, & - read_restart, write_restart, write_data, & - get_global_io_domain_indices, variable_exists + use fms2_io_mod, only: FmsNetcdfDomainFile_t, & + register_axis, register_restart_field use fv3atm_common_io, only: get_nx_ny_from_atm use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys - use GFS_restart, only: GFS_restart_type - use mpp_mod, only: mpp_error, mpp_pe, mpp_root_pe, & - mpp_chksum, NOTE, FATAL - use physcons, only: con_tice !saltwater freezing temp (K) implicit none private diff --git a/io/fv3atm_restart_io.F90 b/io/fv3atm_restart_io.F90 index 8915354a1..f99bc3c8e 100644 --- a/io/fv3atm_restart_io.F90 +++ b/io/fv3atm_restart_io.F90 @@ -1,8 +1,7 @@ module fv3atm_restart_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 mpp_mod, only: mpp_error, mpp_chksum, NOTE, FATAL use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys, GFS_data_type use GFS_restart, only: GFS_restart_type use fms_mod, only: stdout @@ -11,10 +10,10 @@ module fv3atm_restart_io_mod 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 + get_global_io_domain_indices + use mpp_domains_mod, only: domain2d use fv3atm_common_io, only: create_2d_field_and_add_to_bundle, & - create_3d_field_and_add_to_bundle, add_zaxis_to_field, copy_from_gfs_data + create_3d_field_and_add_to_bundle, copy_from_gfs_data use fv3atm_sfc_io use fv3atm_rrfs_sd_io use fv3atm_clm_lake_io diff --git a/io/fv3atm_rrfs_sd_io.F90 b/io/fv3atm_rrfs_sd_io.F90 index 1fbbe2dfc..2910e79a6 100644 --- a/io/fv3atm_rrfs_sd_io.F90 +++ b/io/fv3atm_rrfs_sd_io.F90 @@ -1,17 +1,11 @@ module fv3atm_rrfs_sd_io use block_control_mod, only: block_control_type - 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 GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, & - GFS_data_type, kind_phys - use GFS_restart, only: GFS_restart_type - use GFS_diagnostics, only: GFS_externaldiag_type + use fms2_io_mod, only: FmsNetcdfDomainFile_t, write_data, & + register_axis, register_restart_field, & + register_variable_attribute, register_field + use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys use fv3atm_common_io, only: get_nx_ny_from_atm, create_2d_field_and_add_to_bundle, & - create_3d_field_and_add_to_bundle, add_zaxis_to_field + create_3d_field_and_add_to_bundle implicit none diff --git a/io/fv3atm_sfc_io.F90 b/io/fv3atm_sfc_io.F90 index a6370fd6b..e08ab8dec 100644 --- a/io/fv3atm_sfc_io.F90 +++ b/io/fv3atm_sfc_io.F90 @@ -1,18 +1,14 @@ module fv3atm_sfc_io use block_control_mod, only: block_control_type - use fms2_io_mod, only: FmsNetcdfDomainFile_t, unlimited, & - register_axis, register_restart_field, & - register_variable_attribute, register_field, & - read_restart, write_restart, write_data, & - get_global_io_domain_indices, variable_exists - use fv3atm_common_io, only: copy_from_GFS_Data, copy_to_GFS_Data, GFS_Data_transfer, & - create_2d_field_and_add_to_bundle, create_3d_field_and_add_to_bundle, & - add_zaxis_to_field + use fms2_io_mod, only: FmsNetcdfDomainFile_t, unlimited, write_data,& + register_axis, register_restart_field, & + register_variable_attribute, register_field, & + get_global_io_domain_indices, variable_exists + use fv3atm_common_io, only: GFS_Data_transfer, & + create_2d_field_and_add_to_bundle, create_3d_field_and_add_to_bundle use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys - use GFS_restart, only: GFS_restart_type - use mpp_mod, only: mpp_error, mpp_pe, mpp_root_pe, & - mpp_chksum, NOTE, FATAL + use mpp_mod, only: mpp_error, NOTE use physcons, only: con_tice !saltwater freezing temp (K) implicit none From b5ab9aea2056d541c2f496618da0687a6385a75c Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Wed, 31 May 2023 20:21:31 +0000 Subject: [PATCH 26/27] comments, consistent indentation, remove trailing whitespace --- io/fv3atm_clm_lake_io.F90 | 125 ++++--- io/fv3atm_common_io.F90 | 769 +++++++++++++++++++++----------------- io/fv3atm_history_io.F90 | 125 ++++--- io/fv3atm_oro_io.F90 | 36 +- io/fv3atm_restart_io.F90 | 149 ++++---- io/fv3atm_rrfs_sd_io.F90 | 72 +++- io/fv3atm_sfc_io.F90 | 55 ++- 7 files changed, 793 insertions(+), 538 deletions(-) diff --git a/io/fv3atm_clm_lake_io.F90 b/io/fv3atm_clm_lake_io.F90 index bb80e9e01..5c61a26be 100644 --- a/io/fv3atm_clm_lake_io.F90 +++ b/io/fv3atm_clm_lake_io.F90 @@ -1,11 +1,20 @@ +!> \file fv3atm_clm_lake_io.F90 +!! This code reads and writes restart files for the CLM Lake Model. The source code of +!! that model can be found in CCPP. Only the fv3atm_restart_io.F90 should ever access +!! these routines. +!! +!! The CLM Lake Model has its own restart code due to its five alternative vertical +!! levels, which don't match the five found in the other surface fields. For the sake +!! of code simplicity, a dedicated file was a better implementation. + module fv3atm_clm_lake_io use GFS_typedefs, only: GFS_sfcprop_type, GFS_control_type, kind_phys use block_control_mod, only: block_control_type use fms2_io_mod, only: FmsNetcdfDomainFile_t, register_axis, & - register_restart_field, write_data, & - register_variable_attribute, register_field + register_restart_field, write_data, & + register_variable_attribute, register_field use fv3atm_common_io, only: create_2d_field_and_add_to_bundle, & - create_3d_field_and_add_to_bundle + create_3d_field_and_add_to_bundle implicit none @@ -15,15 +24,17 @@ module fv3atm_clm_lake_io clm_lake_copy_from_grid, clm_lake_copy_to_grid, clm_lake_bundle_fields, & clm_lake_final - type clm_lake_data_type - ! The clm_lake_data_type derived type is a class that stores - ! temporary arrays used to read or write CLM Lake model restart - ! and axis variables. It can safely be declared and unused, but - ! you should only call these routines if the CLM Lake Model was - ! (or will be) used by this execution of the FV3. It is the - ! responsibility of the caller to ensure the necessary data is in - ! Sfc_restart, Sfcprop, and Model. + !>\defgroup CLM Lake Model restart public interface + !> @{ + !>@ The clm_lake_data_type derived type is a class that stores + !! temporary arrays used to read or write CLM Lake model restart + !! and axis variables. It can safely be declared and unused, but + !! you should only call these routines if the CLM Lake Model was + !! (or will be) used by this execution of the FV3. It is the + !! responsibility of the caller to ensure the necessary data is in + !! Sfc_restart, Sfcprop, and Model. + type clm_lake_data_type ! All 2D variables needed for a restart real(kind_phys), pointer, private, dimension(:,:) :: & T_snow=>null(), T_ice=>null(), & @@ -79,9 +90,11 @@ module fv3atm_clm_lake_io final :: clm_lake_final end type clm_lake_data_type - CONTAINS +CONTAINS + + !>@ This subroutine is clm_lake%alocate_data. It deallocates all + !! data, and reallocate to the size specified in Model subroutine clm_lake_allocate_data(clm_lake,Model) - ! Deallocate all data, and reallocate to the size specified in Model implicit none class(clm_lake_data_type) :: clm_lake type(GFS_control_type), intent(in) :: Model @@ -140,8 +153,9 @@ subroutine clm_lake_allocate_data(clm_lake,Model) enddo end subroutine clm_lake_allocate_data + !>@ This is clm_lake%register_axes. It registers all five axes needed + !! by CLM Lake restart data. subroutine clm_lake_register_axes(clm_lake,Model,Sfc_restart) - ! Register all five axes needed by CLM Lake restart data implicit none class(clm_lake_data_type) :: clm_lake type(GFS_control_type), intent(in) :: Model @@ -153,9 +167,10 @@ subroutine clm_lake_register_axes(clm_lake,Model,Sfc_restart) call register_axis(Sfc_restart, 'levsnowsoil1_clm_lake', dimension_length=Model%nlevsnowsoil1_clm_lake) end subroutine clm_lake_register_axes + !>@ This is clm_lake%write_axes. It creates variables with the name + !! name as each clm_lake axis, and fills the variable with the + !! appropriate indices subroutine clm_lake_write_axes(clm_lake, Model, Sfc_restart) - ! Create variables with the name name as each clm_lake axis, and - ! fill the variable with the appropriate indices implicit none class(clm_lake_data_type) :: clm_lake type(GFS_control_type), intent(in) :: Model @@ -179,9 +194,11 @@ subroutine clm_lake_write_axes(clm_lake, Model, Sfc_restart) call write_data(Sfc_restart, 'levsnowsoil1_clm_lake', clm_lake%levsnowsoil1_clm_lake) end subroutine clm_lake_write_axes + !>@ This is clm_lake%copy_from_grid. It copies from Sfcprop + !! variables to the corresponding data temporary variables. + !! Terrible things will happen if you don't call + !! clm_lake%allocate_data first. subroutine clm_lake_copy_from_grid(clm_lake, Model, Atm_block, Sfcprop) - ! Copies from Sfcprop variables to the corresponding data temporary variables. - ! Terrible things will happen if you don't call clm_lake%allocate_data first. implicit none class(clm_lake_data_type) :: clm_lake type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) @@ -194,7 +211,7 @@ subroutine clm_lake_copy_from_grid(clm_lake, Model, Atm_block, Sfcprop) ! Copy data to temporary arrays -!$omp parallel do default(shared) private(i, j, nb, ix) + !$omp parallel do default(shared) private(i, j, nb, ix) do nb = 1, Atm_block%nblks do ix = 1, Atm_block%blksz(nb) i = Atm_block%index(nb)%ii(ix) - isc + 1 @@ -232,9 +249,10 @@ subroutine clm_lake_copy_from_grid(clm_lake, Model, Atm_block, Sfcprop) enddo end subroutine clm_lake_copy_from_grid + !>@ This is clm_lake%copy_to_grid. It copies from data temporary + !! variables to the corresponding Sfcprop variables. Terrible + !! things will happen if you don't call data%allocate_data first. subroutine clm_lake_copy_to_grid(clm_lake, Model, Atm_block, Sfcprop) - ! Copies from data temporary variables to the corresponding Sfcprop variables. - ! Terrible things will happen if you don't call data%allocate_data first. implicit none class(clm_lake_data_type) :: clm_lake type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) @@ -247,7 +265,7 @@ subroutine clm_lake_copy_to_grid(clm_lake, Model, Atm_block, Sfcprop) ! Copy data to temporary arrays -!$omp parallel do default(shared) private(i, j, nb, ix) + !$omp parallel do default(shared) private(i, j, nb, ix) do nb = 1, Atm_block%nblks do ix = 1, Atm_block%blksz(nb) i = Atm_block%index(nb)%ii(ix) - isc + 1 @@ -285,10 +303,11 @@ subroutine clm_lake_copy_to_grid(clm_lake, Model, Atm_block, Sfcprop) enddo end subroutine clm_lake_copy_to_grid + !>@ This is clm_lake%register_fields, and it is only used in the + !! non-quilt restart. It registers all restart fields needed by the + !! CLM Lake Model. Terrible things will happen if you don't call + !! clm_lake%allocate_data and clm_lake%register_axes first. subroutine clm_lake_register_fields(clm_lake, Sfc_restart) - ! Registers all restart fields needed by the CLM Lake Model. - ! Terrible things will happen if you don't call clm_lake%allocate_data - ! and clm_lake%register_axes first. implicit none class(clm_lake_data_type) :: clm_lake type(FmsNetcdfDomainFile_t) :: Sfc_restart @@ -316,61 +335,65 @@ subroutine clm_lake_register_fields(clm_lake, Sfc_restart) ! Register 3D fields call register_restart_field(Sfc_restart, 'lake_z3d', clm_lake%lake_z3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levlake_clm_lake ', 'Time '/), is_optional=.true.) + 'levlake_clm_lake ', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart, 'lake_dz3d', clm_lake%lake_dz3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levlake_clm_lake ', 'Time '/), is_optional=.true.) + 'levlake_clm_lake ', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_soil_watsat3d', clm_lake%lake_soil_watsat3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levlake_clm_lake ', 'Time '/), is_optional=.true.) + 'levlake_clm_lake ', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_csol3d', clm_lake%lake_csol3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levlake_clm_lake ', 'Time '/), is_optional=.true.) + 'levlake_clm_lake ', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_soil_tkmg3d', clm_lake%lake_soil_tkmg3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levlake_clm_lake ', 'Time '/), is_optional=.true.) + 'levlake_clm_lake ', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_soil_tkdry3d', clm_lake%lake_soil_tkdry3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levlake_clm_lake ', 'Time '/), is_optional=.true.) + 'levlake_clm_lake ', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_soil_tksatu3d', clm_lake%lake_soil_tksatu3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levlake_clm_lake ', 'Time '/), is_optional=.true.) + 'levlake_clm_lake ', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_snow_z3d', clm_lake%lake_snow_z3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) + 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_snow_dz3d', clm_lake%lake_snow_dz3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) + 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_snow_zi3d', clm_lake%lake_snow_zi3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levsnowsoil_clm_lake ', 'Time '/), is_optional=.true.) + 'levsnowsoil_clm_lake ', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_h2osoi_vol3d', clm_lake%lake_h2osoi_vol3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) + 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_h2osoi_liq3d', clm_lake%lake_h2osoi_liq3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) + 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_h2osoi_ice3d', clm_lake%lake_h2osoi_ice3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) + 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_t_soisno3d', clm_lake%lake_t_soisno3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) + 'levsnowsoil1_clm_lake', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_t_lake3d', clm_lake%lake_t_lake3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levlake_clm_lake ', 'Time '/), is_optional=.true.) + 'levlake_clm_lake ', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_icefrac3d', clm_lake%lake_icefrac3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levlake_clm_lake ', 'Time '/), is_optional=.true.) + 'levlake_clm_lake ', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_clay3d', clm_lake%lake_clay3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levsoil_clm_lake ', 'Time '/), is_optional=.true.) + 'levsoil_clm_lake ', 'Time '/), is_optional=.true.) call register_restart_field(Sfc_restart,'lake_sand3d', clm_lake%lake_sand3d, & dimensions=(/'xaxis_1 ', 'yaxis_1 ', & - 'levsoil_clm_lake ', 'Time '/), is_optional=.true.) + 'levsoil_clm_lake ', 'Time '/), is_optional=.true.) end subroutine clm_lake_register_fields - + !>@ This is clm_lake%bundle_fields, and it is only used in the + !! quilt restart. It bundles all fields needed by the CLM Lake + !! Model, which makes them available to ESMF for restart I/O. + !! Terrible things will happen if you don't call + !! clm_lake%allocate_data and clm_lake%register_axes first. subroutine clm_lake_bundle_fields(clm_lake, bundle, grid, Model, outputfile) use esmf use GFS_typedefs, only: GFS_control_type @@ -436,19 +459,20 @@ subroutine clm_lake_bundle_fields(clm_lake, bundle, grid, Model, outputfile) end subroutine Clm_lake_bundle_fields + !>@ Final routine (destructor) for the clm_lake_data_type, called + !! automatically when an object of that type goes out of scope. This + !! is simply a wrapper around clm_lake%deallocate_data(). subroutine clm_lake_final(clm_lake) - ! Final routine for clm_lake_data_type, called automatically when - ! an object of that type goes out of scope. This is simply a - ! wrapper around clm_lake%deallocate_data(). implicit none type(clm_lake_data_type) :: clm_lake call clm_lake_deallocate_data(clm_lake) end subroutine clm_lake_final + !>@ This is clm_lake%deallocate_data. It deallocates all data used, + !! and nullifies the pointers. The clm_lake object can safely be + !! used again after this call. This is also the implementation of + !! the clm_lake_data_type final routine. subroutine clm_lake_deallocate_data(clm_lake) - ! Deallocates all data used, and nullifies the pointers. The clm_lake - ! object can safely be used again after this call. This is also - ! the implementation of the clm_lake_data_type final routine. implicit none class(clm_lake_data_type) :: clm_lake @@ -494,3 +518,4 @@ subroutine clm_lake_deallocate_data(clm_lake) end subroutine clm_lake_deallocate_data end module fv3atm_clm_lake_io +!> @} diff --git a/io/fv3atm_common_io.F90 b/io/fv3atm_common_io.F90 index 0fab618b8..1143f23ac 100644 --- a/io/fv3atm_common_io.F90 +++ b/io/fv3atm_common_io.F90 @@ -1,3 +1,9 @@ +!> \file fv3atm_common_io.F90 +!! A set of routines commonly accessed by other io/fv3atm +!! modules. This should not be accessed by other code. Most of the +!! routines in this file copy data between x-y-z arrays and +!! block-decomposed (nb-ix-z) atmosphere arrays. + module fv3atm_common_io use GFS_typedefs, only: kind_phys @@ -13,11 +19,11 @@ module fv3atm_common_io public :: GFS_data_transfer public :: GFS_data_transfer_2d_phys2phys, & - GFS_data_transfer_3d_phys2phys, & - GFS_data_transfer_2d_int2phys, & - GFS_data_transfer_3d_int2phys, & - GFS_data_transfer_3d_slice_phys2phys, & - GFS_data_transfer_2d_stack_phys2phys + GFS_data_transfer_3d_phys2phys, & + GFS_data_transfer_2d_int2phys, & + GFS_data_transfer_3d_int2phys, & + GFS_data_transfer_3d_slice_phys2phys, & + GFS_data_transfer_2d_stack_phys2phys public :: create_2d_field_and_add_to_bundle public :: create_3d_field_and_add_to_bundle @@ -25,6 +31,14 @@ module fv3atm_common_io public :: get_nx_ny_from_atm + !>\defgroup fv3atm_common_io FV3ATM Common I/O Utilities Module + !> @{ + + !>@ These subroutines copy data from x-y-z arrays to nb-ix-z grid arrays. + !! \section copy_from_GFS_Data interface + !! There are different combinations of decomposition, copy methods, + !! and datatypes. All are combined together into copy_from_GFS_Data + !! for convenience interface copy_from_GFS_Data module procedure copy_from_GFS_Data_2d_phys2phys, & copy_from_GFS_Data_3d_phys2phys, & @@ -32,8 +46,13 @@ module fv3atm_common_io copy_from_GFS_Data_3d_int2phys, & copy_from_GFS_Data_3d_slice_phys2phys, & copy_from_GFS_Data_2d_stack_phys2phys - end interface + end interface copy_from_GFS_Data + !>@ These subroutines copy data from nb-ix-z grid arrays to x-y-z arrays. + !! \section copy_to_GFS_Data interface + !! There are different combinations of decomposition, copy methods, + !! and datatypes. All are combined together into copy_to_GFS_Data + !! for convenience interface copy_to_GFS_Data module procedure copy_to_GFS_Data_2d_phys2phys, & copy_to_GFS_Data_3d_phys2phys, & @@ -43,6 +62,15 @@ module fv3atm_common_io copy_to_GFS_Data_2d_stack_phys2phys end interface copy_to_GFS_Data + !>@brief These subroutines copy data in either direction between nb-ix-z grid arrays and x-y-z arrays. + !> \section GFS_data_transfer interface functions. + !! This interface allows a single subroutine to handle both reading + !! and writing restart files. The direction is controled by the "to" + !! argument (first argument) which is true when copying from x-y-z + !! arrays to nb-ix-z arrays. + !! There are different combinations of decomposition, copy methods, + !! and datatypes. All are combined together into copy_to_GFS_Data + !! for convenience interface GFS_data_transfer module procedure GFS_data_transfer_2d_phys2phys, & GFS_data_transfer_3d_phys2phys, & @@ -54,6 +82,7 @@ module fv3atm_common_io contains + !>@brief Convenience function to get the x and y dimensions of the grid from Atm_block pure subroutine get_nx_ny_from_atm(Atm_block, nx, ny) use block_control_mod, only: block_control_type implicit none @@ -72,366 +101,418 @@ pure subroutine get_nx_ny_from_atm(Atm_block, nx, ny) endif end subroutine get_nx_ny_from_atm - pure subroutine copy_from_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(in) :: var_block(:) - real(kind=kind_phys), intent(out) :: var2d(:,:,:) - integer ix - - nt=nt+1 - do ix=1,size(var_block) - var2d(ii1(ix),jj1(ix),nt) = var_block(ix) - enddo - end subroutine copy_from_GFS_Data_2d_phys2phys - - pure subroutine copy_from_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(in) :: var_block(:,:) - real(kind=kind_phys), intent(out) :: var3d(:,:,:,:) - integer ix, k - - nt=nt+1 - do k=lbound(var_block,2),ubound(var_block,2) - do ix=1,size(var_block,1) - var3d(ii1(ix),jj1(ix),k,nt) = var_block(ix,k) - enddo - enddo - end subroutine copy_from_GFS_Data_3d_phys2phys - - pure subroutine copy_from_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc, var_block(:) - integer, intent(inout) :: nt - real(kind=kind_phys), intent(out) :: var2d(:,:,:) - integer ix - - nt=nt+1 - do ix=1,size(var_block) - var2d(ii1(ix),jj1(ix),nt) = var_block(ix) - enddo - end subroutine copy_from_GFS_Data_2d_int2phys - - pure subroutine copy_from_GFS_Data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - ! For copying phy_f2d and phy_fctd - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(in) :: var_block(:,:) - real(kind=kind_phys), intent(out) :: var3d(:,:,:) - integer ix, k - - nt=nt+1 - do k=lbound(var_block,2),ubound(var_block,2) - do ix=1,size(var_block,1) - var3d(ii1(ix),jj1(ix),nt) = var_block(ix,k) - enddo - enddo - end subroutine copy_from_GFS_Data_2d_stack_phys2phys - - pure subroutine copy_from_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), var_block(:,:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(out) :: var3d(:,:,:,:) - integer ix, k - - nt=nt+1 - do k=lbound(var_block,2),ubound(var_block,2) - do ix=1,size(var_block,1) - var3d(ii1(ix),jj1(ix),k,nt) = real(var_block(ix,k),kind_phys) - enddo - enddo - end subroutine copy_from_GFS_Data_3d_int2phys - - pure subroutine copy_from_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc, k1, k2 - integer, intent(inout) :: nt - real(kind=kind_phys), intent(in) :: var_block(:,:) - real(kind=kind_phys), intent(out) :: var3d(:,:,:,:) - integer ix, k - - nt=nt+1 - do k=k1,k2 - do ix=1,size(var_block,1) - var3d(ii1(ix),jj1(ix),k,nt) = var_block(ix,k) - enddo - enddo - end subroutine copy_from_GFS_Data_3d_slice_phys2phys - - pure subroutine copy_to_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(out) :: var_block(:) - real(kind=kind_phys), intent(in) :: var2d(:,:,:) - integer ix - - nt=nt+1 - do ix=1,size(var_block) - var_block(ix) = var2d(ii1(ix),jj1(ix),nt) - enddo - end subroutine copy_to_GFS_Data_2d_phys2phys - - pure subroutine copy_to_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(out) :: var_block(:,:) - real(kind=kind_phys), intent(in) :: var3d(:,:,:,:) - integer ix, k - - nt=nt+1 - do k=lbound(var_block,2),ubound(var_block,2) - do ix=1,size(var_block,1) - var_block(ix,k) = var3d(ii1(ix),jj1(ix),k,nt) - enddo - enddo - end subroutine copy_to_GFS_Data_3d_phys2phys - - pure subroutine copy_to_GFS_Data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - ! For copying phy_f2d and phy_fctd - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(out) :: var_block(:,:) - real(kind=kind_phys), intent(in) :: var3d(:,:,:) - integer ix, k - - nt=nt+1 - do k=lbound(var_block,2),ubound(var_block,2) - do ix=1,size(var_block,1) - var_block(ix,k) = var3d(ii1(ix),jj1(ix),nt) - enddo - enddo - end subroutine copy_to_GFS_Data_2d_stack_phys2phys - - pure subroutine copy_to_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc, k1, k2 - integer, intent(inout) :: nt - real(kind=kind_phys), intent(out) :: var_block(:,:) - real(kind=kind_phys), intent(in) :: var3d(:,:,:,:) - integer ix, k - - nt=nt+1 - do k=k1,k2 - do ix=1,size(var_block,1) - var_block(ix,k) = var3d(ii1(ix),jj1(ix),k,nt) - enddo - enddo - end subroutine copy_to_GFS_Data_3d_slice_phys2phys - - pure subroutine copy_to_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - integer, intent(out) :: var_block(:) - real(kind=kind_phys), intent(in) :: var2d(:,:,:) - integer ix - - nt=nt+1 - do ix=1,size(var_block) - var_block(ix) = int(var2d(ii1(ix),jj1(ix),nt)) - enddo - end subroutine copy_to_GFS_Data_2d_int2phys - - pure subroutine copy_to_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - implicit none - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - integer, intent(out) :: var_block(:,:) - real(kind=kind_phys), intent(in) :: var3d(:,:,:,:) - integer ix - - nt=nt+1 - do ix=1,size(var_block,1) - var_block(ix,:) = int(var3d(ii1(ix),jj1(ix),:,nt)) - enddo - end subroutine copy_to_GFS_Data_3d_int2phys - - pure subroutine GFS_data_transfer_2d_phys2phys(to,ii1,jj1,isc,jsc,nt,var2d,var_block) - implicit none - logical, intent(in) :: to - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(inout) :: var_block(:) - real(kind=kind_phys), intent(inout) :: var2d(:,:,:) - - if(to) then - call copy_to_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - else - call copy_from_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - end if - end subroutine GFS_data_transfer_2d_phys2phys - - pure subroutine GFS_data_transfer_3d_phys2phys(to,ii1,jj1,isc,jsc,nt,var3d,var_block) - implicit none - logical, intent(in) :: to - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(inout) :: var_block(:,:) - real(kind=kind_phys), intent(inout) :: var3d(:,:,:,:) - - if(to) then - call copy_to_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - else - call copy_from_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - endif - end subroutine GFS_data_transfer_3d_phys2phys - - pure subroutine GFS_data_transfer_3d_slice_phys2phys(to,ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) - implicit none - logical, intent(in) :: to - integer, intent(in) :: ii1(:), jj1(:), isc, jsc, k1, k2 - integer, intent(inout) :: nt - real(kind=kind_phys), intent(inout) :: var_block(:,:) - real(kind=kind_phys), intent(inout) :: var3d(:,:,:,:) - - if(to) then - call copy_to_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) - else - call copy_from_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) - endif - end subroutine GFS_data_transfer_3d_slice_phys2phys - - pure subroutine GFS_data_transfer_2d_int2phys(to,ii1,jj1,isc,jsc,nt,var2d,var_block) - implicit none - logical, intent(in) :: to - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - integer, intent(inout) :: var_block(:) - real(kind=kind_phys), intent(inout) :: var2d(:,:,:) - - if(to) then - call copy_to_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - else - call copy_from_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) - endif - end subroutine GFS_data_transfer_2d_int2phys - - pure subroutine GFS_data_transfer_3d_int2phys(to,ii1,jj1,isc,jsc,nt,var3d,var_block) - implicit none - logical, intent(in) :: to - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - integer, intent(inout) :: var_block(:,:) - real(kind=kind_phys), intent(inout) :: var3d(:,:,:,:) - - if(to) then - call copy_to_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - else - call copy_from_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - endif - end subroutine GFS_data_transfer_3d_int2phys - - pure subroutine GFS_Data_transfer_2d_stack_phys2phys(to,ii1,jj1,isc,jsc,nt,var3d,var_block) - ! For copying phy_f2d and phy_fctd - implicit none - logical, intent(in) :: to - integer, intent(in) :: ii1(:), jj1(:), isc, jsc - integer, intent(inout) :: nt - real(kind=kind_phys), intent(inout) :: var_block(:,:) - real(kind=kind_phys), intent(inout) :: var3d(:,:,:) - integer ix, k - - if(to) then - call copy_to_GFS_data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - else - call copy_from_GFS_data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) - end if - end subroutine GFS_Data_transfer_2d_stack_phys2phys - - subroutine create_2d_field_and_add_to_bundle(temp_r2d, field_name, outputfile, grid, bundle) - - use esmf - - implicit none - - real(kind_phys), dimension(:,:), pointer, intent(in) :: temp_r2d - character(len=*), intent(in) :: field_name - character(len=*), intent(in) :: outputfile - type(ESMF_Grid), intent(in) :: grid - type(ESMF_FieldBundle), intent(inout) :: bundle - - type(ESMF_Field) :: field - - integer :: rc, i - - field = ESMF_FieldCreate(grid, temp_r2d, datacopyflag=ESMF_DATACOPY_REFERENCE, & - name=trim(field_name), indexFlag=ESMF_INDEX_DELOCAL, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU,line=__LINE__, file=__FILE__)) & - call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", name='output_file', value=trim(outputfile), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - call ESMF_FieldBundleAdd(bundle, (/field/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !>@brief copies from the ix-indexed var_block to the 2d x-y real(kind_phys) var2d array + pure subroutine copy_from_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(in) :: var_block(:) + real(kind=kind_phys), intent(out) :: var2d(:,:,:) + integer ix + + nt=nt+1 + do ix=1,size(var_block) + var2d(ii1(ix),jj1(ix),nt) = var_block(ix) + enddo + end subroutine copy_from_GFS_Data_2d_phys2phys + + !>@brief copies from the ix-k-indexed var_block to the 3d x-y-z real(kind_phys) var3d array + pure subroutine copy_from_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(in) :: var_block(:,:) + real(kind=kind_phys), intent(out) :: var3d(:,:,:,:) + integer ix, k + + nt=nt+1 + do k=lbound(var_block,2),ubound(var_block,2) + do ix=1,size(var_block,1) + var3d(ii1(ix),jj1(ix),k,nt) = var_block(ix,k) + enddo + enddo + end subroutine copy_from_GFS_Data_3d_phys2phys + + !>@brief copies from the ix-k-indexed var_block to the 3d x-y-z integer var2d array + pure subroutine copy_from_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc, var_block(:) + integer, intent(inout) :: nt + real(kind=kind_phys), intent(out) :: var2d(:,:,:) + integer ix + + nt=nt+1 + do ix=1,size(var_block) + var2d(ii1(ix),jj1(ix),nt) = var_block(ix) + enddo + end subroutine copy_from_GFS_Data_2d_int2phys + + !>@brief copies a range of levels from the ix-k-indexed var_block to the x-y real(kind_phys) var3d array + pure subroutine copy_from_GFS_Data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + ! For copying phy_f2d and phy_fctd + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(in) :: var_block(:,:) + real(kind=kind_phys), intent(out) :: var3d(:,:,:) + integer ix, k + + nt=nt+1 + do k=lbound(var_block,2),ubound(var_block,2) + do ix=1,size(var_block,1) + var3d(ii1(ix),jj1(ix),nt) = var_block(ix,k) + enddo + enddo + end subroutine copy_from_GFS_Data_2d_stack_phys2phys + + !>@brief copies from the ix-k-indexed var_block to the x-y integer var3d array + pure subroutine copy_from_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), var_block(:,:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(out) :: var3d(:,:,:,:) + integer ix, k + + nt=nt+1 + do k=lbound(var_block,2),ubound(var_block,2) + do ix=1,size(var_block,1) + var3d(ii1(ix),jj1(ix),k,nt) = real(var_block(ix,k),kind_phys) + enddo + enddo + end subroutine copy_from_GFS_Data_3d_int2phys + + !>@brief copies a range of levels from from the ix-k-indexed var_block to the x-y-z real(kind_phys) var3d array + pure subroutine copy_from_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc, k1, k2 + integer, intent(inout) :: nt + real(kind=kind_phys), intent(in) :: var_block(:,:) + real(kind=kind_phys), intent(out) :: var3d(:,:,:,:) + integer ix, k + + nt=nt+1 + do k=k1,k2 + do ix=1,size(var_block,1) + var3d(ii1(ix),jj1(ix),k,nt) = var_block(ix,k) + enddo + enddo + end subroutine copy_from_GFS_Data_3d_slice_phys2phys + + !>@brief copies from x-y real(kind_phys) var2d array to the ix-indexed var_block array + pure subroutine copy_to_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(out) :: var_block(:) + real(kind=kind_phys), intent(in) :: var2d(:,:,:) + integer ix + + nt=nt+1 + do ix=1,size(var_block) + var_block(ix) = var2d(ii1(ix),jj1(ix),nt) + enddo + end subroutine copy_to_GFS_Data_2d_phys2phys + + !>@brief copies from x-y-z real(kind_phys) var3d array to the ix-k-indexed var_block array + pure subroutine copy_to_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(out) :: var_block(:,:) + real(kind=kind_phys), intent(in) :: var3d(:,:,:,:) + integer ix, k + + nt=nt+1 + do k=lbound(var_block,2),ubound(var_block,2) + do ix=1,size(var_block,1) + var_block(ix,k) = var3d(ii1(ix),jj1(ix),k,nt) + enddo + enddo + end subroutine copy_to_GFS_Data_3d_phys2phys + + !>@brief copies from x-y-z real(kind_phys) var3d array to the ix-k-indexed var_block array + pure subroutine copy_to_GFS_Data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + ! For copying phy_f2d and phy_fctd + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(out) :: var_block(:,:) + real(kind=kind_phys), intent(in) :: var3d(:,:,:) + integer ix, k + + nt=nt+1 + do k=lbound(var_block,2),ubound(var_block,2) + do ix=1,size(var_block,1) + var_block(ix,k) = var3d(ii1(ix),jj1(ix),nt) + enddo + enddo + end subroutine copy_to_GFS_Data_2d_stack_phys2phys + + !>@brief copies a range of levels from the x-y-z real(kind_phys) var3d array to the ix-k-indexed var_block array + pure subroutine copy_to_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc, k1, k2 + integer, intent(inout) :: nt + real(kind=kind_phys), intent(out) :: var_block(:,:) + real(kind=kind_phys), intent(in) :: var3d(:,:,:,:) + integer ix, k + + nt=nt+1 + do k=k1,k2 + do ix=1,size(var_block,1) + var_block(ix,k) = var3d(ii1(ix),jj1(ix),k,nt) + enddo + enddo + end subroutine copy_to_GFS_Data_3d_slice_phys2phys + + !>@brief copies from x-y integer var2d array to the ix-indexed var_block array + pure subroutine copy_to_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + integer, intent(out) :: var_block(:) + real(kind=kind_phys), intent(in) :: var2d(:,:,:) + integer ix + + nt=nt+1 + do ix=1,size(var_block) + var_block(ix) = int(var2d(ii1(ix),jj1(ix),nt)) + enddo + end subroutine copy_to_GFS_Data_2d_int2phys + + !>@brief copies from x-y-z integer var3d array to the ix-k-indexed var_block array + pure subroutine copy_to_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + implicit none + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + integer, intent(out) :: var_block(:,:) + real(kind=kind_phys), intent(in) :: var3d(:,:,:,:) + integer ix + + nt=nt+1 + do ix=1,size(var_block,1) + var_block(ix,:) = int(var3d(ii1(ix),jj1(ix),:,nt)) + enddo + end subroutine copy_to_GFS_Data_3d_int2phys + + !>@brief copies between the ix-indexed var_block array and x-y real(kind_phys) var2d array. + !> \section GFS_data_transfer_2d_phys2phys subroutine from the GFS_data_transfer interface + !! This is a wrapper around copy_to_GFS_Data and copy_from_GFS_Data routines. + !! If to=true, then data is copied to var_block (the GFS_Data structures) but if + !! to=false, it is copied from the var_block arrays. This allows the same subroutine + !! to both read and write, preventing error-prone code duplication. + pure subroutine GFS_data_transfer_2d_phys2phys(to,ii1,jj1,isc,jsc,nt,var2d,var_block) + implicit none + logical, intent(in) :: to + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(inout) :: var_block(:) + real(kind=kind_phys), intent(inout) :: var2d(:,:,:) + + if(to) then + call copy_to_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + else + call copy_from_GFS_Data_2d_phys2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + end if + end subroutine GFS_data_transfer_2d_phys2phys + + !>@brief copies between the ix-k-indexed var_block array and x-y-z real(kind_phys) var3d array. + !> \section GFS_data_transfer_3d_phys2phys subroutine from the GFS_data_transfer interface + !! This is a wrapper around copy_to_GFS_Data and copy_from_GFS_Data routines. + !! If to=true, then data is copied to var_block (the GFS_Data structures) but if + !! to=false, it is copied from the var_block arrays. This allows the same subroutine + !! to both read and write, preventing error-prone code duplication. + pure subroutine GFS_data_transfer_3d_phys2phys(to,ii1,jj1,isc,jsc,nt,var3d,var_block) + implicit none + logical, intent(in) :: to + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(inout) :: var_block(:,:) + real(kind=kind_phys), intent(inout) :: var3d(:,:,:,:) + + if(to) then + call copy_to_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + else + call copy_from_GFS_Data_3d_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + endif + end subroutine GFS_data_transfer_3d_phys2phys + + !>@brief copies a range of levels between the ix-k-indexed var_block array and x-y-z real(kind_phys) var3d array. + !> \section GFS_data_transfer_3d_slice_phys2phys subroutine from the GFS_data_transfer interface + !! This is a wrapper around copy_to_GFS_Data and copy_from_GFS_Data routines. + !! If to=true, then data is copied to var_block (the GFS_Data structures) but if + !! to=false, it is copied from the var_block arrays. This allows the same subroutine + !! to both read and write, preventing error-prone code duplication. + pure subroutine GFS_data_transfer_3d_slice_phys2phys(to,ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) + implicit none + logical, intent(in) :: to + integer, intent(in) :: ii1(:), jj1(:), isc, jsc, k1, k2 + integer, intent(inout) :: nt + real(kind=kind_phys), intent(inout) :: var_block(:,:) + real(kind=kind_phys), intent(inout) :: var3d(:,:,:,:) + + if(to) then + call copy_to_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) + else + call copy_from_GFS_Data_3d_slice_phys2phys(ii1,jj1,isc,jsc,nt,k1,k2,var3d,var_block) + endif + end subroutine GFS_data_transfer_3d_slice_phys2phys + + !>@brief copies between the ix-indexed var_block array and x-y integer var2d array. + !> \section GFS_data_transfer_2d_int2phys subroutine from the GFS_data_transfer interface + !! This is a wrapper around copy_to_GFS_Data and copy_from_GFS_Data routines. + !! If to=true, then data is copied to var_block (the GFS_Data structures) but if + !! to=false, it is copied from the var_block arrays. This allows the same subroutine + !! to both read and write, preventing error-prone code duplication. + pure subroutine GFS_data_transfer_2d_int2phys(to,ii1,jj1,isc,jsc,nt,var2d,var_block) + implicit none + logical, intent(in) :: to + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + integer, intent(inout) :: var_block(:) + real(kind=kind_phys), intent(inout) :: var2d(:,:,:) + + if(to) then + call copy_to_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + else + call copy_from_GFS_Data_2d_int2phys(ii1,jj1,isc,jsc,nt,var2d,var_block) + endif + end subroutine GFS_data_transfer_2d_int2phys + + !>@brief copies between the ix-k-indexed var_block array and x-y-z integer var3d array. + !> \section GFS_data_transfer_3d_int2phys subroutine from the GFS_data_transfer interface + !! This is a wrapper around copy_to_GFS_Data and copy_from_GFS_Data routines. + !! If to=true, then data is copied to var_block (the GFS_Data structures) but if + !! to=false, it is copied from the var_block arrays. This allows the same subroutine + !! to both read and write, preventing error-prone code duplication. + pure subroutine GFS_data_transfer_3d_int2phys(to,ii1,jj1,isc,jsc,nt,var3d,var_block) + implicit none + logical, intent(in) :: to + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + integer, intent(inout) :: var_block(:,:) + real(kind=kind_phys), intent(inout) :: var3d(:,:,:,:) + + if(to) then + call copy_to_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + else + call copy_from_GFS_Data_3d_int2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + endif + end subroutine GFS_data_transfer_3d_int2phys + + !>@brief copies a range of levels between the ix-k-indexed var_block array and x-y-z real(kind_phys) var3d array. + !> \section GFS_Data_transfer_2d_stack_phys2phys subroutine from the GFS_data_transfer interface + !! This is a wrapper around copy_to_GFS_Data and copy_from_GFS_Data routines. + !! If to=true, then data is copied to var_block (the GFS_Data structures) but if + !! to=false, it is copied from the var_block arrays. This allows the same subroutine + !! to both read and write, preventing error-prone code duplication. + pure subroutine GFS_Data_transfer_2d_stack_phys2phys(to,ii1,jj1,isc,jsc,nt,var3d,var_block) + ! For copying phy_f2d and phy_fctd + implicit none + logical, intent(in) :: to + integer, intent(in) :: ii1(:), jj1(:), isc, jsc + integer, intent(inout) :: nt + real(kind=kind_phys), intent(inout) :: var_block(:,:) + real(kind=kind_phys), intent(inout) :: var3d(:,:,:) + integer ix, k + + if(to) then + call copy_to_GFS_data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + else + call copy_from_GFS_data_2d_stack_phys2phys(ii1,jj1,isc,jsc,nt,var3d,var_block) + end if + end subroutine GFS_Data_transfer_2d_stack_phys2phys + + !>@brief adds a 2D restart array to an ESMF bundle for quilting restarts. + subroutine create_2d_field_and_add_to_bundle(temp_r2d, field_name, outputfile, grid, bundle) + + use esmf + + implicit none + + real(kind_phys), dimension(:,:), pointer, intent(in) :: temp_r2d + character(len=*), intent(in) :: field_name + character(len=*), intent(in) :: outputfile + type(ESMF_Grid), intent(in) :: grid + type(ESMF_FieldBundle), intent(inout) :: bundle + + type(ESMF_Field) :: field + + integer :: rc, i + + field = ESMF_FieldCreate(grid, temp_r2d, datacopyflag=ESMF_DATACOPY_REFERENCE, & + name=trim(field_name), indexFlag=ESMF_INDEX_DELOCAL, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU,line=__LINE__, file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", name='output_file', value=trim(outputfile), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_FieldBundleAdd(bundle, (/field/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) end subroutine create_2d_field_and_add_to_bundle - subroutine create_3d_field_and_add_to_bundle(temp_r3d, field_name, axis_name, axis_values, outputfile, grid, bundle) + !>@brief adds a 3D restart array and its vertical axis to an ESMF bundle for quilting restarts. + subroutine create_3d_field_and_add_to_bundle(temp_r3d, field_name, axis_name, axis_values, outputfile, grid, bundle) - use esmf + use esmf - implicit none + implicit none - real(kind_phys), dimension(:,:,:), pointer, intent(in) :: temp_r3d - character(len=*), intent(in) :: field_name - character(len=*), intent(in) :: axis_name - real(kind_phys), dimension(:), intent(in) :: axis_values - character(len=*), intent(in) :: outputfile - type(ESMF_Grid), intent(in) :: grid - type(ESMF_FieldBundle), intent(inout) :: bundle + real(kind_phys), dimension(:,:,:), pointer, intent(in) :: temp_r3d + character(len=*), intent(in) :: field_name + character(len=*), intent(in) :: axis_name + real(kind_phys), dimension(:), intent(in) :: axis_values + character(len=*), intent(in) :: outputfile + type(ESMF_Grid), intent(in) :: grid + type(ESMF_FieldBundle), intent(inout) :: bundle - type(ESMF_Field) :: field + type(ESMF_Field) :: field - integer :: rc, i + integer :: rc, i - field = ESMF_FieldCreate(grid, temp_r3d, datacopyflag=ESMF_DATACOPY_REFERENCE, & - name=trim(field_name), indexFlag=ESMF_INDEX_DELOCAL, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU,line=__LINE__, file=__FILE__)) & - call ESMF_Finalize(endflag=ESMF_END_ABORT) + field = ESMF_FieldCreate(grid, temp_r3d, datacopyflag=ESMF_DATACOPY_REFERENCE, & + name=trim(field_name), indexFlag=ESMF_INDEX_DELOCAL, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU,line=__LINE__, file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", name='output_file', value=trim(outputfile), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", name='output_file', value=trim(outputfile), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) - call add_zaxis_to_field(field, axis_name, axis_values) + call add_zaxis_to_field(field, axis_name, axis_values) - call ESMF_FieldBundleAdd(bundle, (/field/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_FieldBundleAdd(bundle, (/field/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT) end subroutine create_3d_field_and_add_to_bundle - subroutine add_zaxis_to_field(field, axis_name, axis_values) + !>@brief adds a vertical axis to an ESMF bundle for quilting restarts. + subroutine add_zaxis_to_field(field, axis_name, axis_values) - use esmf + use esmf - implicit none + implicit none - type(ESMF_Field), intent(inout) :: field - character(len=*), intent(in) :: axis_name - real(kind_phys), dimension(:), intent(in) :: axis_values + type(ESMF_Field), intent(inout) :: field + character(len=*), intent(in) :: axis_name + real(kind_phys), dimension(:), intent(in) :: axis_values - integer :: rc + integer :: rc - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & - name="ESMF:ungridded_dim_labels", valueList=(/trim(axis_name)/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3", & + name="ESMF:ungridded_dim_labels", valueList=(/trim(axis_name)/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3-dim", & - name=trim(axis_name), valueList=axis_values, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3-dim", & + name=trim(axis_name), valueList=axis_values, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3-dim", & - name=trim(axis_name)//"cartesian_axis", value="Z", rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + call ESMF_AttributeSet(field, convention="NetCDF", purpose="FV3-dim", & + name=trim(axis_name)//"cartesian_axis", value="Z", rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - end subroutine add_zaxis_to_field + end subroutine add_zaxis_to_field end module fv3atm_common_io +!> @} diff --git a/io/fv3atm_history_io.F90 b/io/fv3atm_history_io.F90 index 1504e6971..7c73fe296 100644 --- a/io/fv3atm_history_io.F90 +++ b/io/fv3atm_history_io.F90 @@ -1,17 +1,9 @@ +!> \file fv3atm_history_io.F90 +!! This file defines routines used to output atmosphere diagnostic +!! (history) data from the physics and surface fields, both for quilt +!! and non-quilt output. module fv3atm_history_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 - ! atmospheric time tendencies for use by other components, namely - ! the atmospheric dynamical core. - ! - ! NOTE: This module currently supports only the operational GFS - ! parameterizations as of September 2015. Further development - ! is needed to support the full suite of physical - ! parameterizations present in the GFS physics package. - !----------------------------------------------------------------------- ! !--- FMS/GFDL modules use block_control_mod, only: block_control_type @@ -40,13 +32,20 @@ module fv3atm_history_io_mod public fv_phys_bundle_setup #endif + !>\defgroup fv3atm_history_io_mod FV3ATM History I/O Module + !> @{ + + !>@ The maximum allowed number of diagnostic fields that can be defined in any given model run. + !! This does not include rrfs-sd or clm lake, which have their own data structures. integer, parameter, public :: DIAG_SIZE = 800 + real, parameter :: missing_value = 9.99e20_kind_phys real, parameter :: stndrd_atmos_ps = 101325.0_kind_phys real, parameter :: stndrd_atmos_lapse = 0.0065_kind_phys real, parameter :: drythresh = 1.e-4_kind_phys real, parameter :: zero = 0.0_kind_phys, one = 1.0_kind_phys + !>@ Storage type for temporary data during output of diagnostic (history) files type history_type integer :: tot_diag_idx = 0 @@ -81,22 +80,19 @@ module fv3atm_history_io_mod #endif end type history_type + !>@ This shared_history_data instance of history_type is shared between all calls to public module subroutines. type(history_type) :: shared_history_data CONTAINS - !------------------------------------------------------------------------- - !--- gfdl_diag_register --- - !------------------------------------------------------------------------- - ! creates and populates a data type which is then used to "register" - ! GFS physics diagnostic variables with the GFDL FMS diagnostic manager. - ! includes short & long names, units, conversion factors, etc. - ! there is no copying of data, but instead a clever use of pointers. - ! calls a GFDL FMS routine to register diagnositcs and compare against - ! the diag_table to determine what variables are to be output. - ! - ! calls: register_diag_field - !------------------------------------------------------------------------- + !>@brief Registers diagnostic variables with the FMS diagnostic manager. + !> \section fv3atm_diag_register subroutine + !! Creates and populates a data type which is then used to "register" + !! diagnostic variables with the GFDL FMS diagnostic manager. + !! includes short & long names, units, conversion factors, etc. + !! there is no copying of data, but instead a clever use of pointers. + !! calls a GFDL FMS routine to register diagnositcs and compare against + !! the diag_table to determine what variables are to be output. subroutine fv3atm_diag_register(Diag, Time, Atm_block, Model, xlon, xlat, axes) use physcons, only: con_g implicit none @@ -112,14 +108,10 @@ subroutine fv3atm_diag_register(Diag, Time, Atm_block, Model, xlon, xlat, axes) call shared_history_data%register(Diag, Time, Atm_block, Model, xlon, xlat, axes) end subroutine fv3atm_diag_register - !------------------------------------------------------------------------- - !--- gfs_diag_output --- - !------------------------------------------------------------------------- - ! routine to transfer the diagnostic data to the gfdl fms diagnostic - ! manager for eventual output to the history files. - ! - ! calls: send_data - !------------------------------------------------------------------------- + !>@brief Transfers diagnostic data to the FMS diagnostic manager + !> \section fv3atm_diag_output subroutine + !! This routine transfers diagnostic data to the FMS diagnostic + !! manager for eventual output to the history files. subroutine fv3atm_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & dt, time_int, time_intfull, time_radsw, time_radlw) !--- subroutine interface variable definitions @@ -139,6 +131,11 @@ subroutine fv3atm_diag_output(time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & end subroutine fv3atm_diag_output #ifdef use_WRTCOMP + !>@brief Sets up the ESMF bundle to use for quilt diagnostic output + !> \section fv_phys_bundle_setup subroutine + !! This part of the write component (quilt) sets up the ESMF bundles + !! to use for writing diagnostic output. It is only defined when the + !! write component is enabled at compile time. subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nbdlphys, rc) ! !------------------------------------------------------------- @@ -161,11 +158,11 @@ subroutine fv_phys_bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nb call shared_history_data%bundle_setup(Diag, axes, phys_bundle, fcst_grid, quilting, nbdlphys, rc) end subroutine fv_phys_bundle_setup #endif - ! - !--------------------------------------------------------------------- - !*** Private subroutines - !--------------------------------------------------------------------- - ! + + !>@brief Private implementation of fv3atm_diag_register. Do not call directly. + !> \section history_type%register procedure + !! This is the history_type%register procedure, which provides the internal + !! implementation of fv3atm_diag_register. Do not call this directly. subroutine history_type_register(hist, Diag, Time, Atm_block, Model, xlon, xlat, axes) use physcons, only: con_g implicit none @@ -273,8 +270,11 @@ subroutine history_type_register(hist, Diag, Time, Atm_block, Model, xlon, xlat, end subroutine history_type_register - !------------------------------------------------------------------------- - + !>@brief Internal implementation of fv3atm_diag_output + !> \section history_type%output procedure + !! This is history_type%output, which provides the internal + !! implementation of the public fv3atm_diag_output routine. Never + !! call this directly. subroutine history_type_output(hist, time, diag, atm_block, nx, ny, levs, ntcw, ntoz, & dt, time_int, time_intfull, time_radsw, time_radlw) !--- subroutine interface variable definitions @@ -473,8 +473,11 @@ subroutine history_type_output(hist, time, diag, atm_block, nx, ny, levs, ntcw, endif has_id end do history_loop end subroutine history_type_output - ! - !------------------------------------------------------------------------- + + !>@brief Part of the internal implementation of history_type_output (history_type%output) + !> \section history_type%store_data procedure + !! This routine copies data from an x-y array to internal buffers for later output. + !! Never call this subroutine directly; call fv3atm_diag_output instead. subroutine history_type_store_data(hist,id, work, Time, idx, intpl_method, fldname) implicit none class(history_type) :: hist @@ -558,9 +561,11 @@ subroutine history_type_store_data(hist,id, work, Time, idx, intpl_method, fldna endif if_has_id ! end subroutine history_type_store_data - ! - !------------------------------------------------------------------------- - ! + + !>@brief Part of the internal implementation of history_type_output (history_type%output) + !> \section history_type%store_data3D procedure + !! This routine copies data from an x-y-z array to internal buffers for later output. + !! Never call this subroutine directly; call fv3atm_diag_output instead. subroutine history_type_store_data3D(hist, id, work, Time, idx, intpl_method, fldname) implicit none class(history_type) :: hist @@ -665,10 +670,13 @@ subroutine history_type_store_data3D(hist, id, work, Time, idx, intpl_method, fl endif ! end subroutine history_type_store_data3D - ! - !------------------------------------------------------------------------- - ! + #ifdef use_WRTCOMP + !>@brief Sets up the ESMF bundle to use for quilt diagnostic output + !> \section history_type%bundle_setup procedure + !! This part of the write component (quilt) sets up the ESMF bundles + !! to use for writing diagnostic output. It is only defined when the + !! write component is enabled at compile time. subroutine history_type_bundle_setup(hist, Diag, axes, phys_bundle, fcst_grid, quilting, nbdlphys, rc) ! set esmf bundle for phys output fields @@ -936,8 +944,12 @@ subroutine history_type_bundle_setup(hist, Diag, axes, phys_bundle, fcst_grid, q nullify(hist%all_axes) end subroutine history_type_bundle_setup - ! - !----------------------------------------------------------------------------------------- + + !>@brief Adds one field to an ESMF field bundle for later output. Internal subroutine; do not call this directly. + !> \section history_type%add_field_to_phybundle procedure + !! This is part of the internal implementation of history_type_bundle_setup (history_type%bundle_setup). + !! It sets attributes for and logs information about a single ESMF field. Do not call this subroutine directly. + !! Call fv_phys_bundle_setup instead. subroutine history_type_add_field_to_phybundle(hist,var_name,long_name,units,cell_methods, axes,phys_grid, & kstt,phys_bundle,output_file,intpl_method,range,l2dvector,rcd) ! @@ -1130,8 +1142,15 @@ subroutine history_type_add_field_to_phybundle(hist,var_name,long_name,units,cel call ESMF_LogWrite('phys field add to fieldbundle '//trim(var_name), ESMF_LOGMSG_INFO, rc=rc) end subroutine history_type_add_field_to_phybundle - ! - ! + + !>@brief Private subroutine to search a field list for a specific name. + !> \section history_type%find_output_name procedure + !! Searches the GFS_Diagnostic-generated field list for a + !! specific name and retrieves the name that should be used for + !! outputting the variable. This is part of the internal + !! implementation of history_type_bundle_setup + !! (history_type%bundle_setup) and should not be called + !! directly. Call fv_phys_bundle_setup instead. subroutine history_type_find_output_name(hist,module_name,field_name,output_name) implicit none class(history_type) :: hist @@ -1153,7 +1172,8 @@ subroutine history_type_find_output_name(hist,module_name,field_name,output_name endif enddo if(output_name == '') then - print *,'Error, cant find out put name' +19 format("Error: can't find output name for model field ",'"',A,'"') + print 19,trim(field_name) endif end subroutine history_type_find_output_name @@ -1161,3 +1181,4 @@ end subroutine history_type_find_output_name !------------------------------------------------------------------------- end module fv3atm_history_io_mod +!> @} diff --git a/io/fv3atm_oro_io.F90 b/io/fv3atm_oro_io.F90 index 7cd60301e..493cfd4c4 100644 --- a/io/fv3atm_oro_io.F90 +++ b/io/fv3atm_oro_io.F90 @@ -1,3 +1,5 @@ +!> \file fv3atm_oro_io.F90 +!! This file defines routines to read orography files for the fv3atm. module fv3atm_oro_io use block_control_mod, only: block_control_type @@ -12,6 +14,9 @@ module fv3atm_oro_io public :: Oro_io_data_type, Oro_io_register, Oro_io_copy, Oro_io_final public :: Oro_scale_io_data_type, Oro_scale_io_register, Oro_scale_io_copy, Oro_scale_io_final + !>\defgroup fv3atm_oro_io FV3ATM Orography I/O Module + !> @{ + !>@ Storage of working arrays for reading orography data. type Oro_io_data_type character(len=32), pointer, private, dimension(:) :: name2 => null() real(kind=kind_phys), pointer, private, dimension(:,:,:) :: var2 => null() @@ -23,6 +28,7 @@ module fv3atm_oro_io final :: Oro_io_final end type Oro_io_data_type + !>@ Storage of working arrays for reading large-scale and small-scale orography data for gravity wave drag schemes. type Oro_scale_io_data_type character(len=32), pointer, private, dimension(:) :: name => null() real(kind=kind_phys), pointer, private, dimension(:,:,:) :: var => null() @@ -32,11 +38,19 @@ module fv3atm_oro_io final :: Oro_scale_io_final end type Oro_scale_io_data_type + !>@ Number of two-dimensional orography fields (excluding large- and small-scale) + integer, parameter :: nvar_oro_2d = 19 + + !>@ Number of large-scale and small-scale orography fields integer, parameter :: nvar_oro_scale = 10 - integer, parameter :: nvar_o2 = 19 contains + !>@brief Registers axes and fields for non-quilt restart reading of non-scaled orography variables. + !> \section oro_io_data_type%register procedure + !! Calls FMS restart register functions for axes and + !! variables in the non-scaled orography data. The scaled data is + !! handled by another function. This includes both 2D and 3D fields. subroutine Oro_io_register(oro, Model, Oro_restart, Atm_block) implicit none class(Oro_io_data_type) :: oro @@ -69,8 +83,8 @@ subroutine Oro_io_register(oro, Model, Oro_restart, Atm_block) nvar_vegfr = Model%nvegcat nvar_soilfr = Model%nsoilcat - allocate(oro%name2(nvar_o2)) - allocate(oro%var2(nx,ny,nvar_o2)) + allocate(oro%name2(nvar_oro_2d)) + allocate(oro%var2(nx,ny,nvar_oro_2d)) allocate(oro%var3v(nx,ny,nvar_vegfr)) allocate(oro%var3s(nx,ny,nvar_soilfr)) @@ -119,6 +133,10 @@ subroutine Oro_io_register(oro, Model, Oro_restart, Atm_block) end subroutine Oro_io_register + !>@brief Copies orography data from temporary arrays back to Sfcprop grid arrays. + !> \section oro_io_data_type%copy procedure + !! After reading the restart, data is on temporary arrays with x-y data storage. + !! This subroutine copies the x-y fields to Sfcprop's blocked grid storage arrays. subroutine Oro_io_copy(oro, Model, Sfcprop, Atm_block) implicit none class(Oro_io_data_type) :: oro @@ -197,6 +215,7 @@ subroutine Oro_io_copy(oro, Model, Sfcprop, Atm_block) end subroutine Oro_io_copy + !>@brief Destructor for Oro_io_data_type subroutine Oro_io_final(oro) implicit none type(Oro_io_data_type) :: oro @@ -216,6 +235,11 @@ subroutine Oro_io_final(oro) #undef IF_ASSOC_DEALLOC_NULL end subroutine Oro_io_final + !>@brief Registers axes and fields for non-quilt restart reading of scaled orography variables. + !> \section Calls FMS restart register functions for axes and + !! variables in the large-scale or small-scale orography data. The + !! scaled data is handled by another function. Each scale needs its + !! own instance of oro_scale_io_data_type. subroutine Oro_scale_io_register(oro_scale, Model, Oro_scale_restart, Atm_block) implicit none class(Oro_scale_io_data_type) :: oro_scale @@ -263,6 +287,10 @@ subroutine Oro_scale_io_register(oro_scale, Model, Oro_scale_restart, Atm_block) enddo end subroutine Oro_scale_io_register + !>@brief Copies scaled orography data from temporary arrays back to Sfcprop grid arrays. + !> \section Oro_scale_io_data_type%copy procedure + !! After reading the restart, data is on temporary arrays with x-y data storage. + !! This subroutine copies the x-y fields to Sfcprop's blocked grid storage arrays. subroutine Oro_scale_io_copy(oro_scale, Sfcprop, Atm_block, first_index) implicit none class(Oro_scale_io_data_type) :: oro_scale @@ -285,6 +313,7 @@ subroutine Oro_scale_io_copy(oro_scale, Sfcprop, Atm_block, first_index) enddo end subroutine Oro_scale_io_copy + !>@brief Oro_scale_io_data_type destructor subroutine Oro_scale_io_final(oro_scale) implicit none type(Oro_scale_io_data_type) :: oro_scale @@ -301,3 +330,4 @@ subroutine Oro_scale_io_final(oro_scale) #undef IF_ASSOC_DEALLOC_NULL end subroutine Oro_scale_io_final end module fv3atm_oro_io +!> @} diff --git a/io/fv3atm_restart_io.F90 b/io/fv3atm_restart_io.F90 index f99bc3c8e..d5cfb9734 100644 --- a/io/fv3atm_restart_io.F90 +++ b/io/fv3atm_restart_io.F90 @@ -1,3 +1,7 @@ +!> \file fv3atm_restart_io.F90 +!! This file contains the restart reading and writing code, for quilt and non-quilt +!! of the Sfcprop and physics data. + module fv3atm_restart_io_mod use block_control_mod, only: block_control_type @@ -31,6 +35,10 @@ module fv3atm_restart_io_mod public fv_sfc_restart_output public fv_sfc_restart_bundle_setup + !>\defgroup fv3atm_restart_io_mod module + !> @{ + + !>@Internal storage for reading and writing physics restart files. type phy_data_type real(kind=kind_phys), pointer, dimension(:,:,:) :: var2 => null() real(kind=kind_phys), pointer, dimension(:,:,:,:) :: var3 => null() @@ -44,27 +52,50 @@ module fv3atm_restart_io_mod end type phy_data_type !--- GFDL filenames + + !>@ Filename template for orography data. FMS may add grid and tile information to the name character(len=32), parameter :: fn_oro = 'oro_data.nc' + + !>@ Filename template for gravity wave drag large-scale orography data. FMS may add grid and tile information to the name character(len=32), parameter :: fn_oro_ls = 'oro_data_ls.nc' + + !>@ Filename template for gravity wave drag small-scale orography data. FMS may add grid and tile information to the name character(len=32), parameter :: fn_oro_ss = 'oro_data_ss.nc' + + !>@ Filename template for surface data that doesn't fall under other categories. FMS may add grid and tile information to the name character(len=32), parameter :: fn_srf = 'sfc_data.nc' + + !>@ Filename template for physics diagnostic data. FMS may add grid and tile information to the name character(len=32), parameter :: fn_phy = 'phy_data.nc' + + !>@ Filename template for monthly dust data for RRFS_SD. FMS may add grid and tile information to the name character(len=32), parameter :: fn_dust12m= 'dust12m_data.nc' + + !>@ Filename template for RRFS-SD emissions data. FMS may add grid and tile information to the name character(len=32), parameter :: fn_emi = 'emi_data.nc' + + !>@ Filename template for RRFS-SD smoke data. FMS may add grid and tile information to the name character(len=32), parameter :: fn_rrfssd = 'SMOKE_RRFS_data.nc' real(kind_phys), parameter:: zero = 0.0, one = 1.0 + !>@ Instance of phy_data_type for quilt output of physics diagnostic data type(phy_data_type) :: phy_quilt + + !>@ Instance of clm_lake_data_type for quilt output of CLM Lake model restart data type(clm_lake_data_type) :: clm_lake_quilt + + !>@ Instance of Sfc_io_data_type for quilt output of surface restart data type(Sfc_io_data_type) :: sfc_quilt + + !>@ Instance of rrfs_sd_state_type for quilt output of RRFS-SD scheme restart data type(rrfs_sd_state_type) :: rrfs_sd_quilt contains - !-------------------- - ! fv3atm_restart_read - !-------------------- + !>@brief Reads physics and surface fields. + !> \section fv3atm_restart_read subroutine + !! Calls sfc_prop_restart_read and phys_restart_read to read all surface and physics restart files. subroutine fv3atm_restart_read (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) implicit none type(GFS_data_type), intent(inout) :: GFS_Data(:) @@ -83,9 +114,11 @@ subroutine fv3atm_restart_read (GFS_Data, GFS_Restart, Atm_block, Model, fv_doma end subroutine fv3atm_restart_read - !--------------------- - ! fv3atm_restart_write - !--------------------- + !>@brief Writes surface and physics restart fields without using the write component (quilt). + !> \section fv3atm_restart_write subroutine + !! Calls sfc_prop_restart_write and phys_restart_write to write + !! surface and physics restart fields. This pauses the model to + !! write; it does not use the write component (quilt). subroutine fv3atm_restart_write (GFS_Data, GFS_Restart, Atm_block, Model, fv_domain, timestamp) implicit none type(GFS_data_type), intent(inout) :: GFS_Data(:) @@ -462,19 +495,12 @@ subroutine fv3atm_checksum (Model, GFS_Data, Atm_block) deallocate(temp3dlevsp1) end subroutine fv3atm_checksum - !---------------------------------------------------------------------- - ! sfc_prop_restart_read - !---------------------------------------------------------------------- - ! creates and populates a data type which is then used to "register" - ! restart variables with the GFDL FMS restart subsystem. - ! calls a GFDL FMS routine to restore the data from a restart file. - ! calculates sncovr if it is not present in the restart file. - ! - ! calls: register_restart_field, restart_state, free_restart - ! - ! opens: oro_data.tile?.nc, sfc_data.tile?.nc - ! - !---------------------------------------------------------------------- + !>@brief Reads surface, orography, CLM Lake, and RRFS-SD data. + !> \section sfc_prop_restart_read subroutine + !! Creates and populates a data type which is then used to "register" + !! restart variables with the FMS restart subsystem. + !! Calls an FMS routine to restore the data from a restart file. + !! Also calculates sncovr if it is not present in the restart file. subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_start, ignore_rst_cksum) use fv3atm_rrfs_sd_io implicit none @@ -674,17 +700,11 @@ subroutine sfc_prop_restart_read (Sfcprop, Atm_block, Model, fv_domain, warm_sta end subroutine sfc_prop_restart_read - - !---------------------------------------------------------------------- - ! sfc_prop_restart_write - !---------------------------------------------------------------------- - ! routine to write out GFS surface restarts via the GFDL FMS restart - ! subsystem. - ! takes an optional argument to append timestamps for intermediate - ! restarts. - ! - ! calls: register_restart_field, save_restart - !---------------------------------------------------------------------- + !>@brief Writes surface restart data without using the write component. + !> \section sfc_prop_restart_write procedure + !! Routine to write out GFS surface restarts via the FMS restart + !! subsystem. Takes an optional argument to append timestamps for intermediate + !! restarts. subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timestamp) use fv3atm_rrfs_sd_io implicit none @@ -772,19 +792,11 @@ subroutine sfc_prop_restart_write (Sfcprop, Atm_block, Model, fv_domain, timesta end subroutine sfc_prop_restart_write - !---------------------------------------------------------------------- - ! phys_restart_read - !---------------------------------------------------------------------- - ! creates and populates a data type which is then used to "register" - ! restart variables with the GFDL FMS restart subsystem. - ! calls a GFDL FMS routine to restore the data from a restart file. - ! calculates sncovr if it is not present in the restart file. - ! - ! calls: register_restart_field, restart_state, free_restart - ! - ! opens: phys_data.tile?.nc - ! - !---------------------------------------------------------------------- + !>@brief Reads the physics restart data. + !> \section phys_restart_read subroutine + !! Creates and populates a data type which is then used to "register" + !! restart variables with the GFDL FMS restart subsystem. + !! Calls a GFDL FMS routine to restore the data from a restart file. subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_rst_cksum) implicit none !--- interface variable definitions @@ -853,17 +865,11 @@ subroutine phys_restart_read (GFS_Restart, Atm_block, Model, fv_domain, ignore_r end subroutine phys_restart_read - - !---------------------------------------------------------------------- - ! phys_restart_write - !---------------------------------------------------------------------- - ! routine to write out GFS surface restarts via the GFDL FMS restart - ! subsystem. - ! takes an optional argument to append timestamps for intermediate - ! restarts. - ! - ! calls: register_restart_field, save_restart - !---------------------------------------------------------------------- + !>@brief Writes the physics restart file without using the write component + !> \section phys_restart_write subroutine + !! Routine to write out GFS surface restarts via the FMS restart + !! subsystem. Takes an optional argument to append timestamps for intermediate + !! restarts. subroutine phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timestamp) implicit none !--- interface variable definitions @@ -955,11 +961,10 @@ subroutine phys_restart_write (GFS_Restart, Atm_block, Model, fv_domain, timesta end subroutine phys_restart_write + !>@brief Allocates buffers and registers fields for a quilting (write component) restart. + !> \section fv3atm_restart_register subroutine + !! Allocates all data buffers and sets variable names for surface and physics restarts. subroutine fv3atm_restart_register (Sfcprop, GFS_restart, Atm_block, Model) - - ! this subroutine must allocate all data buffers and set the variable names - ! for both 'phy' and 'sfc' restart bundles - implicit none type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) @@ -987,6 +992,7 @@ subroutine fv3atm_restart_register (Sfcprop, GFS_restart, Atm_block, Model) end subroutine fv3atm_restart_register + !>@Copies physics restart fields from write component data structures to the model grid. subroutine fv_phy_restart_output(GFS_Restart, Atm_block) implicit none @@ -998,6 +1004,7 @@ subroutine fv_phy_restart_output(GFS_Restart, Atm_block) end subroutine fv_phy_restart_output + !>@Copies physics restart fields from the model grid to write component data structures subroutine fv_sfc_restart_output(Sfcprop, Atm_block, Model) !--- interface variable definitions implicit none @@ -1016,12 +1023,8 @@ subroutine fv_sfc_restart_output(Sfcprop, Atm_block, Model) end subroutine fv_sfc_restart_output + !>@ Creates the ESMF bundle for physics restart data subroutine fv_phy_restart_bundle_setup(bundle, grid, rc) - ! - !------------------------------------------------------------- - !*** set esmf bundle for phys restart fields - !------------------------------------------------------------ - ! use esmf implicit none @@ -1070,12 +1073,8 @@ subroutine fv_phy_restart_bundle_setup(bundle, grid, rc) end subroutine fv_phy_restart_bundle_setup + !>@ Creates the ESMF bundle for surface restart data subroutine fv_sfc_restart_bundle_setup(bundle, grid, Model, rc) - ! - !------------------------------------------------------------- - !*** set esmf bundle for sfc restart fields - !------------------------------------------------------------ - ! use esmf implicit none @@ -1114,6 +1113,11 @@ end subroutine fv_sfc_restart_bundle_setup ! !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + !>@brief Allocates and fills internal data structures for quilt or non-quilt physics restart I/O + !> \section phy_data_type%alloc procedure + !! Allocates the variable and variable name data structures in the phy_data_type. + !! Also, copies the GFS_Restart names to the phy_data_type arrays. + !! Do not call from outside this module; it is part of the internal implementation. logical function phy_data_alloc(phy, GFS_Restart, Atm_block) use fv3atm_common_io, only: get_nx_ny_from_atm implicit none @@ -1147,6 +1151,13 @@ logical function phy_data_alloc(phy, GFS_Restart, Atm_block) phy_data_alloc = .true. end function phy_data_alloc + !>@brief Copies data between the internal physics restart data structures and the model grid + !> \section phy_data_type%transfer_data procedure + !! Restart I/O stores data in temporary arrays while interfacing with ESMF or FMS. This procedure + !! copies between the temporary arrays and the model grid. The "reading" flag controls the + !! direction of the copy. For reading=.true., data is copied from the temporary arrays to the + !! model grid (during restart read). For reading=.false., data is copied from the model grid to + !! temporary arrays (for writing the restart). subroutine phy_data_transfer_data(phy, reading, GFS_Restart, Atm_block, Model) use mpp_mod, only: FATAL, mpp_error implicit none @@ -1247,6 +1258,7 @@ subroutine phy_data_transfer_data(phy, reading, GFS_Restart, Atm_block, Model) end subroutine phy_data_transfer_data + !>@ Destructor for phy_data_type subroutine phy_data_final(phy) implicit none type(phy_data_type) :: phy @@ -1267,3 +1279,4 @@ subroutine phy_data_final(phy) end subroutine phy_data_final end module fv3atm_restart_io_mod +!> @} diff --git a/io/fv3atm_rrfs_sd_io.F90 b/io/fv3atm_rrfs_sd_io.F90 index 2910e79a6..c6dc44e34 100644 --- a/io/fv3atm_rrfs_sd_io.F90 +++ b/io/fv3atm_rrfs_sd_io.F90 @@ -1,3 +1,7 @@ +!> \file fv3atm_rrfs_sd_io.F90 +!! This file contains derived types and subroutines for RRFS-SD scheme I/O. +!! They read and write restart files, and read emissions data. + module fv3atm_rrfs_sd_io use block_control_mod, only: block_control_type use fms2_io_mod, only: FmsNetcdfDomainFile_t, write_data, & @@ -21,8 +25,10 @@ module fv3atm_rrfs_sd_io rrfs_sd_emissions_register_emi, rrfs_sd_emissions_copy_emi, & rrfs_sd_emissions_register_fire, rrfs_sd_emissions_copy_fire - ! -------------------------------------------------------------------- + !>\defgroup fv3atm_rrfs_sd_io module + !> @{ + !>@ Temporary data storage for reading and writing restart data for the RRFS-SD scheme. type rrfs_sd_state_type ! The rrfs_sd_state_type stores temporary arrays used to read or ! write RRFS-SD restart and axis variables. @@ -51,6 +57,7 @@ module fv3atm_rrfs_sd_io ! -------------------------------------------------------------------- + !>@ Temporary data storage for reading RRFS-SD emissions data type rrfs_sd_emissions_type integer, private :: nvar_dust12m = 5 integer, private :: nvar_emi = 1 @@ -87,6 +94,7 @@ module fv3atm_rrfs_sd_io ! -- RRFS_SD_STATE IMPLEMENTATION ------------------------------------ ! -------------------------------------------------------------------- + !>@ Registers the fire_aux_data_levels axis for restart I/O subroutine rrfs_sd_state_register_axis(data,Model,Sfc_restart) implicit none class(rrfs_sd_state_type) :: data @@ -98,6 +106,7 @@ end subroutine rrfs_sd_state_register_axis ! -------------------------------------------------------------------- + !>@ Registers and writes the axis indices for the fire_aux_data_levels axis subroutine rrfs_sd_state_write_axis(data,Model,Sfc_restart) implicit none class(rrfs_sd_state_type) :: data @@ -111,6 +120,7 @@ end subroutine rrfs_sd_state_write_axis ! -------------------------------------------------------------------- + !>@ Allocates temporary arrays for RRFS-SD scheme I/O and stores fire_aux_data_levels axis indices subroutine rrfs_sd_state_allocate_data(data,Model) implicit none class(rrfs_sd_state_type) :: data @@ -138,11 +148,11 @@ end subroutine rrfs_sd_state_allocate_data ! -------------------------------------------------------------------- + !>@brief Fills RRFS-SD temporary arrays with reasonable defaults. + !> \section rrfs_sd_state_type%fill_data() procedure + !! Fills all temporary variables with default values. + !! Terrible things will happen if you don't call data%allocate_data first. subroutine rrfs_sd_state_fill_data(data, Model, Atm_block, Sfcprop) - ! Fills all temporary variables with default values. - ! Terrible things will happen if you don't call data%allocate_data first. - ! IMPORTANT: This must match the corresponding code in sfcprop_create in - ! GFS_typedefs.F90 implicit none class(rrfs_sd_state_type) :: data type(GFS_sfcprop_type), intent(in) :: Sfcprop(:) @@ -173,10 +183,12 @@ end subroutine rrfs_sd_state_fill_data ! -------------------------------------------------------------------- + !>@brief Registers RRFS-SD restart variables (for read or write) + !> \section rrfs_sd_state_type%register_fields() procedure + !! Registers all restart fields needed by the RRFS-SD + !! Terrible things will happen if you don't call data%allocate_data + !! and data%register_axes first. subroutine rrfs_sd_state_register_fields(data,Sfc_restart) - ! Registers all restart fields needed by the RRFS-SD - ! Terrible things will happen if you don't call data%allocate_data - ! and data%register_axes first. implicit none class(rrfs_sd_state_type) :: data type(FmsNetcdfDomainFile_t) :: Sfc_restart @@ -202,12 +214,14 @@ end subroutine rrfs_sd_state_register_fields ! -------------------------------------------------------------------- + !>@brief Creates ESMF bundles for writing RRFS-SD restarts via the write component (quilt) + !> \section rrfs_sd_state_type%bundle_fields() procedure + !! Registers all restart fields needed by the RRFS-SD + !! Terrible things will happen if you don't call data%allocate_data + !! and data%register_axes first. subroutine rrfs_sd_bundle_fields(data, bundle, grid, Model, outputfile) use esmf use GFS_typedefs, only: GFS_control_type - ! Registers all restart fields needed by the RRFS-SD - ! Terrible things will happen if you don't call data%allocate_data - ! and data%register_axes first. implicit none class(rrfs_sd_state_type) :: data type(ESMF_FieldBundle),intent(inout) :: bundle @@ -229,11 +243,13 @@ end subroutine rrfs_sd_bundle_fields ! -------------------------------------------------------------------- + !>@brief Destructor for the rrfs_sd_state_type + !> \section rrfs_sd_state_type destructor() procedure + !! Final routine for rrfs_sd_state_type, called automatically when + !! an object of that type goes out of scope. This is a wrapper + !! around data%deallocate_data() with necessary syntactic + !! differences. subroutine rrfs_sd_state_final(data) - ! Final routine for rrfs_sd_state_type, called automatically when - ! an object of that type goes out of scope. This is a wrapper - ! around data%deallocate_data() with necessary syntactic - ! differences. implicit none type(rrfs_sd_state_type) :: data call rrfs_sd_state_deallocate_data(data) @@ -241,10 +257,12 @@ end subroutine rrfs_sd_state_final ! -------------------------------------------------------------------- + !>@brief Deallocates internal arrays in an rrfs_sd_state_type + !> \section rrfs_sd_state_type%deallocate_data() procedure + !! Deallocates all data used, and nullifies the pointers. The data + !! object can safely be used again after this call. This is also + !! the implementation of the rrfs_sd_state_deallocate_data final routine. subroutine rrfs_sd_state_deallocate_data(data) - ! Deallocates all data used, and nullifies the pointers. The data - ! object can safely be used again after this call. This is also - ! the implementation of the rrfs_sd_state_deallocate_data final routine. implicit none class(rrfs_sd_state_type) :: data @@ -269,6 +287,10 @@ end subroutine rrfs_sd_state_deallocate_data ! -------------------------------------------------------------------- + !>@brief Copies from rrfs_sd_state_type internal arrays to the model grid. + !> \section rrfs_sd_state_type%copy_to_grid() procedure + !! This procedure is called after reading a restart, to copy restart data + !! from the rrfs_sd_state_type to the model grid. subroutine rrfs_sd_state_copy_to_grid(data, Model, Atm_block, Sfcprop) implicit none class(rrfs_sd_state_type) :: data @@ -297,6 +319,11 @@ end subroutine rrfs_sd_state_copy_to_grid ! -------------------------------------------------------------------- + !>@brief Copies from the model grid to rrfs_sd_state_type internal arrays + !> \section rrfs_sd_state_type%copy_from_grid() procedure + !! This procedure is called before writing the restart, to copy data from + !! the model grid to rrfs_sd_state_type internal arrays. The ESMF or FMS + !! restart code will write data from those arrays, not the model grid. subroutine rrfs_sd_state_copy_from_grid(data, Model, Atm_block, Sfcprop) implicit none class(rrfs_sd_state_type) :: data @@ -327,6 +354,7 @@ end subroutine rrfs_sd_state_copy_from_grid ! -- RRFS_SD_EMISSIONS IMPLEMENTATION -------------------------------- ! -------------------------------------------------------------------- + !>@ Allocates temporary arrays and registers variables for reading the dust12m file. subroutine rrfs_sd_emissions_register_dust12m(data, restart, Atm_block) implicit none class(rrfs_sd_emissions_type) :: data @@ -371,6 +399,7 @@ end subroutine rrfs_sd_emissions_register_dust12m ! -------------------------------------------------------------------- + !>@ Called after register_dust12m() to copy data from internal arrays to the model grid and deallocate arrays subroutine rrfs_sd_emissions_copy_dust12m(data, Sfcprop, Atm_block) implicit none type(GFS_sfcprop_type), intent(inout) :: Sfcprop(:) @@ -408,6 +437,7 @@ end subroutine rrfs_sd_emissions_copy_dust12m ! -------------------------------------------------------------------- + !>@ Allocates temporary arrays and registers variables for reading the emissions file. subroutine rrfs_sd_emissions_register_emi(data, restart, Atm_block) implicit none class(rrfs_sd_emissions_type) :: data @@ -446,6 +476,7 @@ end subroutine rrfs_sd_emissions_register_emi ! -------------------------------------------------------------------- + !>@ Called after register_emi() to copy data from internal arrays to the model grid and deallocate arrays subroutine rrfs_sd_emissions_copy_emi(data, Sfcprop, Atm_block) implicit none type(GFS_sfcprop_type), intent(inout) :: Sfcprop(:) @@ -479,6 +510,7 @@ end subroutine rrfs_sd_emissions_copy_emi ! -------------------------------------------------------------------- + !>@ Allocates temporary arrays and registers variables for reading the fire data file. subroutine rrfs_sd_emissions_register_fire(data, restart, Atm_block) implicit none class(rrfs_sd_emissions_type) :: data @@ -522,6 +554,7 @@ end subroutine rrfs_sd_emissions_register_fire ! -------------------------------------------------------------------- + !>@ Called after register_fire() to copy data from internal arrays to the model grid and deallocate arrays subroutine rrfs_sd_emissions_copy_fire(data, Sfcprop, Atm_block) implicit none class(rrfs_sd_emissions_type) :: data @@ -546,6 +579,7 @@ subroutine rrfs_sd_emissions_copy_fire(data, Sfcprop, Atm_block) enddo end subroutine rrfs_sd_emissions_copy_fire + !>@ Destructor for rrfs_sd_emissions_type subroutine rrfs_sd_emissions_final(data) implicit none type(rrfs_sd_emissions_type) :: data @@ -569,3 +603,5 @@ subroutine rrfs_sd_emissions_final(data) end subroutine rrfs_sd_emissions_final end module fv3atm_rrfs_sd_io + +!> @} diff --git a/io/fv3atm_sfc_io.F90 b/io/fv3atm_sfc_io.F90 index e08ab8dec..54f829cd3 100644 --- a/io/fv3atm_sfc_io.F90 +++ b/io/fv3atm_sfc_io.F90 @@ -1,3 +1,8 @@ +!> \file fv3atm_sfc_io.F90 +!! This file contains a derived type and subroutines to read and write restart files for +!! most FV3ATM surface fields. It works both for quilt (via ESMF) and non-quilt (via FMS) +!! restarts. Certain fields are handled by other files: fv3atm_oro_io.F90, fv3atm_rrfs_sd_io.F90, +!! and fv3atm_clm_lake_io.F90. module fv3atm_sfc_io use block_control_mod, only: block_control_type @@ -20,10 +25,16 @@ module fv3atm_sfc_io Sfc_io_register_3d_fields, Sfc_io_copy_to_grid, Sfc_io_copy_from_grid, & Sfc_io_apply_safeguards, Sfc_io_transfer, Sfc_io_final - real(kind=kind_phys), parameter :: timin = 173.0_kind_phys ! minimum temperature allowed for snow/ice + !> \defgroup fv3atm_sfc_io module + !> @{ + + !>@ Minimum temperature allowed for snow/ice + real(kind=kind_phys), parameter :: timin = 173.0_kind_phys + real(kind_phys), parameter:: min_lake_orog = 200.0_kind_phys real(kind_phys), parameter:: zero = 0, one = 1 + !> Internal data storage type for reading and writing surface restart files type Sfc_io_data_type integer, public :: nvar2o = 0 integer, public :: nvar3 = 0 @@ -81,6 +92,11 @@ module fv3atm_sfc_io contains + !>@brief Calculates all nvar indices in the Sfc_io_data_type + !> \section Sfc_io_data_type%calculate_indices() procedure + !! Calculates all nvar counts, which record the number of fields + !! of various types. These determine array sizes. + !! Returns .true. if any nvar counts changed, or .false. otherwise. function Sfc_io_calculate_indices(sfc, Model, reading, warm_start) implicit none class(Sfc_io_data_type) :: sfc @@ -158,6 +174,12 @@ function Sfc_io_calculate_indices(sfc, Model, reading, warm_start) end function Sfc_io_calculate_indices + !>@brief Allocates internal Sfc_io_data_type arrays if array sizes should change. + !> \section Sfc_io_data_type%allocate_arrays() procedure + !! Calls calculate_arrays() to determine if any nvar counts have changed, based + !! on the new arguments. If they have changed, then arrays are reallocated. + !! The arrays will need to be filled with new data at that point, as the contents + !! will be unknown. Returns .true. if arrays were reallocated, and .false. otherwise. function Sfc_io_allocate_arrays(sfc, Model, Atm_block, reading, warm_start) implicit none class(Sfc_io_data_type) :: sfc @@ -219,6 +241,7 @@ function Sfc_io_allocate_arrays(sfc, Model, Atm_block, reading, warm_start) endif end function Sfc_io_allocate_arrays + !>@ Registers all axes for reading or writing restarts using FMS (non-quilt) subroutine Sfc_io_register_axes(sfc, Model, Sfc_restart, reading, warm_start) implicit none class(Sfc_io_data_type) :: sfc @@ -251,9 +274,14 @@ subroutine Sfc_io_register_axes(sfc, Model, Sfc_restart, reading, warm_start) if (Model%lsm == Model%lsm_noah .or. Model%lsm == Model%lsm_noahmp) then call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil) else if(Model%lsm == Model%lsm_ruc .and. reading) then - ! The RUC defines zaxis_1 for reading, so it can read a restart from a different LSM. - ! The lsm_ruc never writes zaxis_2. call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil_lsm) + ! The RUC only ever writes zaxis_1, which is combined soil-ice, kice, which is 9. + ! Other LSMs read and write zaxis_2, which is lsoil for them, and that's always 4. + ! Defining zaxis_2 here lets RUC LSM read from a different soil vertical coordinate + ! (lsoil_lsm). In practice, this probably won't work well since levels will be + ! filled with zeroes. We retain this capability for historical reasons. + ! Just make sure you only restart RUC LSM off of RUC LSM, and always have + ! kice = lsoil = lsoil_lsm = 9 and everything will be fine. endif if(Model%lsm == Model%lsm_noahmp) then call register_axis(Sfc_restart, 'zaxis_3', dimension_length=3) @@ -263,6 +291,7 @@ subroutine Sfc_io_register_axes(sfc, Model, Sfc_restart, reading, warm_start) endif end subroutine Sfc_io_register_axes + !>@ Writes axis index variables and related metadata for all axes when writing FMS (non-quilt) restarts subroutine Sfc_io_write_axes(sfc, Model, Sfc_restart) implicit none class(Sfc_io_data_type) :: sfc @@ -329,6 +358,7 @@ subroutine Sfc_io_write_axes(sfc, Model, Sfc_restart) call write_data( Sfc_restart, 'Time', 1) end subroutine Sfc_io_write_axes + !>@ Fills the name3d array with all surface 3D field names. subroutine Sfc_io_fill_3d_names(sfc,Model,warm_start) implicit none class(Sfc_io_data_type) :: sfc @@ -360,6 +390,7 @@ subroutine Sfc_io_fill_3d_names(sfc,Model,warm_start) sfc%name3(0) = 'tiice' end subroutine Sfc_io_fill_3d_names + !>@ Fills the name2d array with all surface 2D field names. Updates nvar2m if needed. subroutine Sfc_io_fill_2d_names(sfc,Model,warm_start) implicit none class(Sfc_io_data_type) :: sfc @@ -519,6 +550,7 @@ subroutine Sfc_io_fill_2d_names(sfc,Model,warm_start) endif end subroutine Sfc_io_fill_2d_names + !>@ Registers 2D fields with FMS for reading or writing non-quilt restart files subroutine Sfc_io_register_2d_fields(sfc,Model,Sfc_restart,reading,warm_start) implicit none class(Sfc_io_data_type) :: sfc @@ -624,6 +656,7 @@ subroutine Sfc_io_register_2d_fields(sfc,Model,Sfc_restart,reading,warm_start) end subroutine Sfc_io_register_2d_fields + !>@ Registers 3D fields with FMS for reading or writing non-quilt restart files subroutine Sfc_io_register_3d_fields(sfc,Model,Sfc_restart,reading,warm_start) implicit none class(Sfc_io_data_type) :: sfc @@ -693,6 +726,7 @@ subroutine Sfc_io_register_3d_fields(sfc,Model,Sfc_restart,reading,warm_start) end subroutine Sfc_io_register_3d_fields + !>@ Initializes some surface fields with reasonable defaults subroutine Sfc_io_init_fields(sfc,Model) implicit none class(Sfc_io_data_type) :: sfc @@ -706,6 +740,14 @@ subroutine Sfc_io_init_fields(sfc,Model) endif end subroutine Sfc_io_init_fields + !>@ Copies data to the model grid (reading=true) or from the model grid (reading=false) + !> \section Sfc_io_data_type%transfer + !! Called to transfer data between the model grid and Sfc_io_data_type temporary arrays. + !! The FMS and ESMF restarts use the temporary arrays, not the model grid arrays. This + !! transfer routine copies to the model grid if reading=.true. or from the model grid + !! if reading=.false. This is mostly loops around GFS_data_transfer() interface calls. + !! + !! In addition, if override_frac_grid is provided, it will be set to Model%frac_grid. subroutine Sfc_io_transfer(sfc, reading, Model, Atm_block, Sfcprop, warm_start, override_frac_grid) !--- interface variable definitions implicit none @@ -1163,6 +1205,7 @@ subroutine Sfc_io_transfer(sfc, reading, Model, Atm_block, Sfcprop, warm_start, end do block_loop end subroutine Sfc_io_transfer + !>@ Copies from Sfc_io_data_type internal arrays to the model grid by calling transfer() with reading=.true. subroutine Sfc_io_copy_to_grid(sfc, Model, Atm_block, Sfcprop, warm_start, override_frac_grid) !--- interface variable definitions implicit none @@ -1178,6 +1221,7 @@ subroutine Sfc_io_copy_to_grid(sfc, Model, Atm_block, Sfcprop, warm_start, overr end subroutine Sfc_io_copy_to_grid + !>@ Copies from the model grid to Sfc_io_data_type internal arrays by calling transfer() with reading=.false. subroutine Sfc_io_copy_from_grid(sfc, Model, Atm_block, Sfcprop) !--- interface variable definitions implicit none @@ -1191,6 +1235,7 @@ subroutine Sfc_io_copy_from_grid(sfc, Model, Atm_block, Sfcprop) end subroutine Sfc_io_copy_from_grid + !>@ Calculates values and applies safeguards after reading restart data. subroutine Sfc_io_apply_safeguards(sfc, Model, Atm_block, Sfcprop) !--- interface variable definitions implicit none @@ -1422,6 +1467,7 @@ subroutine Sfc_io_apply_safeguards(sfc, Model, Atm_block, Sfcprop) end subroutine Sfc_io_apply_safeguards + !>@ destructor for Sfc_io_data_type subroutine Sfc_io_final(sfc) implicit none type(Sfc_io_data_type) :: sfc @@ -1457,6 +1503,7 @@ subroutine Sfc_io_final(sfc) end subroutine Sfc_io_final + !>@ Creates ESMF bundles for 2D fields, for writing surface restart files using the write component (quilt) subroutine Sfc_io_bundle_2d_fields(sfc, bundle, grid, Model, outputfile) use esmf use GFS_typedefs, only: GFS_control_type @@ -1504,6 +1551,7 @@ subroutine Sfc_io_bundle_2d_fields(sfc, bundle, grid, Model, outputfile) endif end subroutine Sfc_io_bundle_2d_fields + !>@ Creates ESMF bundles for 3D fields, for writing surface restart files using the write component (quilt) subroutine Sfc_io_bundle_3d_fields(sfc, bundle, grid, Model, outputfile) use esmf use GFS_typedefs, only: GFS_control_type @@ -1568,3 +1616,4 @@ subroutine Sfc_io_bundle_3d_fields(sfc, bundle, grid, Model, outputfile) end subroutine Sfc_io_bundle_3d_fields end module fv3atm_sfc_io +!> @} From 0466c61e211ba2e778429f21856933460c10704c Mon Sep 17 00:00:00 2001 From: "samuel.trahan" Date: Wed, 31 May 2023 21:49:16 +0000 Subject: [PATCH 27/27] Even longer explanation of RUC LSM axes from @tanyasmirnova --- io/fv3atm_sfc_io.F90 | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/io/fv3atm_sfc_io.F90 b/io/fv3atm_sfc_io.F90 index 54f829cd3..cff249370 100644 --- a/io/fv3atm_sfc_io.F90 +++ b/io/fv3atm_sfc_io.F90 @@ -275,13 +275,19 @@ subroutine Sfc_io_register_axes(sfc, Model, Sfc_restart, reading, warm_start) call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil) else if(Model%lsm == Model%lsm_ruc .and. reading) then call register_axis(Sfc_restart, 'zaxis_2', dimension_length=Model%lsoil_lsm) - ! The RUC only ever writes zaxis_1, which is combined soil-ice, kice, which is 9. - ! Other LSMs read and write zaxis_2, which is lsoil for them, and that's always 4. - ! Defining zaxis_2 here lets RUC LSM read from a different soil vertical coordinate - ! (lsoil_lsm). In practice, this probably won't work well since levels will be - ! filled with zeroes. We retain this capability for historical reasons. - ! Just make sure you only restart RUC LSM off of RUC LSM, and always have - ! kice = lsoil = lsoil_lsm = 9 and everything will be fine. + ! The RUC only ever writes zaxis_1, which is combined soil/ice + ! vertical dimension, lsoil_lsm/kice, which is 9. Other LSMs read and + ! write zaxis_2, which is lsoil for them, and that's always 4. + ! Defining zaxis_2 here lets RUC LSM read from a different soil + ! vertical coordinate (lsoil_lsm). It is needed for restart of RUC LSM + ! from RUC LSM. This capability exists for historical reasons, because + ! there are two sets of soil state variables: one set has lsoil=4 + ! vertical layers (Noah LSM. NoahMP LSM), and another set has + ! lsoil_lsm=9 vertical levels (RUC LSM). Ideally there should be just + ! one set of soil variables that could have different vertical + ! dimension depending on the choice of LSM. For now: just make sure + ! you only restart RUC LSM off of RUC LSM, and always have kice = + ! lsoil = lsoil_lsm = 9 and everything will be fine. endif if(Model%lsm == Model%lsm_noahmp) then call register_axis(Sfc_restart, 'zaxis_3', dimension_length=3)