From 086143c38b9815a6b64d7b922b3a5a172a7f1e6f Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Fri, 28 Oct 2022 17:56:51 +0000 Subject: [PATCH 01/50] Baseline initial routines to process fractional veg/soil type. Routines were created to interpolate, search for missing data, and output the data. Fixes #709. --- sorc/sfc_climo_gen.fd/CMakeLists.txt | 3 + sorc/sfc_climo_gen.fd/driver.F90 | 2 +- sorc/sfc_climo_gen.fd/interp2.F90 | 404 +++++++++++++++++++++++++++ sorc/sfc_climo_gen.fd/output2.f90 | 269 ++++++++++++++++++ sorc/sfc_climo_gen.fd/search2.f90 | 146 ++++++++++ 5 files changed, 823 insertions(+), 1 deletion(-) create mode 100644 sorc/sfc_climo_gen.fd/interp2.F90 create mode 100644 sorc/sfc_climo_gen.fd/output2.f90 create mode 100644 sorc/sfc_climo_gen.fd/search2.f90 diff --git a/sorc/sfc_climo_gen.fd/CMakeLists.txt b/sorc/sfc_climo_gen.fd/CMakeLists.txt index f5e3b9186..20118b456 100644 --- a/sorc/sfc_climo_gen.fd/CMakeLists.txt +++ b/sorc/sfc_climo_gen.fd/CMakeLists.txt @@ -5,10 +5,13 @@ set(lib_src interp.F90 + interp2.F90 model_grid.F90 output.f90 + output2.f90 program_setup.f90 search.f90 + search2.f90 source_grid.F90 utils.f90) diff --git a/sorc/sfc_climo_gen.fd/driver.F90 b/sorc/sfc_climo_gen.fd/driver.F90 index 4f05d974a..59fed8652 100644 --- a/sorc/sfc_climo_gen.fd/driver.F90 +++ b/sorc/sfc_climo_gen.fd/driver.F90 @@ -81,7 +81,7 @@ program driver call define_source_grid(localpet, npets, input_vegetation_type_file) method=ESMF_REGRIDMETHOD_NEAREST_STOD - call interp(localpet, method, input_vegetation_type_file) + call interp2(localpet, method, input_vegetation_type_file) call source_grid_cleanup ! Snow free albedo diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 new file mode 100644 index 000000000..013e12c33 --- /dev/null +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -0,0 +1,404 @@ +!> @file +!! @brief Read the input source data and interpolate it to the +!! model grid. +!! @author George Gayno @date 2018 + +!> Read the input source data and interpolate it to the +!! model grid. +!! +!! @param[in] localpet this mpi task +!! @param[in] method interpolation method.defined where mask=1 +!! @param[in] input_file filename of input source data. +!! @author George Gayno @date 2018 + subroutine interp2(localpet, method, input_file) + + use esmf + use netcdf + use model_grid + use source_grid + use utils + use mpi + + implicit none + + character(len=*), intent(in) :: input_file + + integer :: rc, localpet + integer :: i, j, ij, tile, n, ncid, status + integer :: l(1), u(1), t + integer :: clb_mdl(3), cub_mdl(3) + integer :: clb_src(3), cub_src(3) + integer :: varid, record + integer :: tile_num, pt_loc_this_tile + integer :: isrctermprocessing + integer :: category + + integer(esmf_kind_i4), allocatable :: mask_mdl_one_tile(:,:) + integer(esmf_kind_i4), pointer :: unmapped_ptr(:) + + real(esmf_kind_r4), pointer :: data_mdl_ptr(:,:,:) + real(esmf_kind_r4), pointer :: data_src_ptr(:,:,:) + real(esmf_kind_r4), allocatable :: data_src_global(:,:) + real(esmf_kind_r4), allocatable :: data_src_global2(:,:,:) + real(esmf_kind_r4), allocatable :: data_mdl_one_tile(:,:,:) + real(esmf_kind_r4), allocatable :: vegt_mdl_one_tile(:,:) + real(esmf_kind_r4), allocatable :: lat_mdl_one_tile(:,:) + real(esmf_kind_r4), allocatable :: lon_mdl_one_tile(:,:) + +!type(esmf_regridmethod_flag),intent(in) :: method + type(esmf_regridmethod_flag) :: method + type(esmf_field) :: data_field_src + type(esmf_field) :: data_field_mdl2 + type(esmf_routehandle) :: regrid_data + type(esmf_polemethod_flag) :: pole + + print*,"- CALL FieldCreate FOR SOURCE GRID DATA." + data_field_src = ESMF_FieldCreate(grid_src, & + typekind=ESMF_TYPEKIND_R4, & + indexflag=ESMF_INDEX_GLOBAL, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/20/), & + name="source data", & + rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldGet FOR SOURCE GRID DATA." + nullify(data_src_ptr) + call ESMF_FieldGet(data_field_src, & + farrayPtr=data_src_ptr, & + computationalLBound=clb_src, & + computationalUBound=cub_src, & + rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,'got here ',localpet,clb_src,cub_src + + print*,"- CALL FieldCreate FOR model GRID veg DATA." + data_field_mdl2 = ESMF_FieldCreate(grid_mdl, & + typekind=ESMF_TYPEKIND_R4, & + indexflag=ESMF_INDEX_GLOBAL, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/20/), & + name="mdl data", & + rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldGet FOR MODEL GRID DATA." + nullify(data_mdl_ptr) + call ESMF_FieldGet(data_field_mdl2, & + farrayPtr=data_mdl_ptr, & + computationalLBound=clb_mdl, & + computationalUBound=cub_mdl, & + rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + + print*,'got here2 ',localpet,clb_mdl,cub_mdl + + if (localpet == 0) then + allocate(data_src_global(i_src,j_src)) + allocate(data_src_global2(i_src,j_src,20)) + else + allocate(data_src_global(0,0)) + allocate(data_src_global2(0,0,0)) + endif + + print*,'- OPEN SOURCE FILE ', trim(input_file) + status = nf90_open(input_file, nf90_nowrite, ncid) + call netcdf_err(status, "IN ROUTINE INTERP OPENING SOURCE FILE") + + if (localpet == 0) then + allocate(data_mdl_one_tile(i_mdl,j_mdl,20)) + allocate(mask_mdl_one_tile(i_mdl,j_mdl)) + allocate(lat_mdl_one_tile(i_mdl,j_mdl)) + allocate(lon_mdl_one_tile(i_mdl,j_mdl)) + else + allocate(data_mdl_one_tile(0,0,0)) + allocate(mask_mdl_one_tile(0,0)) + allocate(lat_mdl_one_tile(0,0)) + allocate(lon_mdl_one_tile(0,0)) + endif + + record = 0 + + TIME_LOOP : do t = 1, num_time_recs ! loop over each time period + + FIELD_LOOP : do n = 1, num_fields ! loop over each surface field. + + record = record + 1 + + if (localpet == 0) then + status = nf90_inq_varid(ncid, field_names(n), varid) + call netcdf_err(status, "IN ROUTINE INTERP READING FIELD ID") + status = nf90_get_var(ncid, varid, data_src_global, start=(/1,1,t/), count=(/i_src,j_src,1/)) + call netcdf_err(status, "IN ROUTINE INTERP READING FIELD") + data_src_global2 = 0.0 + do j = 1, j_src + do i = 1, i_src + category = nint(data_src_global(i,j)) +! if (category < 1) category = 17 + if (category < 1) cycle + data_src_global2(i,j,category) = 1.0 + enddo + enddo + endif + + print*,"- CALL FieldScatter FOR SOURCE GRID DATA." + call ESMF_FieldScatter(data_field_src, data_src_global2, rootPet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter.", rc) + + isrctermprocessing = 1 + + if (record == 1) then + + method = ESMF_REGRIDMETHOD_CONSERVE + + if (method == ESMF_REGRIDMETHOD_BILINEAR) then + pole = ESMF_POLEMETHOD_ALLAVG + else + pole = ESMF_POLEMETHOD_NONE + endif + + + print*,"- CALL FieldRegridStore." + nullify(unmapped_ptr) + call ESMF_FieldRegridStore(data_field_src, & + data_field_mdl2, & + srcmaskvalues=(/0/), & + dstmaskvalues=(/0/), & + polemethod=pole, & + unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, & + normtype=ESMF_NORMTYPE_FRACAREA, & + srctermprocessing=isrctermprocessing, & + routehandle=regrid_data, & + regridmethod=method, & + unmappedDstList=unmapped_ptr, & + rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegridStore.", rc) + + endif + + print*,"- CALL Field_Regrid." + call ESMF_FieldRegrid(data_field_src, & + data_field_mdl2, & + routehandle=regrid_data, & + termorderflag=ESMF_TERMORDER_SRCSEQ, & + rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegrid.", rc) + +!----------------------------------------------------------------------- +! Unmapped points are stored in "unmapped_ptr". The pointer contains +! "ij" global indices as follows: +! +! tile 1: 1 thru (itile*jtile) +! tile n: (n-1)*(itile*jtile) thru n*(itile*jtile) +! +! This "ij" index is converted to the tile number and i/j index of the +! field object. This logic assumes the model grid object was +! created using "GLOBAL" indices. +! +! Unmapped data points are given the flag value of -9999.9, which +! will be replaced in routine "search". +!----------------------------------------------------------------------- + + l = lbound(unmapped_ptr) + u = ubound(unmapped_ptr) +! do ij = l(1), u(1) + +! tile_num = ((unmapped_ptr(ij)-1) / (i_mdl*j_mdl)) ! tile number minus 1 +! pt_loc_this_tile = unmapped_ptr(ij) - (tile_num * i_mdl * j_mdl) + ! "ij" location of point within tile. + +! j = (pt_loc_this_tile - 1) / i_mdl + 1 +! i = mod(pt_loc_this_tile, i_mdl) +! if (i==0) i = i_mdl +! data_mdl_ptr(i,j,:) = -9999.9 + +! enddo + +! These fields are adjusted at landice. + +! select case (trim(field_names(n))) +! case ('substrate_temperature','vegetation_greenness','leaf_area_index','slope_type','soil_type') +! if (localpet == 0) then +! allocate(vegt_mdl_one_tile(i_mdl,j_mdl)) +! else +! allocate(vegt_mdl_one_tile(0,0)) +! endif +! end select + + OUTPUT_LOOP : do tile = 1, num_tiles + + print*,"- CALL FieldGather FOR MODEL LATITUDE." + call ESMF_FieldGather(latitude_field_mdl, lat_mdl_one_tile, rootPet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather.", rc) + + print*,"- CALL FieldGather FOR MODEL LONGITUDE." + call ESMF_FieldGather(longitude_field_mdl, lon_mdl_one_tile, rootPet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather.", rc) + + print*,"- CALL FieldGather FOR MODEL GRID DATA." + call ESMF_FieldGather(data_field_mdl2, data_mdl_one_tile, rootPet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather.", rc) + + print*,"- CALL FieldGather FOR MODEL GRID LAND MASK." + call ESMF_FieldGather(mask_field_mdl, mask_mdl_one_tile, rootPet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather.", rc) + + select case (trim(field_names(n))) + case ('substrate_temperature','vegetation_greenness','leaf_area_index','slope_type','soil_type') + print*,"- CALL FieldGather FOR MODEL GRID VEG TYPE." + call ESMF_FieldGather(vegt_field_mdl, vegt_mdl_one_tile, rootPet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather.", rc) + end select + + if (localpet == 0) then + print*,'- CALL SEARCH FOR TILE ',tile + lat_mdl_one_tile = sum(data_mdl_one_tile, dim=3) ! use unused variable to now. + do j = 1, j_mdl + do i = 1, i_mdl + + if (mask_mdl_one_tile(i,j) == 1 .and. lat_mdl_one_tile(i,j) == 0.0) then + data_mdl_one_tile(i,j,:) = -9999.9 + endif + + enddo + enddo + + call search2 (data_mdl_one_tile, mask_mdl_one_tile, i_mdl, j_mdl, tile, field_names(n)) +! where(mask_mdl_one_tile == 0) data_mdl_one_tile = missing + print*,'after regrid ',data_mdl_one_tile(i_mdl/2,j_mdl/2,:) + call output2 (data_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, tile, record, t, n) + endif + + print*,'after output ', localpet + call mpi_barrier(mpi_comm_world, rc) + stop + +! if (field_names(n) == 'vegetation_type') then +! print*,"- CALL FieldScatter FOR MODEL GRID VEGETATION TYPE." +! call ESMF_FieldScatter(vegt_field_mdl, data_mdl_one_tile, rootPet=0, tile=tile, rc=rc) +! if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & +! call error_handler("IN FieldScatter.", rc) +! endif + + enddo OUTPUT_LOOP + + if (allocated(vegt_mdl_one_tile)) deallocate(vegt_mdl_one_tile) + + enddo FIELD_LOOP + enddo TIME_LOOP + + status=nf90_close(ncid) + + deallocate(data_mdl_one_tile, mask_mdl_one_tile) + deallocate(data_src_global, lat_mdl_one_tile, lon_mdl_one_tile) + + print*,"- CALL FieldRegridRelease." + call ESMF_FieldRegridRelease(routehandle=regrid_data, rc=rc) + + print*,"- CALL FieldDestroy." + call ESMF_FieldDestroy(data_field_src, rc=rc) + + end subroutine interp2 + +!> Ensure consistent fields at land ice points. +!! Land ice is vegetation type 15 (variable landice). +!! output is Model field. +!! +!! @param[in] field Model field before adjustments for land ice. +!! @param[in] vegt Vegetation type on the model tile. +!! @param[inout] idim i dimension of model tile. +!! @param[inout] jdim j dimension of model tile. +!! @param[in] field_ch Field name. +!! @author George Gayno NCEP/EMC + subroutine adjust_for_landice2(field, vegt, idim, jdim, field_ch) + + use esmf + use mpi + + implicit none + + character(len=*), intent(in) :: field_ch + + integer, intent(in) :: idim, jdim + + real(esmf_kind_i4), intent(in) :: vegt(idim,jdim) + real(esmf_kind_r4), intent(inout) :: field(idim,jdim) + + integer, parameter :: landice=15 + + integer :: i, j, ierr + + real :: landice_value + + select case (field_ch) + case ('substrate_temperature') ! soil substrate temp + landice_value = 273.15 + do j = 1, jdim + do i = 1, idim + if (nint(vegt(i,j)) == landice) then + field(i,j) = min(field(i,j), landice_value) + endif + enddo + enddo + case ('vegetation_greenness') ! vegetation greenness + landice_value = 0.01 ! 1.0% is bare ground + do j = 1, jdim + do i = 1, idim + if (nint(vegt(i,j)) == landice) then + field(i,j) = landice_value + endif + enddo + enddo + case ('leaf_area_index') ! leaf area index + landice_value = 0.0 ! bare ground + do j = 1, jdim + do i = 1, idim + if (nint(vegt(i,j)) == landice) then + field(i,j) = landice_value + endif + enddo + enddo + case ('slope_type') ! slope type + landice_value = 9.0 + do j = 1, jdim + do i = 1, idim + if (nint(vegt(i,j)) == landice) then + field(i,j) = landice_value + else + if (nint(field(i,j)) == nint(landice_value)) field(i,j) = 2.0 + endif + enddo + enddo + case ('soil_type') ! soil type + landice_value = 16.0 + do j = 1, jdim + do i = 1, idim + if (nint(vegt(i,j)) == landice) then + field(i,j) = landice_value + else + if (nint(field(i,j)) == nint(landice_value)) field(i,j) = 6.0 + endif + enddo + enddo + case default + print*,'- FATAL ERROR IN ROUTINE ADJUST_FOR_LANDICE. UNIDENTIFIED FIELD : ', field_ch + call mpi_abort(mpi_comm_world, 57, ierr) + end select + + end subroutine adjust_for_landice2 diff --git a/sorc/sfc_climo_gen.fd/output2.f90 b/sorc/sfc_climo_gen.fd/output2.f90 new file mode 100644 index 000000000..42357fb82 --- /dev/null +++ b/sorc/sfc_climo_gen.fd/output2.f90 @@ -0,0 +1,269 @@ +!> @file +!! @brief Output model data for a single tile and a single record. +!! @author George Gayno @date 2018 + +!> Output model data for a single tile and a single +!! record in netcdf format. +!! +!! @param[in] data_one_tile Data to be output (single tile). +!! @param[in] lat_one_tile Latitude of tile. +!! @param[in] lon_one_tile Longitude of tile. +!! @param[in] field_idx Index of field within field name array. +!! @param[in] i_mdl i dimensions of tile. +!! @param[in] j_mdl j dimensions of tile. +!! @param[in] record Record number to be output. +!! @param[in] tile Tile number. +!! @param[in] time Time period to be output. +!! @author George Gayno @date 2018 + subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & + tile, record, time, field_idx) + + use mpi + use esmf + use netcdf + use utils + use source_grid, only : field_names, source, num_fields, & + num_time_recs, num_records, day_of_rec + use model_grid, only : missing, grid_tiles + use program_setup, only : halo + + implicit none + + integer, intent(in) :: i_mdl, j_mdl, tile + integer, intent(in) :: record, time, field_idx + + real(esmf_kind_r4), intent(in) :: data_one_tile(i_mdl,j_mdl,20) + real(esmf_kind_r4) :: lat_one_tile(i_mdl,j_mdl) + real(esmf_kind_r4), intent(in) :: lon_one_tile(i_mdl,j_mdl) + + character(len=200) :: out_file + character(len=200) :: out_file_with_halo + + integer :: initialsiz, fsize, error, j + integer :: dim_x, dim_y, dim_z, id_data + integer :: dim_time, id_times, ierr + integer :: header_buffer_val = 16384 + integer :: i_out, j_out, id_lat, id_lon, id_sum + integer :: i_start, i_end, j_start, j_end + integer, save :: ncid(6), ncid_with_halo + + select case (field_names(field_idx)) + case ('substrate_temperature') + out_file = "./substrate_temperature." // grid_tiles(tile) // ".nc" + out_file_with_halo = "./substrate_temperature." // grid_tiles(tile) // ".halo.nc" + case ('vegetation_greenness') + out_file = "./vegetation_greenness." // grid_tiles(tile) // ".nc" + out_file_with_halo = "./vegetation_greenness." // grid_tiles(tile) // ".halo.nc" + case ('maximum_snow_albedo') + out_file = "./maximum_snow_albedo." // grid_tiles(tile) // ".nc" + out_file_with_halo = "./maximum_snow_albedo." // grid_tiles(tile) // ".halo.nc" + case ('leaf_area_index') + out_file = "./leaf_area_index." // grid_tiles(tile) // ".nc" + out_file_with_halo = "./leaf_area_index." // grid_tiles(tile) // ".halo.nc" + case ('visible_black_sky_albedo', 'visible_white_sky_albedo', 'near_IR_black_sky_albedo', 'near_IR_white_sky_albedo') + out_file = "./snowfree_albedo." // grid_tiles(tile) // ".nc" + out_file_with_halo = "./snowfree_albedo." // grid_tiles(tile) // ".halo.nc" + case ('facsf') + out_file = "./facsf." // grid_tiles(tile) // ".nc" + out_file_with_halo = "./facsf." // grid_tiles(tile) // ".halo.nc" + case ('slope_type') + out_file = "./slope_type." // grid_tiles(tile) // ".nc" + out_file_with_halo = "./slope_type." // grid_tiles(tile) // ".halo.nc" + case ('soil_type') + out_file = "./soil_type." // grid_tiles(tile) // ".nc" + out_file_with_halo = "./soil_type." // grid_tiles(tile) // ".halo.nc" + case ('vegetation_type') + out_file = "./vegetation_type." // grid_tiles(tile) // ".nc" + out_file_with_halo = "./vegetation_type." // grid_tiles(tile) // ".halo.nc" + case default + print*,'- FATAL ERROR IN ROUTINE OUTPUT. UNIDENTIFIED FIELD : ', field_names(field_idx) + call mpi_abort(mpi_comm_world, 67, ierr) + end select + +!---------------------------------------------------------------------- +! If user specified a halo (for running stand-alone regional grid), +! remove it. +!---------------------------------------------------------------------- + + if (halo > 0) then + print*,"- WILL REMOVE HALO REGION OF ", halo, " ROWS/COLS." + i_start = 1 + halo + i_end = i_mdl - halo + j_start = 1 + halo + j_end = j_mdl - halo + else + i_start = 1 + i_end = i_mdl + j_start = 1 + j_end = j_mdl + endif + + i_out = i_end - i_start + 1 + j_out = j_end - j_start + 1 + + if (record == 1) then + + initialsiz = 0 + fsize = 65536 + error = nf90_create(out_file, IOR(NF90_NETCDF4,NF90_CLASSIC_MODEL), & + ncid(tile), initialsize=initialsiz, chunksize=fsize) + call netcdf_err(error, 'ERROR IN NF90_CREATE' ) + error = nf90_def_dim(ncid(tile), 'nx', i_out, dim_x) + call netcdf_err(error, 'DEFINING NX DIMENSION' ) + error = nf90_def_dim(ncid(tile), 'ny', j_out, dim_y) + call netcdf_err(error, 'DEFINING NY DIMENSION' ) + error = nf90_def_dim(ncid(tile), 'nz', 20, dim_z) + call netcdf_err(error, 'DEFINING NZ DIMENSION' ) + error = nf90_def_dim(ncid(tile), 'time', num_time_recs, dim_time) + call netcdf_err(error, 'DEFINING TIME DIMENSION' ) + error = nf90_def_var(ncid(tile), 'time', NF90_FLOAT, dim_time, id_times) + call netcdf_err(error, 'DEFINING TIME VARIABLE' ) + error = nf90_put_att(ncid(tile), id_times, "units", "days since 2015-1-1") + call netcdf_err(error, 'DEFINING TIME ATTRIBUTE' ) + if (len_trim(source) > 0) then + error = nf90_put_att(ncid(tile), nf90_global, 'source', source) + call netcdf_err(error, 'DEFINING GLOBAL SOURCE ATTRIBUTE' ) + endif + + error = nf90_def_var(ncid(tile), 'geolat', NF90_FLOAT, (/dim_x,dim_y/), id_lat) + call netcdf_err(error, 'DEFINING GEOLAT FIELD' ) + error = nf90_put_att(ncid(tile), id_lat, "long_name", "Latitude") + call netcdf_err(error, 'DEFINING GEOLAT NAME ATTRIBUTE' ) + error = nf90_put_att(ncid(tile), id_lat, "units", "degrees_north") + call netcdf_err(error, 'DEFINING GEOLAT UNIT ATTRIBUTE' ) + error = nf90_def_var(ncid(tile), 'geolon', NF90_FLOAT, (/dim_x,dim_y/), id_lon) + call netcdf_err(error, 'DEFINING GEOLON FIELD' ) + error = nf90_put_att(ncid(tile), id_lon, "long_name", "Longitude") + call netcdf_err(error, 'DEFINING GEOLON NAME ATTRIBUTE' ) + error = nf90_put_att(ncid(tile), id_lon, "units", "degrees_east") + call netcdf_err(error, 'DEFINING GEOLON UNIT ATTRIBUTE' ) + + do j = 1, num_fields + error = nf90_def_var(ncid(tile), trim(field_names(j)), NF90_FLOAT, (/dim_x,dim_y,dim_z,dim_time/), id_data) + call netcdf_err(error, 'DEFINING FIELD' ) + error = nf90_put_att(ncid(tile), id_data, "missing_value", missing) + call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) + error = nf90_put_att(ncid(tile), id_data, "coordinates", "geolon geolat") + call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) + error = nf90_def_var(ncid(tile), 'sum', NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_sum) + call netcdf_err(error, 'DEFINING FIELD' ) + enddo + + error = nf90_enddef(ncid(tile), header_buffer_val,4,0,4) + call netcdf_err(error, 'IN NF90_ENDDEF' ) + + error = nf90_put_var( ncid(tile), id_times, day_of_rec) + call netcdf_err(error, 'WRITING TIME FIELD' ) + + error = nf90_put_var( ncid(tile), id_lat, lat_one_tile(i_start:i_end,j_start:j_end), & + start=(/1,1/), count=(/i_out,j_out/)) + call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLAT' ) + + error = nf90_put_var( ncid(tile), id_lon, lon_one_tile(i_start:i_end,j_start:j_end), & + start=(/1,1/), count=(/i_out,j_out/)) + call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLON' ) + + endif + + print*,'- WRITE DATA FOR RECORD: ',record + error = nf90_inq_varid( ncid(tile), field_names(field_idx), id_data) + call netcdf_err(error, 'IN NF90_INQ_VARID' ) + error = nf90_put_var( ncid(tile), id_data, data_one_tile(i_start:i_end,j_start:j_end,:), & + start=(/1,1,1,time/), count=(/i_out,j_out,20,1/)) + call netcdf_err(error, 'IN NF90_PUT_VAR' ) + +! reuse lat + lat_one_tile = sum(data_one_tile, dim=3) + error = nf90_put_var( ncid(tile), id_sum, lat_one_tile(i_start:i_end,j_start:j_end), & + start=(/1,1,time/), count=(/i_out,j_out,1/)) + + if (record == num_records) then + error = nf90_close(ncid(tile)) + endif + + print*,'after write' + stop + +!---------------------------------------------------------------------- +! For regional nests, also output files including the halo +!---------------------------------------------------------------------- + + if (halo == 0) return + + print*,"- WRITE OUT FILES THAT INCLUDE HALO REGION." + + if (record == 1) then + + initialsiz = 0 + fsize = 65536 + error = nf90_create(out_file_with_halo, IOR(NF90_NETCDF4,NF90_CLASSIC_MODEL), & + ncid_with_halo, initialsize=initialsiz, chunksize=fsize) + call netcdf_err(error, 'IN NF90_CREATE' ) + error = nf90_def_dim(ncid_with_halo, 'nx', i_mdl, dim_x) + call netcdf_err(error, 'DEFINING NX DIMENSION' ) + error = nf90_def_dim(ncid_with_halo, 'ny', j_mdl, dim_y) + call netcdf_err(error, 'DEFINING NY DIMENSION' ) + error = nf90_def_dim(ncid_with_halo, 'time', num_time_recs, dim_time) + call netcdf_err(error, 'DEFINING TIME DIMENSION' ) + error = nf90_def_var(ncid_with_halo, 'time', NF90_FLOAT, dim_time, id_times) + call netcdf_err(error, 'DEFINING TIME VARIABLE' ) + error = nf90_put_att(ncid_with_halo, id_times, "units", "days since 2015-1-1") + call netcdf_err(error, 'DEFINING TIME ATTRIBUTE' ) + if (len_trim(source) > 0) then + error = nf90_put_att(ncid_with_halo, nf90_global, 'source', source) + call netcdf_err(error, 'DEFINING GLOBAL SOURCE ATTRIBUTE' ) + endif + + error = nf90_def_var(ncid_with_halo, 'geolat', NF90_FLOAT, (/dim_x,dim_y/), id_lat) + call netcdf_err(error, 'DEFINING GEOLAT FIELD' ) + error = nf90_put_att(ncid_with_halo, id_lat, "long_name", "Latitude") + call netcdf_err(error, 'DEFINING GEOLAT NAME ATTRIBUTE' ) + error = nf90_put_att(ncid_with_halo, id_lat, "units", "degrees_north") + call netcdf_err(error, 'DEFINING GEOLAT UNIT ATTRIBUTE' ) + error = nf90_def_var(ncid_with_halo, 'geolon', NF90_FLOAT, (/dim_x,dim_y/), id_lon) + call netcdf_err(error, 'DEFINING GEOLON FIELD' ) + error = nf90_put_att(ncid_with_halo, id_lon, "long_name", "Longitude") + call netcdf_err(error, 'DEFINING GEOLON NAME ATTRIBUTE' ) + error = nf90_put_att(ncid_with_halo, id_lon, "units", "degrees_east") + call netcdf_err(error, 'DEFINING GEOLON UNIT ATTRIBUTE' ) + + do j = 1, num_fields + error = nf90_def_var(ncid_with_halo, field_names(j), NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_data) + call netcdf_err(error, 'DEFINING FIELD VARIABLE' ) + error = nf90_put_att(ncid_with_halo, id_data, "missing_value", missing) + call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) + error = nf90_put_att(ncid_with_halo, id_data, "coordinates", "geolon geolat") + call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) + enddo + + error = nf90_enddef(ncid_with_halo, header_buffer_val,4,0,4) + call netcdf_err(error, 'WRITING HEADER ENDDEF' ) + + error = nf90_put_var(ncid_with_halo, id_times, day_of_rec) + call netcdf_err(error, 'WRITING TIME VARIABLE' ) + + error = nf90_put_var( ncid_with_halo, id_lat, lat_one_tile, & + start=(/1,1/), count=(/i_mdl,j_mdl/)) + call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLAT' ) + + error = nf90_put_var( ncid_with_halo, id_lon, lon_one_tile, & + start=(/1,1/), count=(/i_mdl,j_mdl/)) + call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLON' ) + + endif + + print*,'- WRITE DATA FOR RECORD: ',record + error = nf90_inq_varid(ncid_with_halo, field_names(field_idx), id_data) + call netcdf_err(error, 'IN NF90_INQ_VARID' ) + + error = nf90_put_var(ncid_with_halo, id_data, data_one_tile, & + start=(/1,1,time/), count=(/i_mdl,j_mdl,1/)) + call netcdf_err(error, 'IN NF90_PUT_VAR' ) + + if (record == num_records) then + error = nf90_close(ncid_with_halo) + endif + + return + + end subroutine output2 diff --git a/sorc/sfc_climo_gen.fd/search2.f90 b/sorc/sfc_climo_gen.fd/search2.f90 new file mode 100644 index 000000000..2aad8cead --- /dev/null +++ b/sorc/sfc_climo_gen.fd/search2.f90 @@ -0,0 +1,146 @@ +!> @file +!! @brief Replace undefined values on the model grid with a valid +!! value at a nearby neighbor. +!! @author George Gayno @date 2018 + +!> Replace undefined values on the model grid with a valid +!! value at a nearby neighbor. Undefined values are typically +!! associated with isolated islands where there is no source data. +!! Routine searches a neighborhood with a radius of 100 grid points. +!! If no valid value is found, a default value is used. This +!! routine works for one tile of a cubed sphere grid. It does +!! not consider valid values at adjacent faces. That is a future +!! upgrade. +!! +!! @param[inout] field - input: field before missing values are replaced +!! - output: field after missing values are replaced +!! @param[in] mask field bitmap. Field defined where mask=1 +!! @param[inout] idim i dimension of tile +!! @param[inout] jdim j dimension of tile +!! @param[in] tile tile number +!! @param[in] field_name field name +!! @author George Gayno @date 2018 + subroutine search2 (field, mask, idim, jdim, tile, field_name) + + use mpi + use esmf + + implicit none + + character(len=*) :: field_name + + integer, intent(in) :: idim, jdim, tile + integer(esmf_kind_i4), intent(in) :: mask(idim,jdim) + + real(esmf_kind_r4), intent(inout) :: field(idim,jdim,20) + + integer :: i, j, krad, ii, jj + integer :: istart, iend + integer :: jstart, jend + integer :: ierr + + real :: default_value + real(esmf_kind_r4), allocatable :: field_save(:,:,:) + +!----------------------------------------------------------------------- +! Set default value. +!----------------------------------------------------------------------- + + + select case (field_name) + case ('substrate_temperature') ! soil substrate_temperature + default_value = 280.0 + case ('vegetation_greenness') ! vegetation greenness + default_value = 0.5 + case ('maximum_snow_albedo') ! maximum snow albedo + default_value = 0.5 + case ('leaf_area_index') ! leaf area index + default_value = 1.0 + case ('visible_black_sky_albedo') ! visible black sky albedo + default_value = 0.1 + case ('visible_white_sky_albedo') ! visible white sky albedo + default_value = 0.1 + case ('near_IR_black_sky_albedo') ! near IR black sky albedo + default_value = 0.2 + case ('near_IR_white_sky_albedo') ! near IR white sky albedo + default_value = 0.2 + case ('facsf') ! facsf + default_value = 0.5 + case ('facwf') ! facwf + default_value = 0.5 + case ('slope_type') ! slope type + default_value = float(1) + case ('soil_type') ! soil type + default_value = float(2) + case ('vegetation_type') ! vegetation type + default_value = float(3) + case default + print*,'- FATAL ERROR IN ROUTINE SEARCH. UNIDENTIFIED FIELD : ', field + call mpi_abort(mpi_comm_world, 77, ierr) + end select + +!----------------------------------------------------------------------- +! Perform search and replace. +!----------------------------------------------------------------------- + + allocate (field_save(idim,jdim,20)) + field_save = field + + J_LOOP : do j = 1, jdim + I_LOOP : do i = 1, idim + + if (mask(i,j) == 1 .and. field_save(i,j,1) < -9999.0) then + + KRAD_LOOP : do krad = 1, 100 + + istart = i - krad + iend = i + krad + jstart = j - krad + jend = j + krad + + JJ_LOOP : do jj = jstart, jend + II_LOOP : do ii = istart, iend + +!----------------------------------------------------------------------- +! Search only along outer square. +!----------------------------------------------------------------------- + + if ((jj == jstart) .or. (jj == jend) .or. & + (ii == istart) .or. (ii == iend)) then + + if (jj < 1 .or. jj > jdim) cycle JJ_LOOP + if (ii < 1 .or. ii > idim) cycle II_LOOP + + print*,'in search ',ii,jj,mask(ii,jj),maxval(field_save(ii,jj,:)) + if (mask(ii,jj) == 1 .and. maxval(field_save(ii,jj,:)) > 0.0) then + field(i,j,:) = field_save(ii,jj,:) + write(6,100) tile,i,j,ii,jj,field(i,j,1) + cycle I_LOOP + endif + + endif + + enddo II_LOOP + enddo JJ_LOOP + + enddo KRAD_LOOP + + field(i,j,:) = 0.0 + field(i,j,nint(default_value)) = 1.0 ! Search failed. Use default value. + + write(6,101) tile,i,j,default_value + + endif + enddo I_LOOP + enddo J_LOOP + + print*,'after search 59/166 ',field(59,166,:) + print*,'after search 60/167 ',field(60,167,:) + print*,'after search 55/168 ',field(55,168,:) + print*,'after search 56/169 ',field(55,168,:) + deallocate(field_save) + + 100 format(1x,"- MISSING2 POINT TILE: ",i2," I/J: ",i5,i5," SET TO VALUE AT: ",i5,i5,". NEW VALUE IS: ",f8.3) + 101 format(1x,"- MISSING2 POINT TILE: ",i2," I/J: ",i5,i5," SET TO DEFAULT VALUE OF: ",f8.3) + + end subroutine search2 From 0a8f4fa4f7281205b23c52d9183fdc19749cee89 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Fri, 28 Oct 2022 19:50:49 +0000 Subject: [PATCH 02/50] Begin clean up of output routine. Fixes #709. --- sorc/sfc_climo_gen.fd/interp2.F90 | 15 +-- sorc/sfc_climo_gen.fd/output2.f90 | 158 ++++++++++++------------------ 2 files changed, 74 insertions(+), 99 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 index 013e12c33..a875fd880 100644 --- a/sorc/sfc_climo_gen.fd/interp2.F90 +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -31,7 +31,7 @@ subroutine interp2(localpet, method, input_file) integer :: varid, record integer :: tile_num, pt_loc_this_tile integer :: isrctermprocessing - integer :: category + integer :: category, num_categories integer(esmf_kind_i4), allocatable :: mask_mdl_one_tile(:,:) integer(esmf_kind_i4), pointer :: unmapped_ptr(:) @@ -52,13 +52,16 @@ subroutine interp2(localpet, method, input_file) type(esmf_routehandle) :: regrid_data type(esmf_polemethod_flag) :: pole +! get this from file. + num_categories = 20 + print*,"- CALL FieldCreate FOR SOURCE GRID DATA." data_field_src = ESMF_FieldCreate(grid_src, & typekind=ESMF_TYPEKIND_R4, & indexflag=ESMF_INDEX_GLOBAL, & staggerloc=ESMF_STAGGERLOC_CENTER, & ungriddedLBound=(/1/), & - ungriddedUBound=(/20/), & + ungriddedUBound=(/num_categories/), & name="source data", & rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -82,7 +85,7 @@ subroutine interp2(localpet, method, input_file) indexflag=ESMF_INDEX_GLOBAL, & staggerloc=ESMF_STAGGERLOC_CENTER, & ungriddedLBound=(/1/), & - ungriddedUBound=(/20/), & + ungriddedUBound=(/num_categories/), & name="mdl data", & rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -103,7 +106,7 @@ subroutine interp2(localpet, method, input_file) if (localpet == 0) then allocate(data_src_global(i_src,j_src)) - allocate(data_src_global2(i_src,j_src,20)) + allocate(data_src_global2(i_src,j_src,num_categories)) else allocate(data_src_global(0,0)) allocate(data_src_global2(0,0,0)) @@ -114,7 +117,7 @@ subroutine interp2(localpet, method, input_file) call netcdf_err(status, "IN ROUTINE INTERP OPENING SOURCE FILE") if (localpet == 0) then - allocate(data_mdl_one_tile(i_mdl,j_mdl,20)) + allocate(data_mdl_one_tile(i_mdl,j_mdl,num_categories)) allocate(mask_mdl_one_tile(i_mdl,j_mdl)) allocate(lat_mdl_one_tile(i_mdl,j_mdl)) allocate(lon_mdl_one_tile(i_mdl,j_mdl)) @@ -282,7 +285,7 @@ subroutine interp2(localpet, method, input_file) call search2 (data_mdl_one_tile, mask_mdl_one_tile, i_mdl, j_mdl, tile, field_names(n)) ! where(mask_mdl_one_tile == 0) data_mdl_one_tile = missing print*,'after regrid ',data_mdl_one_tile(i_mdl/2,j_mdl/2,:) - call output2 (data_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, tile, record, t, n) + call output2 (data_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile, record, t, n) endif print*,'after output ', localpet diff --git a/sorc/sfc_climo_gen.fd/output2.f90 b/sorc/sfc_climo_gen.fd/output2.f90 index 42357fb82..23e6a5b0d 100644 --- a/sorc/sfc_climo_gen.fd/output2.f90 +++ b/sorc/sfc_climo_gen.fd/output2.f90 @@ -16,7 +16,7 @@ !! @param[in] time Time period to be output. !! @author George Gayno @date 2018 subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & - tile, record, time, field_idx) + num_categories, tile, record, time, field_idx) use mpi use esmf @@ -29,17 +29,17 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & implicit none - integer, intent(in) :: i_mdl, j_mdl, tile + integer, intent(in) :: i_mdl, j_mdl, tile, num_categories integer, intent(in) :: record, time, field_idx - real(esmf_kind_r4), intent(in) :: data_one_tile(i_mdl,j_mdl,20) + real(esmf_kind_r4), intent(in) :: data_one_tile(i_mdl,j_mdl,num_categories) real(esmf_kind_r4) :: lat_one_tile(i_mdl,j_mdl) real(esmf_kind_r4), intent(in) :: lon_one_tile(i_mdl,j_mdl) character(len=200) :: out_file character(len=200) :: out_file_with_halo - integer :: initialsiz, fsize, error, j + integer :: error, j integer :: dim_x, dim_y, dim_z, id_data integer :: dim_time, id_times, ierr integer :: header_buffer_val = 16384 @@ -47,28 +47,11 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & integer :: i_start, i_end, j_start, j_end integer, save :: ncid(6), ncid_with_halo + print*,'num_time_recs/num_records/day_of_reo ',num_time_recs,num_records,day_of_rec + print*,'record time ',record, time + print*,'num fields ', num_fields + select case (field_names(field_idx)) - case ('substrate_temperature') - out_file = "./substrate_temperature." // grid_tiles(tile) // ".nc" - out_file_with_halo = "./substrate_temperature." // grid_tiles(tile) // ".halo.nc" - case ('vegetation_greenness') - out_file = "./vegetation_greenness." // grid_tiles(tile) // ".nc" - out_file_with_halo = "./vegetation_greenness." // grid_tiles(tile) // ".halo.nc" - case ('maximum_snow_albedo') - out_file = "./maximum_snow_albedo." // grid_tiles(tile) // ".nc" - out_file_with_halo = "./maximum_snow_albedo." // grid_tiles(tile) // ".halo.nc" - case ('leaf_area_index') - out_file = "./leaf_area_index." // grid_tiles(tile) // ".nc" - out_file_with_halo = "./leaf_area_index." // grid_tiles(tile) // ".halo.nc" - case ('visible_black_sky_albedo', 'visible_white_sky_albedo', 'near_IR_black_sky_albedo', 'near_IR_white_sky_albedo') - out_file = "./snowfree_albedo." // grid_tiles(tile) // ".nc" - out_file_with_halo = "./snowfree_albedo." // grid_tiles(tile) // ".halo.nc" - case ('facsf') - out_file = "./facsf." // grid_tiles(tile) // ".nc" - out_file_with_halo = "./facsf." // grid_tiles(tile) // ".halo.nc" - case ('slope_type') - out_file = "./slope_type." // grid_tiles(tile) // ".nc" - out_file_with_halo = "./slope_type." // grid_tiles(tile) // ".halo.nc" case ('soil_type') out_file = "./soil_type." // grid_tiles(tile) // ".nc" out_file_with_halo = "./soil_type." // grid_tiles(tile) // ".halo.nc" @@ -101,85 +84,77 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & i_out = i_end - i_start + 1 j_out = j_end - j_start + 1 - if (record == 1) then - - initialsiz = 0 - fsize = 65536 - error = nf90_create(out_file, IOR(NF90_NETCDF4,NF90_CLASSIC_MODEL), & - ncid(tile), initialsize=initialsiz, chunksize=fsize) - call netcdf_err(error, 'ERROR IN NF90_CREATE' ) - error = nf90_def_dim(ncid(tile), 'nx', i_out, dim_x) - call netcdf_err(error, 'DEFINING NX DIMENSION' ) - error = nf90_def_dim(ncid(tile), 'ny', j_out, dim_y) - call netcdf_err(error, 'DEFINING NY DIMENSION' ) - error = nf90_def_dim(ncid(tile), 'nz', 20, dim_z) - call netcdf_err(error, 'DEFINING NZ DIMENSION' ) - error = nf90_def_dim(ncid(tile), 'time', num_time_recs, dim_time) - call netcdf_err(error, 'DEFINING TIME DIMENSION' ) - error = nf90_def_var(ncid(tile), 'time', NF90_FLOAT, dim_time, id_times) - call netcdf_err(error, 'DEFINING TIME VARIABLE' ) - error = nf90_put_att(ncid(tile), id_times, "units", "days since 2015-1-1") - call netcdf_err(error, 'DEFINING TIME ATTRIBUTE' ) - if (len_trim(source) > 0) then - error = nf90_put_att(ncid(tile), nf90_global, 'source', source) - call netcdf_err(error, 'DEFINING GLOBAL SOURCE ATTRIBUTE' ) - endif - - error = nf90_def_var(ncid(tile), 'geolat', NF90_FLOAT, (/dim_x,dim_y/), id_lat) - call netcdf_err(error, 'DEFINING GEOLAT FIELD' ) - error = nf90_put_att(ncid(tile), id_lat, "long_name", "Latitude") - call netcdf_err(error, 'DEFINING GEOLAT NAME ATTRIBUTE' ) - error = nf90_put_att(ncid(tile), id_lat, "units", "degrees_north") - call netcdf_err(error, 'DEFINING GEOLAT UNIT ATTRIBUTE' ) - error = nf90_def_var(ncid(tile), 'geolon', NF90_FLOAT, (/dim_x,dim_y/), id_lon) - call netcdf_err(error, 'DEFINING GEOLON FIELD' ) - error = nf90_put_att(ncid(tile), id_lon, "long_name", "Longitude") - call netcdf_err(error, 'DEFINING GEOLON NAME ATTRIBUTE' ) - error = nf90_put_att(ncid(tile), id_lon, "units", "degrees_east") - call netcdf_err(error, 'DEFINING GEOLON UNIT ATTRIBUTE' ) - - do j = 1, num_fields - error = nf90_def_var(ncid(tile), trim(field_names(j)), NF90_FLOAT, (/dim_x,dim_y,dim_z,dim_time/), id_data) - call netcdf_err(error, 'DEFINING FIELD' ) - error = nf90_put_att(ncid(tile), id_data, "missing_value", missing) - call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid(tile), id_data, "coordinates", "geolon geolat") - call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) - error = nf90_def_var(ncid(tile), 'sum', NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_sum) - call netcdf_err(error, 'DEFINING FIELD' ) - enddo - - error = nf90_enddef(ncid(tile), header_buffer_val,4,0,4) - call netcdf_err(error, 'IN NF90_ENDDEF' ) - - error = nf90_put_var( ncid(tile), id_times, day_of_rec) - call netcdf_err(error, 'WRITING TIME FIELD' ) + error = nf90_create(out_file, NF90_NETCDF4, ncid(tile)) + call netcdf_err(error, 'ERROR IN NF90_CREATE' ) + error = nf90_def_dim(ncid(tile), 'nx', i_out, dim_x) + call netcdf_err(error, 'DEFINING NX DIMENSION' ) + error = nf90_def_dim(ncid(tile), 'ny', j_out, dim_y) + call netcdf_err(error, 'DEFINING NY DIMENSION' ) + error = nf90_def_dim(ncid(tile), 'num_categories', num_categories, dim_z) + call netcdf_err(error, 'DEFINING NZ DIMENSION' ) + error = nf90_def_dim(ncid(tile), 'time', num_time_recs, dim_time) + call netcdf_err(error, 'DEFINING TIME DIMENSION' ) + error = nf90_def_var(ncid(tile), 'time', NF90_FLOAT, dim_time, id_times) + call netcdf_err(error, 'DEFINING TIME VARIABLE' ) + error = nf90_put_att(ncid(tile), id_times, "units", "days since 2015-1-1") + call netcdf_err(error, 'DEFINING TIME ATTRIBUTE' ) + if (len_trim(source) > 0) then + error = nf90_put_att(ncid(tile), nf90_global, 'source', source) + call netcdf_err(error, 'DEFINING GLOBAL SOURCE ATTRIBUTE' ) + endif - error = nf90_put_var( ncid(tile), id_lat, lat_one_tile(i_start:i_end,j_start:j_end), & + error = nf90_def_var(ncid(tile), 'geolat', NF90_FLOAT, (/dim_x,dim_y/), id_lat) + call netcdf_err(error, 'DEFINING GEOLAT FIELD' ) + error = nf90_put_att(ncid(tile), id_lat, "long_name", "Latitude") + call netcdf_err(error, 'DEFINING GEOLAT NAME ATTRIBUTE' ) + error = nf90_put_att(ncid(tile), id_lat, "units", "degrees_north") + call netcdf_err(error, 'DEFINING GEOLAT UNIT ATTRIBUTE' ) + error = nf90_def_var(ncid(tile), 'geolon', NF90_FLOAT, (/dim_x,dim_y/), id_lon) + call netcdf_err(error, 'DEFINING GEOLON FIELD' ) + error = nf90_put_att(ncid(tile), id_lon, "long_name", "Longitude") + call netcdf_err(error, 'DEFINING GEOLON NAME ATTRIBUTE' ) + error = nf90_put_att(ncid(tile), id_lon, "units", "degrees_east") + call netcdf_err(error, 'DEFINING GEOLON UNIT ATTRIBUTE' ) + + error = nf90_def_var(ncid(tile), trim(field_names(1)), NF90_FLOAT, (/dim_x,dim_y,dim_z,dim_time/), id_data) + call netcdf_err(error, 'DEFINING FIELD' ) + error = nf90_put_att(ncid(tile), id_data, "units", "percent coverage each category") + call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) + error = nf90_put_att(ncid(tile), id_data, "missing_value", missing) + call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) + error = nf90_put_att(ncid(tile), id_data, "coordinates", "geolon geolat") + call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) + error = nf90_def_var(ncid(tile), 'sum', NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_sum) + call netcdf_err(error, 'DEFINING FIELD' ) + + error = nf90_enddef(ncid(tile), header_buffer_val,4,0,4) + call netcdf_err(error, 'IN NF90_ENDDEF' ) + + error = nf90_put_var( ncid(tile), id_times, day_of_rec) + call netcdf_err(error, 'WRITING TIME FIELD' ) + + error = nf90_put_var( ncid(tile), id_lat, lat_one_tile(i_start:i_end,j_start:j_end), & start=(/1,1/), count=(/i_out,j_out/)) - call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLAT' ) + call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLAT' ) - error = nf90_put_var( ncid(tile), id_lon, lon_one_tile(i_start:i_end,j_start:j_end), & + error = nf90_put_var( ncid(tile), id_lon, lon_one_tile(i_start:i_end,j_start:j_end), & start=(/1,1/), count=(/i_out,j_out/)) - call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLON' ) - - endif + call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLON' ) print*,'- WRITE DATA FOR RECORD: ',record error = nf90_inq_varid( ncid(tile), field_names(field_idx), id_data) call netcdf_err(error, 'IN NF90_INQ_VARID' ) error = nf90_put_var( ncid(tile), id_data, data_one_tile(i_start:i_end,j_start:j_end,:), & - start=(/1,1,1,time/), count=(/i_out,j_out,20,1/)) + start=(/1,1,1,time/), count=(/i_out,j_out,num_categories,1/)) call netcdf_err(error, 'IN NF90_PUT_VAR' ) -! reuse lat +! Temporary output of sum of %. +! reuse latitude array. lat_one_tile = sum(data_one_tile, dim=3) error = nf90_put_var( ncid(tile), id_sum, lat_one_tile(i_start:i_end,j_start:j_end), & start=(/1,1,time/), count=(/i_out,j_out,1/)) - if (record == num_records) then - error = nf90_close(ncid(tile)) - endif + error = nf90_close(ncid(tile)) print*,'after write' stop @@ -194,10 +169,7 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & if (record == 1) then - initialsiz = 0 - fsize = 65536 - error = nf90_create(out_file_with_halo, IOR(NF90_NETCDF4,NF90_CLASSIC_MODEL), & - ncid_with_halo, initialsize=initialsiz, chunksize=fsize) + error = nf90_create(out_file_with_halo, NF90_NETCDF4, ncid_with_halo) call netcdf_err(error, 'IN NF90_CREATE' ) error = nf90_def_dim(ncid_with_halo, 'nx', i_mdl, dim_x) call netcdf_err(error, 'DEFINING NX DIMENSION' ) From b5e90be56f8e37650277e3370ff8280751faa5aa Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Fri, 28 Oct 2022 21:14:02 +0000 Subject: [PATCH 03/50] More cleanup to output routine. Fixes #709. --- sorc/sfc_climo_gen.fd/interp2.F90 | 9 +- sorc/sfc_climo_gen.fd/output2.f90 | 143 ++++++++++++++---------------- 2 files changed, 73 insertions(+), 79 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 index a875fd880..086ac1891 100644 --- a/sorc/sfc_climo_gen.fd/interp2.F90 +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -43,6 +43,7 @@ subroutine interp2(localpet, method, input_file) real(esmf_kind_r4), allocatable :: data_mdl_one_tile(:,:,:) real(esmf_kind_r4), allocatable :: vegt_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: lat_mdl_one_tile(:,:) + real(esmf_kind_r4), allocatable :: sum_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: lon_mdl_one_tile(:,:) !type(esmf_regridmethod_flag),intent(in) :: method @@ -120,11 +121,13 @@ subroutine interp2(localpet, method, input_file) allocate(data_mdl_one_tile(i_mdl,j_mdl,num_categories)) allocate(mask_mdl_one_tile(i_mdl,j_mdl)) allocate(lat_mdl_one_tile(i_mdl,j_mdl)) + allocate(sum_mdl_one_tile(i_mdl,j_mdl)) allocate(lon_mdl_one_tile(i_mdl,j_mdl)) else allocate(data_mdl_one_tile(0,0,0)) allocate(mask_mdl_one_tile(0,0)) allocate(lat_mdl_one_tile(0,0)) + allocate(sum_mdl_one_tile(0,0)) allocate(lon_mdl_one_tile(0,0)) endif @@ -271,11 +274,11 @@ subroutine interp2(localpet, method, input_file) if (localpet == 0) then print*,'- CALL SEARCH FOR TILE ',tile - lat_mdl_one_tile = sum(data_mdl_one_tile, dim=3) ! use unused variable to now. + sum_mdl_one_tile = sum(data_mdl_one_tile, dim=3) ! use unused variable to now. do j = 1, j_mdl do i = 1, i_mdl - if (mask_mdl_one_tile(i,j) == 1 .and. lat_mdl_one_tile(i,j) == 0.0) then + if (mask_mdl_one_tile(i,j) == 1 .and. sum_mdl_one_tile(i,j) == 0.0) then data_mdl_one_tile(i,j,:) = -9999.9 endif @@ -285,7 +288,7 @@ subroutine interp2(localpet, method, input_file) call search2 (data_mdl_one_tile, mask_mdl_one_tile, i_mdl, j_mdl, tile, field_names(n)) ! where(mask_mdl_one_tile == 0) data_mdl_one_tile = missing print*,'after regrid ',data_mdl_one_tile(i_mdl/2,j_mdl/2,:) - call output2 (data_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile, record, t, n) + call output2 (data_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile, t, n) endif print*,'after output ', localpet diff --git a/sorc/sfc_climo_gen.fd/output2.f90 b/sorc/sfc_climo_gen.fd/output2.f90 index 23e6a5b0d..b90b70f99 100644 --- a/sorc/sfc_climo_gen.fd/output2.f90 +++ b/sorc/sfc_climo_gen.fd/output2.f90 @@ -11,35 +11,35 @@ !! @param[in] field_idx Index of field within field name array. !! @param[in] i_mdl i dimensions of tile. !! @param[in] j_mdl j dimensions of tile. -!! @param[in] record Record number to be output. !! @param[in] tile Tile number. !! @param[in] time Time period to be output. !! @author George Gayno @date 2018 subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & - num_categories, tile, record, time, field_idx) + num_categories, tile, time, field_idx) use mpi use esmf use netcdf use utils - use source_grid, only : field_names, source, num_fields, & - num_time_recs, num_records, day_of_rec + use source_grid, only : field_names, source, & + num_time_recs, day_of_rec use model_grid, only : missing, grid_tiles use program_setup, only : halo implicit none integer, intent(in) :: i_mdl, j_mdl, tile, num_categories - integer, intent(in) :: record, time, field_idx + integer, intent(in) :: time, field_idx real(esmf_kind_r4), intent(in) :: data_one_tile(i_mdl,j_mdl,num_categories) real(esmf_kind_r4) :: lat_one_tile(i_mdl,j_mdl) real(esmf_kind_r4), intent(in) :: lon_one_tile(i_mdl,j_mdl) + real(esmf_kind_r4) :: sum_one_tile(i_mdl,j_mdl) character(len=200) :: out_file character(len=200) :: out_file_with_halo - integer :: error, j + integer :: error integer :: dim_x, dim_y, dim_z, id_data integer :: dim_time, id_times, ierr integer :: header_buffer_val = 16384 @@ -47,10 +47,6 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & integer :: i_start, i_end, j_start, j_end integer, save :: ncid(6), ncid_with_halo - print*,'num_time_recs/num_records/day_of_reo ',num_time_recs,num_records,day_of_rec - print*,'record time ',record, time - print*,'num fields ', num_fields - select case (field_names(field_idx)) case ('soil_type') out_file = "./soil_type." // grid_tiles(tile) // ".nc" @@ -141,7 +137,7 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & start=(/1,1/), count=(/i_out,j_out/)) call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLON' ) - print*,'- WRITE DATA FOR RECORD: ',record + print*,'- WRITE DATA ' error = nf90_inq_varid( ncid(tile), field_names(field_idx), id_data) call netcdf_err(error, 'IN NF90_INQ_VARID' ) error = nf90_put_var( ncid(tile), id_data, data_one_tile(i_start:i_end,j_start:j_end,:), & @@ -149,16 +145,12 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & call netcdf_err(error, 'IN NF90_PUT_VAR' ) ! Temporary output of sum of %. -! reuse latitude array. - lat_one_tile = sum(data_one_tile, dim=3) - error = nf90_put_var( ncid(tile), id_sum, lat_one_tile(i_start:i_end,j_start:j_end), & + sum_one_tile = sum(data_one_tile, dim=3) + error = nf90_put_var( ncid(tile), id_sum, sum_one_tile(i_start:i_end,j_start:j_end), & start=(/1,1,time/), count=(/i_out,j_out,1/)) error = nf90_close(ncid(tile)) - print*,'after write' - stop - !---------------------------------------------------------------------- ! For regional nests, also output files including the halo !---------------------------------------------------------------------- @@ -167,74 +159,73 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & print*,"- WRITE OUT FILES THAT INCLUDE HALO REGION." - if (record == 1) then - - error = nf90_create(out_file_with_halo, NF90_NETCDF4, ncid_with_halo) - call netcdf_err(error, 'IN NF90_CREATE' ) - error = nf90_def_dim(ncid_with_halo, 'nx', i_mdl, dim_x) - call netcdf_err(error, 'DEFINING NX DIMENSION' ) - error = nf90_def_dim(ncid_with_halo, 'ny', j_mdl, dim_y) - call netcdf_err(error, 'DEFINING NY DIMENSION' ) - error = nf90_def_dim(ncid_with_halo, 'time', num_time_recs, dim_time) - call netcdf_err(error, 'DEFINING TIME DIMENSION' ) - error = nf90_def_var(ncid_with_halo, 'time', NF90_FLOAT, dim_time, id_times) - call netcdf_err(error, 'DEFINING TIME VARIABLE' ) - error = nf90_put_att(ncid_with_halo, id_times, "units", "days since 2015-1-1") - call netcdf_err(error, 'DEFINING TIME ATTRIBUTE' ) - if (len_trim(source) > 0) then - error = nf90_put_att(ncid_with_halo, nf90_global, 'source', source) - call netcdf_err(error, 'DEFINING GLOBAL SOURCE ATTRIBUTE' ) - endif - - error = nf90_def_var(ncid_with_halo, 'geolat', NF90_FLOAT, (/dim_x,dim_y/), id_lat) - call netcdf_err(error, 'DEFINING GEOLAT FIELD' ) - error = nf90_put_att(ncid_with_halo, id_lat, "long_name", "Latitude") - call netcdf_err(error, 'DEFINING GEOLAT NAME ATTRIBUTE' ) - error = nf90_put_att(ncid_with_halo, id_lat, "units", "degrees_north") - call netcdf_err(error, 'DEFINING GEOLAT UNIT ATTRIBUTE' ) - error = nf90_def_var(ncid_with_halo, 'geolon', NF90_FLOAT, (/dim_x,dim_y/), id_lon) - call netcdf_err(error, 'DEFINING GEOLON FIELD' ) - error = nf90_put_att(ncid_with_halo, id_lon, "long_name", "Longitude") - call netcdf_err(error, 'DEFINING GEOLON NAME ATTRIBUTE' ) - error = nf90_put_att(ncid_with_halo, id_lon, "units", "degrees_east") - call netcdf_err(error, 'DEFINING GEOLON UNIT ATTRIBUTE' ) - - do j = 1, num_fields - error = nf90_def_var(ncid_with_halo, field_names(j), NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_data) - call netcdf_err(error, 'DEFINING FIELD VARIABLE' ) - error = nf90_put_att(ncid_with_halo, id_data, "missing_value", missing) - call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid_with_halo, id_data, "coordinates", "geolon geolat") - call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) - enddo - - error = nf90_enddef(ncid_with_halo, header_buffer_val,4,0,4) - call netcdf_err(error, 'WRITING HEADER ENDDEF' ) - - error = nf90_put_var(ncid_with_halo, id_times, day_of_rec) - call netcdf_err(error, 'WRITING TIME VARIABLE' ) - - error = nf90_put_var( ncid_with_halo, id_lat, lat_one_tile, & - start=(/1,1/), count=(/i_mdl,j_mdl/)) - call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLAT' ) + error = nf90_create(out_file_with_halo, NF90_NETCDF4, ncid_with_halo) + call netcdf_err(error, 'IN NF90_CREATE' ) + error = nf90_def_dim(ncid_with_halo, 'nx', i_mdl, dim_x) + call netcdf_err(error, 'DEFINING NX DIMENSION' ) + error = nf90_def_dim(ncid_with_halo, 'ny', j_mdl, dim_y) + call netcdf_err(error, 'DEFINING NY DIMENSION' ) + error = nf90_def_dim(ncid(tile), 'num_categories', num_categories, dim_z) + call netcdf_err(error, 'DEFINING NZ DIMENSION' ) + error = nf90_def_dim(ncid_with_halo, 'time', num_time_recs, dim_time) + call netcdf_err(error, 'DEFINING TIME DIMENSION' ) + error = nf90_def_var(ncid_with_halo, 'time', NF90_FLOAT, dim_time, id_times) + call netcdf_err(error, 'DEFINING TIME VARIABLE' ) + error = nf90_put_att(ncid_with_halo, id_times, "units", "days since 2015-1-1") + call netcdf_err(error, 'DEFINING TIME ATTRIBUTE' ) + if (len_trim(source) > 0) then + error = nf90_put_att(ncid_with_halo, nf90_global, 'source', source) + call netcdf_err(error, 'DEFINING GLOBAL SOURCE ATTRIBUTE' ) + endif - error = nf90_put_var( ncid_with_halo, id_lon, lon_one_tile, & - start=(/1,1/), count=(/i_mdl,j_mdl/)) - call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLON' ) + error = nf90_def_var(ncid_with_halo, 'geolat', NF90_FLOAT, (/dim_x,dim_y/), id_lat) + call netcdf_err(error, 'DEFINING GEOLAT FIELD' ) + error = nf90_put_att(ncid_with_halo, id_lat, "long_name", "Latitude") + call netcdf_err(error, 'DEFINING GEOLAT NAME ATTRIBUTE' ) + error = nf90_put_att(ncid_with_halo, id_lat, "units", "degrees_north") + call netcdf_err(error, 'DEFINING GEOLAT UNIT ATTRIBUTE' ) + error = nf90_def_var(ncid_with_halo, 'geolon', NF90_FLOAT, (/dim_x,dim_y/), id_lon) + call netcdf_err(error, 'DEFINING GEOLON FIELD' ) + error = nf90_put_att(ncid_with_halo, id_lon, "long_name", "Longitude") + call netcdf_err(error, 'DEFINING GEOLON NAME ATTRIBUTE' ) + error = nf90_put_att(ncid_with_halo, id_lon, "units", "degrees_east") + call netcdf_err(error, 'DEFINING GEOLON UNIT ATTRIBUTE' ) - endif + error = nf90_def_var(ncid_with_halo, field_names(1), NF90_FLOAT, (/dim_x,dim_y,dim_z,dim_time/), id_data) + call netcdf_err(error, 'DEFINING FIELD VARIABLE' ) + error = nf90_put_att(ncid_with_halo, id_data, "units", "percent coverage each category") + call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) + error = nf90_put_att(ncid_with_halo, id_data, "missing_value", missing) + call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) + error = nf90_put_att(ncid_with_halo, id_data, "coordinates", "geolon geolat") + call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) + + error = nf90_enddef(ncid_with_halo, header_buffer_val,4,0,4) + call netcdf_err(error, 'WRITING HEADER ENDDEF' ) + + error = nf90_put_var(ncid_with_halo, id_times, day_of_rec) + call netcdf_err(error, 'WRITING TIME VARIABLE' ) - print*,'- WRITE DATA FOR RECORD: ',record + error = nf90_put_var( ncid_with_halo, id_lat, lat_one_tile, & + start=(/1,1/), count=(/i_mdl,j_mdl/)) + call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLAT' ) + + error = nf90_put_var( ncid_with_halo, id_lon, lon_one_tile, & + start=(/1,1/), count=(/i_mdl,j_mdl/)) + call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLON' ) + + print*,'- WRITE DATA' error = nf90_inq_varid(ncid_with_halo, field_names(field_idx), id_data) call netcdf_err(error, 'IN NF90_INQ_VARID' ) error = nf90_put_var(ncid_with_halo, id_data, data_one_tile, & - start=(/1,1,time/), count=(/i_mdl,j_mdl,1/)) + start=(/1,1,1,time/), count=(/i_mdl,j_mdl,num_categories,1/)) call netcdf_err(error, 'IN NF90_PUT_VAR' ) - if (record == num_records) then - error = nf90_close(ncid_with_halo) - endif + error = nf90_close(ncid_with_halo) + + call mpi_barrier(mpi_comm_world, error) + stop return From e90969d369bad94d3b6dfc47c910918bff075ce8 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Mon, 31 Oct 2022 14:14:24 +0000 Subject: [PATCH 04/50] Some cleanup to new search routine. Fixes #709. --- sorc/sfc_climo_gen.fd/interp2.F90 | 2 +- sorc/sfc_climo_gen.fd/search2.f90 | 57 +++++++++++-------------------- 2 files changed, 20 insertions(+), 39 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 index 086ac1891..85f9e5c3e 100644 --- a/sorc/sfc_climo_gen.fd/interp2.F90 +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -285,7 +285,7 @@ subroutine interp2(localpet, method, input_file) enddo enddo - call search2 (data_mdl_one_tile, mask_mdl_one_tile, i_mdl, j_mdl, tile, field_names(n)) + call search2 (data_mdl_one_tile, mask_mdl_one_tile, i_mdl, j_mdl, num_categories, tile, field_names(n)) ! where(mask_mdl_one_tile == 0) data_mdl_one_tile = missing print*,'after regrid ',data_mdl_one_tile(i_mdl/2,j_mdl/2,:) call output2 (data_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile, t, n) diff --git a/sorc/sfc_climo_gen.fd/search2.f90 b/sorc/sfc_climo_gen.fd/search2.f90 index 2aad8cead..5246bfb3f 100644 --- a/sorc/sfc_climo_gen.fd/search2.f90 +++ b/sorc/sfc_climo_gen.fd/search2.f90 @@ -1,7 +1,8 @@ !> @file !! @brief Replace undefined values on the model grid with a valid -!! value at a nearby neighbor. -!! @author George Gayno @date 2018 +!! value at a nearby neighbor. This routine works for fractional +!! categorical fields. +!! @author George Gayno @date 2022 !> Replace undefined values on the model grid with a valid !! value at a nearby neighbor. Undefined values are typically @@ -12,15 +13,18 @@ !! not consider valid values at adjacent faces. That is a future !! upgrade. !! +!! @note This routine works for fractional categorical fields. +!! !! @param[inout] field - input: field before missing values are replaced !! - output: field after missing values are replaced !! @param[in] mask field bitmap. Field defined where mask=1 -!! @param[inout] idim i dimension of tile -!! @param[inout] jdim j dimension of tile +!! @param[in] idim i dimension of tile +!! @param[in] jdim j dimension of tile +!! @param[in] num_categories number of veg/soil categories !! @param[in] tile tile number !! @param[in] field_name field name -!! @author George Gayno @date 2018 - subroutine search2 (field, mask, idim, jdim, tile, field_name) +!! @author George Gayno @date 2022 + subroutine search2 (field, mask, idim, jdim, num_categories, tile, field_name) use mpi use esmf @@ -29,51 +33,28 @@ subroutine search2 (field, mask, idim, jdim, tile, field_name) character(len=*) :: field_name - integer, intent(in) :: idim, jdim, tile + integer, intent(in) :: idim, jdim, tile, num_categories integer(esmf_kind_i4), intent(in) :: mask(idim,jdim) - real(esmf_kind_r4), intent(inout) :: field(idim,jdim,20) + real(esmf_kind_r4), intent(inout) :: field(idim,jdim,num_categories) integer :: i, j, krad, ii, jj integer :: istart, iend integer :: jstart, jend integer :: ierr + integer :: default_category - real :: default_value real(esmf_kind_r4), allocatable :: field_save(:,:,:) !----------------------------------------------------------------------- -! Set default value. +! Set default category. !----------------------------------------------------------------------- - select case (field_name) - case ('substrate_temperature') ! soil substrate_temperature - default_value = 280.0 - case ('vegetation_greenness') ! vegetation greenness - default_value = 0.5 - case ('maximum_snow_albedo') ! maximum snow albedo - default_value = 0.5 - case ('leaf_area_index') ! leaf area index - default_value = 1.0 - case ('visible_black_sky_albedo') ! visible black sky albedo - default_value = 0.1 - case ('visible_white_sky_albedo') ! visible white sky albedo - default_value = 0.1 - case ('near_IR_black_sky_albedo') ! near IR black sky albedo - default_value = 0.2 - case ('near_IR_white_sky_albedo') ! near IR white sky albedo - default_value = 0.2 - case ('facsf') ! facsf - default_value = 0.5 - case ('facwf') ! facwf - default_value = 0.5 - case ('slope_type') ! slope type - default_value = float(1) case ('soil_type') ! soil type - default_value = float(2) + default_category = 3 case ('vegetation_type') ! vegetation type - default_value = float(3) + default_category = 3 case default print*,'- FATAL ERROR IN ROUTINE SEARCH. UNIDENTIFIED FIELD : ', field call mpi_abort(mpi_comm_world, 77, ierr) @@ -83,7 +64,7 @@ subroutine search2 (field, mask, idim, jdim, tile, field_name) ! Perform search and replace. !----------------------------------------------------------------------- - allocate (field_save(idim,jdim,20)) + allocate (field_save(idim,jdim,num_categories)) field_save = field J_LOOP : do j = 1, jdim @@ -126,9 +107,9 @@ subroutine search2 (field, mask, idim, jdim, tile, field_name) enddo KRAD_LOOP field(i,j,:) = 0.0 - field(i,j,nint(default_value)) = 1.0 ! Search failed. Use default value. + field(i,j,default_category) = 1.0 ! Search failed. Use 100% of default category. - write(6,101) tile,i,j,default_value + write(6,101) tile,i,j,default_category endif enddo I_LOOP From 6b2834ad2b4c9dbd7c548edef3eec408ec0e50e2 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Mon, 31 Oct 2022 14:31:52 +0000 Subject: [PATCH 05/50] Some cleanup to interp2. Fixes #709. --- sorc/sfc_climo_gen.fd/interp2.F90 | 101 ------------------------------ 1 file changed, 101 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 index 85f9e5c3e..c17786cfe 100644 --- a/sorc/sfc_climo_gen.fd/interp2.F90 +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -27,7 +27,6 @@ subroutine interp2(localpet, method, input_file) integer :: i, j, ij, tile, n, ncid, status integer :: l(1), u(1), t integer :: clb_mdl(3), cub_mdl(3) - integer :: clb_src(3), cub_src(3) integer :: varid, record integer :: tile_num, pt_loc_this_tile integer :: isrctermprocessing @@ -37,7 +36,6 @@ subroutine interp2(localpet, method, input_file) integer(esmf_kind_i4), pointer :: unmapped_ptr(:) real(esmf_kind_r4), pointer :: data_mdl_ptr(:,:,:) - real(esmf_kind_r4), pointer :: data_src_ptr(:,:,:) real(esmf_kind_r4), allocatable :: data_src_global(:,:) real(esmf_kind_r4), allocatable :: data_src_global2(:,:,:) real(esmf_kind_r4), allocatable :: data_mdl_one_tile(:,:,:) @@ -68,18 +66,6 @@ subroutine interp2(localpet, method, input_file) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) - print*,"- CALL FieldGet FOR SOURCE GRID DATA." - nullify(data_src_ptr) - call ESMF_FieldGet(data_field_src, & - farrayPtr=data_src_ptr, & - computationalLBound=clb_src, & - computationalUBound=cub_src, & - rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,'got here ',localpet,clb_src,cub_src - print*,"- CALL FieldCreate FOR model GRID veg DATA." data_field_mdl2 = ESMF_FieldCreate(grid_mdl, & typekind=ESMF_TYPEKIND_R4, & @@ -321,90 +307,3 @@ subroutine interp2(localpet, method, input_file) call ESMF_FieldDestroy(data_field_src, rc=rc) end subroutine interp2 - -!> Ensure consistent fields at land ice points. -!! Land ice is vegetation type 15 (variable landice). -!! output is Model field. -!! -!! @param[in] field Model field before adjustments for land ice. -!! @param[in] vegt Vegetation type on the model tile. -!! @param[inout] idim i dimension of model tile. -!! @param[inout] jdim j dimension of model tile. -!! @param[in] field_ch Field name. -!! @author George Gayno NCEP/EMC - subroutine adjust_for_landice2(field, vegt, idim, jdim, field_ch) - - use esmf - use mpi - - implicit none - - character(len=*), intent(in) :: field_ch - - integer, intent(in) :: idim, jdim - - real(esmf_kind_i4), intent(in) :: vegt(idim,jdim) - real(esmf_kind_r4), intent(inout) :: field(idim,jdim) - - integer, parameter :: landice=15 - - integer :: i, j, ierr - - real :: landice_value - - select case (field_ch) - case ('substrate_temperature') ! soil substrate temp - landice_value = 273.15 - do j = 1, jdim - do i = 1, idim - if (nint(vegt(i,j)) == landice) then - field(i,j) = min(field(i,j), landice_value) - endif - enddo - enddo - case ('vegetation_greenness') ! vegetation greenness - landice_value = 0.01 ! 1.0% is bare ground - do j = 1, jdim - do i = 1, idim - if (nint(vegt(i,j)) == landice) then - field(i,j) = landice_value - endif - enddo - enddo - case ('leaf_area_index') ! leaf area index - landice_value = 0.0 ! bare ground - do j = 1, jdim - do i = 1, idim - if (nint(vegt(i,j)) == landice) then - field(i,j) = landice_value - endif - enddo - enddo - case ('slope_type') ! slope type - landice_value = 9.0 - do j = 1, jdim - do i = 1, idim - if (nint(vegt(i,j)) == landice) then - field(i,j) = landice_value - else - if (nint(field(i,j)) == nint(landice_value)) field(i,j) = 2.0 - endif - enddo - enddo - case ('soil_type') ! soil type - landice_value = 16.0 - do j = 1, jdim - do i = 1, idim - if (nint(vegt(i,j)) == landice) then - field(i,j) = landice_value - else - if (nint(field(i,j)) == nint(landice_value)) field(i,j) = 6.0 - endif - enddo - enddo - case default - print*,'- FATAL ERROR IN ROUTINE ADJUST_FOR_LANDICE. UNIDENTIFIED FIELD : ', field_ch - call mpi_abort(mpi_comm_world, 57, ierr) - end select - - end subroutine adjust_for_landice2 From 46db839b6272f8d5b377f07be87a68837e97401f Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Mon, 31 Oct 2022 15:00:45 +0000 Subject: [PATCH 06/50] More interp2 cleanup. Fixes #709. --- sorc/sfc_climo_gen.fd/driver.F90 | 2 +- sorc/sfc_climo_gen.fd/interp2.F90 | 43 +++---------------------------- 2 files changed, 5 insertions(+), 40 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/driver.F90 b/sorc/sfc_climo_gen.fd/driver.F90 index 59fed8652..b7a233b0f 100644 --- a/sorc/sfc_climo_gen.fd/driver.F90 +++ b/sorc/sfc_climo_gen.fd/driver.F90 @@ -81,7 +81,7 @@ program driver call define_source_grid(localpet, npets, input_vegetation_type_file) method=ESMF_REGRIDMETHOD_NEAREST_STOD - call interp2(localpet, method, input_vegetation_type_file) + call interp2(localpet, input_vegetation_type_file) call source_grid_cleanup ! Snow free albedo diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 index c17786cfe..bf4ccba05 100644 --- a/sorc/sfc_climo_gen.fd/interp2.F90 +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -7,10 +7,9 @@ !! model grid. !! !! @param[in] localpet this mpi task -!! @param[in] method interpolation method.defined where mask=1 !! @param[in] input_file filename of input source data. !! @author George Gayno @date 2018 - subroutine interp2(localpet, method, input_file) + subroutine interp2(localpet, input_file) use esmf use netcdf @@ -24,11 +23,10 @@ subroutine interp2(localpet, method, input_file) character(len=*), intent(in) :: input_file integer :: rc, localpet - integer :: i, j, ij, tile, n, ncid, status - integer :: l(1), u(1), t + integer :: i, j, tile, n, ncid, status + integer :: t integer :: clb_mdl(3), cub_mdl(3) integer :: varid, record - integer :: tile_num, pt_loc_this_tile integer :: isrctermprocessing integer :: category, num_categories @@ -44,7 +42,6 @@ subroutine interp2(localpet, method, input_file) real(esmf_kind_r4), allocatable :: sum_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: lon_mdl_one_tile(:,:) -!type(esmf_regridmethod_flag),intent(in) :: method type(esmf_regridmethod_flag) :: method type(esmf_field) :: data_field_src type(esmf_field) :: data_field_mdl2 @@ -151,13 +148,7 @@ subroutine interp2(localpet, method, input_file) if (record == 1) then method = ESMF_REGRIDMETHOD_CONSERVE - - if (method == ESMF_REGRIDMETHOD_BILINEAR) then - pole = ESMF_POLEMETHOD_ALLAVG - else - pole = ESMF_POLEMETHOD_NONE - endif - + pole = ESMF_POLEMETHOD_NONE print*,"- CALL FieldRegridStore." nullify(unmapped_ptr) @@ -202,32 +193,6 @@ subroutine interp2(localpet, method, input_file) ! will be replaced in routine "search". !----------------------------------------------------------------------- - l = lbound(unmapped_ptr) - u = ubound(unmapped_ptr) -! do ij = l(1), u(1) - -! tile_num = ((unmapped_ptr(ij)-1) / (i_mdl*j_mdl)) ! tile number minus 1 -! pt_loc_this_tile = unmapped_ptr(ij) - (tile_num * i_mdl * j_mdl) - ! "ij" location of point within tile. - -! j = (pt_loc_this_tile - 1) / i_mdl + 1 -! i = mod(pt_loc_this_tile, i_mdl) -! if (i==0) i = i_mdl -! data_mdl_ptr(i,j,:) = -9999.9 - -! enddo - -! These fields are adjusted at landice. - -! select case (trim(field_names(n))) -! case ('substrate_temperature','vegetation_greenness','leaf_area_index','slope_type','soil_type') -! if (localpet == 0) then -! allocate(vegt_mdl_one_tile(i_mdl,j_mdl)) -! else -! allocate(vegt_mdl_one_tile(0,0)) -! endif -! end select - OUTPUT_LOOP : do tile = 1, num_tiles print*,"- CALL FieldGather FOR MODEL LATITUDE." From cae15a1f3554d8275df315f242050fe5c032ae9f Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Mon, 31 Oct 2022 19:19:59 +0000 Subject: [PATCH 07/50] More cleanup to interp2 and output2. Fixes #709. --- sorc/sfc_climo_gen.fd/interp2.F90 | 256 +++++++++++------------------- sorc/sfc_climo_gen.fd/output2.f90 | 13 +- 2 files changed, 104 insertions(+), 165 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 index bf4ccba05..8f9cba6f2 100644 --- a/sorc/sfc_climo_gen.fd/interp2.F90 +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -13,7 +13,9 @@ subroutine interp2(localpet, input_file) use esmf use netcdf - use model_grid + use model_grid, only : grid_mdl, i_mdl, j_mdl, & + num_tiles, latitude_field_mdl, & + longitude_field_mdl, mask_field_mdl use source_grid use utils use mpi @@ -23,33 +25,46 @@ subroutine interp2(localpet, input_file) character(len=*), intent(in) :: input_file integer :: rc, localpet - integer :: i, j, tile, n, ncid, status - integer :: t - integer :: clb_mdl(3), cub_mdl(3) - integer :: varid, record + integer :: i, j, tile, ncid, status + integer :: varid integer :: isrctermprocessing integer :: category, num_categories integer(esmf_kind_i4), allocatable :: mask_mdl_one_tile(:,:) integer(esmf_kind_i4), pointer :: unmapped_ptr(:) - real(esmf_kind_r4), pointer :: data_mdl_ptr(:,:,:) real(esmf_kind_r4), allocatable :: data_src_global(:,:) real(esmf_kind_r4), allocatable :: data_src_global2(:,:,:) real(esmf_kind_r4), allocatable :: data_mdl_one_tile(:,:,:) - real(esmf_kind_r4), allocatable :: vegt_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: lat_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: sum_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: lon_mdl_one_tile(:,:) type(esmf_regridmethod_flag) :: method type(esmf_field) :: data_field_src - type(esmf_field) :: data_field_mdl2 + type(esmf_field) :: data_field_mdl type(esmf_routehandle) :: regrid_data type(esmf_polemethod_flag) :: pole -! get this from file. - num_categories = 20 + if (localpet == 0) then + allocate(data_src_global(i_src,j_src)) + else + allocate(data_src_global(0,0)) + endif + + if (localpet == 0) then + print*,'- OPEN SOURCE FILE ', trim(input_file) + status = nf90_open(input_file, nf90_nowrite, ncid) + call netcdf_err(status, "IN ROUTINE INTERP OPENING SOURCE FILE") + status = nf90_inq_varid(ncid, field_names(1), varid) + call netcdf_err(status, "IN ROUTINE INTERP READING FIELD ID") + status = nf90_get_var(ncid, varid, data_src_global, start=(/1,1,1/), count=(/i_src,j_src,1/)) + call netcdf_err(status, "IN ROUTINE INTERP READING FIELD") + print*,'number of cats ',maxval(data_src_global) + num_categories = nint(maxval(data_src_global)) + endif + + call mpi_bcast(num_categories,1,MPI_INTEGER,0,MPI_COMM_WORLD,status) print*,"- CALL FieldCreate FOR SOURCE GRID DATA." data_field_src = ESMF_FieldCreate(grid_src, & @@ -64,7 +79,7 @@ subroutine interp2(localpet, input_file) call error_handler("IN FieldCreate", rc) print*,"- CALL FieldCreate FOR model GRID veg DATA." - data_field_mdl2 = ESMF_FieldCreate(grid_mdl, & + data_field_mdl = ESMF_FieldCreate(grid_mdl, & typekind=ESMF_TYPEKIND_R4, & indexflag=ESMF_INDEX_GLOBAL, & staggerloc=ESMF_STAGGERLOC_CENTER, & @@ -75,38 +90,15 @@ subroutine interp2(localpet, input_file) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) - print*,"- CALL FieldGet FOR MODEL GRID DATA." - nullify(data_mdl_ptr) - call ESMF_FieldGet(data_field_mdl2, & - farrayPtr=data_mdl_ptr, & - computationalLBound=clb_mdl, & - computationalUBound=cub_mdl, & - rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - - print*,'got here2 ',localpet,clb_mdl,cub_mdl - if (localpet == 0) then - allocate(data_src_global(i_src,j_src)) allocate(data_src_global2(i_src,j_src,num_categories)) - else - allocate(data_src_global(0,0)) - allocate(data_src_global2(0,0,0)) - endif - - print*,'- OPEN SOURCE FILE ', trim(input_file) - status = nf90_open(input_file, nf90_nowrite, ncid) - call netcdf_err(status, "IN ROUTINE INTERP OPENING SOURCE FILE") - - if (localpet == 0) then allocate(data_mdl_one_tile(i_mdl,j_mdl,num_categories)) allocate(mask_mdl_one_tile(i_mdl,j_mdl)) allocate(lat_mdl_one_tile(i_mdl,j_mdl)) allocate(sum_mdl_one_tile(i_mdl,j_mdl)) allocate(lon_mdl_one_tile(i_mdl,j_mdl)) else + allocate(data_src_global2(0,0,0)) allocate(data_mdl_one_tile(0,0,0)) allocate(mask_mdl_one_tile(0,0)) allocate(lat_mdl_one_tile(0,0)) @@ -114,46 +106,33 @@ subroutine interp2(localpet, input_file) allocate(lon_mdl_one_tile(0,0)) endif - record = 0 - - TIME_LOOP : do t = 1, num_time_recs ! loop over each time period - - FIELD_LOOP : do n = 1, num_fields ! loop over each surface field. - - record = record + 1 - - if (localpet == 0) then - status = nf90_inq_varid(ncid, field_names(n), varid) - call netcdf_err(status, "IN ROUTINE INTERP READING FIELD ID") - status = nf90_get_var(ncid, varid, data_src_global, start=(/1,1,t/), count=(/i_src,j_src,1/)) - call netcdf_err(status, "IN ROUTINE INTERP READING FIELD") - data_src_global2 = 0.0 - do j = 1, j_src - do i = 1, i_src - category = nint(data_src_global(i,j)) -! if (category < 1) category = 17 - if (category < 1) cycle - data_src_global2(i,j,category) = 1.0 - enddo - enddo - endif + if (localpet == 0) then + data_src_global2 = 0.0 + do j = 1, j_src + do i = 1, i_src + category = nint(data_src_global(i,j)) + if (category < 1) cycle + data_src_global2(i,j,category) = 1.0 + enddo + enddo + endif - print*,"- CALL FieldScatter FOR SOURCE GRID DATA." - call ESMF_FieldScatter(data_field_src, data_src_global2, rootPet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter.", rc) + deallocate(data_src_global) - isrctermprocessing = 1 + print*,"- CALL FieldScatter FOR SOURCE GRID DATA." + call ESMF_FieldScatter(data_field_src, data_src_global2, rootPet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter.", rc) - if (record == 1) then + isrctermprocessing = 1 - method = ESMF_REGRIDMETHOD_CONSERVE - pole = ESMF_POLEMETHOD_NONE + method = ESMF_REGRIDMETHOD_CONSERVE + pole = ESMF_POLEMETHOD_NONE - print*,"- CALL FieldRegridStore." - nullify(unmapped_ptr) - call ESMF_FieldRegridStore(data_field_src, & - data_field_mdl2, & + print*,"- CALL FieldRegridStore." + nullify(unmapped_ptr) + call ESMF_FieldRegridStore(data_field_src, & + data_field_mdl, & srcmaskvalues=(/0/), & dstmaskvalues=(/0/), & polemethod=pole, & @@ -164,106 +143,61 @@ subroutine interp2(localpet, input_file) regridmethod=method, & unmappedDstList=unmapped_ptr, & rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegridStore.", rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegridStore.", rc) + + print*,"- CALL Field_Regrid." + call ESMF_FieldRegrid(data_field_src, & + data_field_mdl, & + routehandle=regrid_data, & + termorderflag=ESMF_TERMORDER_SRCSEQ, & + rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegrid.", rc) - endif + OUTPUT_LOOP : do tile = 1, num_tiles - print*,"- CALL Field_Regrid." - call ESMF_FieldRegrid(data_field_src, & - data_field_mdl2, & - routehandle=regrid_data, & - termorderflag=ESMF_TERMORDER_SRCSEQ, & - rc=rc) + print*,"- CALL FieldGather FOR MODEL LATITUDE." + call ESMF_FieldGather(latitude_field_mdl, lat_mdl_one_tile, rootPet=0, tile=tile, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid.", rc) - -!----------------------------------------------------------------------- -! Unmapped points are stored in "unmapped_ptr". The pointer contains -! "ij" global indices as follows: -! -! tile 1: 1 thru (itile*jtile) -! tile n: (n-1)*(itile*jtile) thru n*(itile*jtile) -! -! This "ij" index is converted to the tile number and i/j index of the -! field object. This logic assumes the model grid object was -! created using "GLOBAL" indices. -! -! Unmapped data points are given the flag value of -9999.9, which -! will be replaced in routine "search". -!----------------------------------------------------------------------- - - OUTPUT_LOOP : do tile = 1, num_tiles - - print*,"- CALL FieldGather FOR MODEL LATITUDE." - call ESMF_FieldGather(latitude_field_mdl, lat_mdl_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather.", rc) - - print*,"- CALL FieldGather FOR MODEL LONGITUDE." - call ESMF_FieldGather(longitude_field_mdl, lon_mdl_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather.", rc) - - print*,"- CALL FieldGather FOR MODEL GRID DATA." - call ESMF_FieldGather(data_field_mdl2, data_mdl_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather.", rc) - - print*,"- CALL FieldGather FOR MODEL GRID LAND MASK." - call ESMF_FieldGather(mask_field_mdl, mask_mdl_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather.", rc) - - select case (trim(field_names(n))) - case ('substrate_temperature','vegetation_greenness','leaf_area_index','slope_type','soil_type') - print*,"- CALL FieldGather FOR MODEL GRID VEG TYPE." - call ESMF_FieldGather(vegt_field_mdl, vegt_mdl_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather.", rc) - end select - - if (localpet == 0) then - print*,'- CALL SEARCH FOR TILE ',tile - sum_mdl_one_tile = sum(data_mdl_one_tile, dim=3) ! use unused variable to now. - do j = 1, j_mdl - do i = 1, i_mdl - - if (mask_mdl_one_tile(i,j) == 1 .and. sum_mdl_one_tile(i,j) == 0.0) then - data_mdl_one_tile(i,j,:) = -9999.9 - endif - - enddo - enddo + call error_handler("IN FieldGather.", rc) - call search2 (data_mdl_one_tile, mask_mdl_one_tile, i_mdl, j_mdl, num_categories, tile, field_names(n)) -! where(mask_mdl_one_tile == 0) data_mdl_one_tile = missing - print*,'after regrid ',data_mdl_one_tile(i_mdl/2,j_mdl/2,:) - call output2 (data_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile, t, n) - endif - - print*,'after output ', localpet - call mpi_barrier(mpi_comm_world, rc) - stop + print*,"- CALL FieldGather FOR MODEL LONGITUDE." + call ESMF_FieldGather(longitude_field_mdl, lon_mdl_one_tile, rootPet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather.", rc) -! if (field_names(n) == 'vegetation_type') then -! print*,"- CALL FieldScatter FOR MODEL GRID VEGETATION TYPE." -! call ESMF_FieldScatter(vegt_field_mdl, data_mdl_one_tile, rootPet=0, tile=tile, rc=rc) -! if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & -! call error_handler("IN FieldScatter.", rc) -! endif + print*,"- CALL FieldGather FOR MODEL GRID DATA." + call ESMF_FieldGather(data_field_mdl, data_mdl_one_tile, rootPet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather.", rc) - enddo OUTPUT_LOOP + print*,"- CALL FieldGather FOR MODEL GRID LAND MASK." + call ESMF_FieldGather(mask_field_mdl, mask_mdl_one_tile, rootPet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather.", rc) - if (allocated(vegt_mdl_one_tile)) deallocate(vegt_mdl_one_tile) + if (localpet == 0) then + print*,'- CALL SEARCH FOR TILE ',tile + sum_mdl_one_tile = sum(data_mdl_one_tile, dim=3) ! use unused variable to now. + do j = 1, j_mdl + do i = 1, i_mdl + if (mask_mdl_one_tile(i,j) == 1 .and. sum_mdl_one_tile(i,j) == 0.0) then + data_mdl_one_tile(i,j,:) = -9999.9 + endif + enddo + enddo + call search2 (data_mdl_one_tile, mask_mdl_one_tile, i_mdl, j_mdl, num_categories, tile, field_names(1)) + print*,'after regrid ',data_mdl_one_tile(i_mdl/2,j_mdl/2,:) + call output2 (data_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile) + endif - enddo FIELD_LOOP - enddo TIME_LOOP + enddo OUTPUT_LOOP status=nf90_close(ncid) - deallocate(data_mdl_one_tile, mask_mdl_one_tile) - deallocate(data_src_global, lat_mdl_one_tile, lon_mdl_one_tile) + deallocate(data_mdl_one_tile, mask_mdl_one_tile, data_src_global2) + deallocate(lat_mdl_one_tile, lon_mdl_one_tile, sum_mdl_one_tile) print*,"- CALL FieldRegridRelease." call ESMF_FieldRegridRelease(routehandle=regrid_data, rc=rc) @@ -271,4 +205,8 @@ subroutine interp2(localpet, input_file) print*,"- CALL FieldDestroy." call ESMF_FieldDestroy(data_field_src, rc=rc) + print*,'after output ', localpet + call mpi_barrier(mpi_comm_world, rc) + stop + end subroutine interp2 diff --git a/sorc/sfc_climo_gen.fd/output2.f90 b/sorc/sfc_climo_gen.fd/output2.f90 index b90b70f99..d121b0a4e 100644 --- a/sorc/sfc_climo_gen.fd/output2.f90 +++ b/sorc/sfc_climo_gen.fd/output2.f90 @@ -12,10 +12,9 @@ !! @param[in] i_mdl i dimensions of tile. !! @param[in] j_mdl j dimensions of tile. !! @param[in] tile Tile number. -!! @param[in] time Time period to be output. !! @author George Gayno @date 2018 subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & - num_categories, tile, time, field_idx) + num_categories, tile) use mpi use esmf @@ -29,7 +28,6 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & implicit none integer, intent(in) :: i_mdl, j_mdl, tile, num_categories - integer, intent(in) :: time, field_idx real(esmf_kind_r4), intent(in) :: data_one_tile(i_mdl,j_mdl,num_categories) real(esmf_kind_r4) :: lat_one_tile(i_mdl,j_mdl) @@ -40,6 +38,7 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & character(len=200) :: out_file_with_halo integer :: error + integer :: field_idx integer :: dim_x, dim_y, dim_z, id_data integer :: dim_time, id_times, ierr integer :: header_buffer_val = 16384 @@ -47,6 +46,8 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & integer :: i_start, i_end, j_start, j_end integer, save :: ncid(6), ncid_with_halo + field_idx = 1 + select case (field_names(field_idx)) case ('soil_type') out_file = "./soil_type." // grid_tiles(tile) // ".nc" @@ -141,13 +142,13 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & error = nf90_inq_varid( ncid(tile), field_names(field_idx), id_data) call netcdf_err(error, 'IN NF90_INQ_VARID' ) error = nf90_put_var( ncid(tile), id_data, data_one_tile(i_start:i_end,j_start:j_end,:), & - start=(/1,1,1,time/), count=(/i_out,j_out,num_categories,1/)) + start=(/1,1,1,1/), count=(/i_out,j_out,num_categories,1/)) call netcdf_err(error, 'IN NF90_PUT_VAR' ) ! Temporary output of sum of %. sum_one_tile = sum(data_one_tile, dim=3) error = nf90_put_var( ncid(tile), id_sum, sum_one_tile(i_start:i_end,j_start:j_end), & - start=(/1,1,time/), count=(/i_out,j_out,1/)) + start=(/1,1,1/), count=(/i_out,j_out,1/)) error = nf90_close(ncid(tile)) @@ -219,7 +220,7 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & call netcdf_err(error, 'IN NF90_INQ_VARID' ) error = nf90_put_var(ncid_with_halo, id_data, data_one_tile, & - start=(/1,1,1,time/), count=(/i_mdl,j_mdl,num_categories,1/)) + start=(/1,1,1,1/), count=(/i_mdl,j_mdl,num_categories,1/)) call netcdf_err(error, 'IN NF90_PUT_VAR' ) error = nf90_close(ncid_with_halo) From 2c8161abedfee791cf5c15f3f74537e9c6b2b20a Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Mon, 31 Oct 2022 20:23:53 +0000 Subject: [PATCH 08/50] Add control flag for processing category percentages. Add the new logic for the processing of soil type. Fixes #709. --- sorc/sfc_climo_gen.fd/driver.F90 | 16 ++++++++++++---- sorc/sfc_climo_gen.fd/interp2.F90 | 4 ---- sorc/sfc_climo_gen.fd/output2.f90 | 3 --- sorc/sfc_climo_gen.fd/program_setup.f90 | 3 +++ 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/driver.F90 b/sorc/sfc_climo_gen.fd/driver.F90 index b7a233b0f..0f2605c79 100644 --- a/sorc/sfc_climo_gen.fd/driver.F90 +++ b/sorc/sfc_climo_gen.fd/driver.F90 @@ -80,8 +80,12 @@ program driver !------------------------------------------------------------------------- call define_source_grid(localpet, npets, input_vegetation_type_file) - method=ESMF_REGRIDMETHOD_NEAREST_STOD - call interp2(localpet, input_vegetation_type_file) + if (fract_vegsoil_type) then + call interp2(localpet, input_vegetation_type_file) + else + method=ESMF_REGRIDMETHOD_NEAREST_STOD + call interp(localpet, method, input_vegetation_type_file) + endif call source_grid_cleanup ! Snow free albedo @@ -136,8 +140,12 @@ program driver if (trim(input_soil_type_file) /= "NULL") then call define_source_grid(localpet, npets, input_soil_type_file) - method=ESMF_REGRIDMETHOD_NEAREST_STOD - call interp(localpet, method, input_soil_type_file) + if (fract_vegsoil_type) then + call interp2(localpet, input_soil_type_file) + else + method=ESMF_REGRIDMETHOD_NEAREST_STOD + call interp(localpet, method, input_soil_type_file) + endif call source_grid_cleanup endif diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 index 8f9cba6f2..b0960f867 100644 --- a/sorc/sfc_climo_gen.fd/interp2.F90 +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -205,8 +205,4 @@ subroutine interp2(localpet, input_file) print*,"- CALL FieldDestroy." call ESMF_FieldDestroy(data_field_src, rc=rc) - print*,'after output ', localpet - call mpi_barrier(mpi_comm_world, rc) - stop - end subroutine interp2 diff --git a/sorc/sfc_climo_gen.fd/output2.f90 b/sorc/sfc_climo_gen.fd/output2.f90 index d121b0a4e..8bb5ee079 100644 --- a/sorc/sfc_climo_gen.fd/output2.f90 +++ b/sorc/sfc_climo_gen.fd/output2.f90 @@ -225,9 +225,6 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & error = nf90_close(ncid_with_halo) - call mpi_barrier(mpi_comm_world, error) - stop - return end subroutine output2 diff --git a/sorc/sfc_climo_gen.fd/program_setup.f90 b/sorc/sfc_climo_gen.fd/program_setup.f90 index a5c59b901..e3723e6cc 100644 --- a/sorc/sfc_climo_gen.fd/program_setup.f90 +++ b/sorc/sfc_climo_gen.fd/program_setup.f90 @@ -43,6 +43,9 @@ module program_setup integer, public :: halo = 0 !< Number of row/cols defining the lateral !! boundary halo. Used for regional nests. + logical, public :: fract_vegsoil_type = .true. !< When true, output the percentage of each soil + !! and vegetation type category. + public :: read_setup_namelist contains From 3e147b5309e999532f39cfe83daf23a8c550623d Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Tue, 1 Nov 2022 18:30:00 +0000 Subject: [PATCH 09/50] Add logic to turn off the landice adjustments when processing fractional types. Fixes #709. --- sorc/sfc_climo_gen.fd/interp.F90 | 54 +++++++++++++++---------- sorc/sfc_climo_gen.fd/model_grid.F90 | 14 ++++--- sorc/sfc_climo_gen.fd/program_setup.f90 | 2 +- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/interp.F90 b/sorc/sfc_climo_gen.fd/interp.F90 index 628e67c66..540985ebd 100644 --- a/sorc/sfc_climo_gen.fd/interp.F90 +++ b/sorc/sfc_climo_gen.fd/interp.F90 @@ -15,6 +15,7 @@ subroutine interp(localpet, method, input_file) use esmf use netcdf use model_grid + use program_setup, only : fract_vegsoil_type use source_grid use utils use mpi @@ -187,14 +188,16 @@ subroutine interp(localpet, method, input_file) ! These fields are adjusted at landice. - select case (trim(field_names(n))) - case ('substrate_temperature','vegetation_greenness','leaf_area_index','slope_type','soil_type') - if (localpet == 0) then - allocate(vegt_mdl_one_tile(i_mdl,j_mdl)) - else - allocate(vegt_mdl_one_tile(0,0)) - endif - end select + if (.not. fract_vegsoil_type) then + select case (trim(field_names(n))) + case ('substrate_temperature','vegetation_greenness','leaf_area_index','slope_type','soil_type') + if (localpet == 0) then + allocate(vegt_mdl_one_tile(i_mdl,j_mdl)) + else + allocate(vegt_mdl_one_tile(0,0)) + endif + end select + endif OUTPUT_LOOP : do tile = 1, num_tiles @@ -218,30 +221,37 @@ subroutine interp(localpet, method, input_file) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGather.", rc) - select case (trim(field_names(n))) - case ('substrate_temperature','vegetation_greenness','leaf_area_index','slope_type','soil_type') - print*,"- CALL FieldGather FOR MODEL GRID VEG TYPE." - call ESMF_FieldGather(vegt_field_mdl, vegt_mdl_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + if (.not. fract_vegsoil_type) then + select case (trim(field_names(n))) + case ('substrate_temperature','vegetation_greenness','leaf_area_index','slope_type','soil_type') + print*,"- CALL FieldGather FOR MODEL GRID VEG TYPE." + call ESMF_FieldGather(vegt_field_mdl, vegt_mdl_one_tile, rootPet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGather.", rc) - end select + end select + endif if (localpet == 0) then print*,'- CALL SEARCH FOR TILE ',tile call search (data_mdl_one_tile, mask_mdl_one_tile, i_mdl, j_mdl, tile, field_names(n)) - select case (field_names(n)) - case ('substrate_temperature','vegetation_greenness','leaf_area_index','slope_type','soil_type') - call adjust_for_landice (data_mdl_one_tile, vegt_mdl_one_tile, i_mdl, j_mdl, field_names(n)) - end select + if (.not. fract_vegsoil_type) then + select case (field_names(n)) + case ('substrate_temperature','vegetation_greenness','leaf_area_index','slope_type','soil_type') + print*,'before adjust ice ',maxval(vegt_mdl_one_tile),minval(vegt_mdl_one_tile) + call adjust_for_landice (data_mdl_one_tile, vegt_mdl_one_tile, i_mdl, j_mdl, field_names(n)) + end select + endif where(mask_mdl_one_tile == 0) data_mdl_one_tile = missing call output (data_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, tile, record, t, n) endif - if (field_names(n) == 'vegetation_type') then - print*,"- CALL FieldScatter FOR MODEL GRID VEGETATION TYPE." - call ESMF_FieldScatter(vegt_field_mdl, data_mdl_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + if (.not. fract_vegsoil_type) then + if (field_names(n) == 'vegetation_type') then + print*,"- CALL FieldScatter FOR MODEL GRID VEGETATION TYPE." + call ESMF_FieldScatter(vegt_field_mdl, data_mdl_one_tile, rootPet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldScatter.", rc) + endif endif enddo OUTPUT_LOOP diff --git a/sorc/sfc_climo_gen.fd/model_grid.F90 b/sorc/sfc_climo_gen.fd/model_grid.F90 index 74763b1a1..9e269ff9e 100644 --- a/sorc/sfc_climo_gen.fd/model_grid.F90 +++ b/sorc/sfc_climo_gen.fd/model_grid.F90 @@ -164,14 +164,16 @@ subroutine define_model_grid(localpet, npets) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) - print*,"- CALL FieldCreate FOR VEGETATION TYPE INTERPOLATED TO MODEL GRID." - vegt_field_mdl = ESMF_FieldCreate(grid_mdl, & + if (.not. fract_vegsoil_type) then + print*,"- CALL FieldCreate FOR VEGETATION TYPE INTERPOLATED TO MODEL GRID." + vegt_field_mdl = ESMF_FieldCreate(grid_mdl, & typekind=ESMF_TYPEKIND_R4, & staggerloc=ESMF_STAGGERLOC_CENTER, & name="veg type on model grid", & rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) + endif print*,"- CALL FieldCreate FOR MODEL GRID LATITUDE." latitude_field_mdl = ESMF_FieldCreate(grid_mdl, & @@ -399,8 +401,10 @@ subroutine model_grid_cleanup print*,"- CALL FieldDestroy FOR MODEL GRID DATA FIELD." call ESMF_FieldDestroy(data_field_mdl,rc=rc) - print*,"- CALL FieldDestroy FOR MODEL GRID VEGETATION TYPE." - call ESMF_FieldDestroy(vegt_field_mdl,rc=rc) + if (ESMF_FieldIsCreated(vegt_field_mdl)) then + print*,"- CALL FieldDestroy FOR MODEL GRID VEGETATION TYPE." + call ESMF_FieldDestroy(vegt_field_mdl,rc=rc) + endif print*,"- CALL FieldDestroy FOR MODEL GRID LATITUDE." call ESMF_FieldDestroy(latitude_field_mdl,rc=rc) diff --git a/sorc/sfc_climo_gen.fd/program_setup.f90 b/sorc/sfc_climo_gen.fd/program_setup.f90 index e3723e6cc..7297a8594 100644 --- a/sorc/sfc_climo_gen.fd/program_setup.f90 +++ b/sorc/sfc_climo_gen.fd/program_setup.f90 @@ -43,7 +43,7 @@ module program_setup integer, public :: halo = 0 !< Number of row/cols defining the lateral !! boundary halo. Used for regional nests. - logical, public :: fract_vegsoil_type = .true. !< When true, output the percentage of each soil + logical, public :: fract_vegsoil_type = .false. !< When true, output the percentage of each soil !! and vegetation type category. public :: read_setup_namelist From 4adcb647d4cabb6709f746fc772d9bb5c4ee9378 Mon Sep 17 00:00:00 2001 From: George Gayno Date: Wed, 2 Nov 2022 12:42:36 +0000 Subject: [PATCH 10/50] Pass in flag to tell program to output dominate category or fractional categories. Fixes #709. --- driver_scripts/driver_grid.hera.sh | 5 ++++- sorc/sfc_climo_gen.fd/driver.F90 | 4 ++++ sorc/sfc_climo_gen.fd/program_setup.f90 | 3 ++- ush/sfc_climo_gen.sh | 2 ++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/driver_scripts/driver_grid.hera.sh b/driver_scripts/driver_grid.hera.sh index f8279d98d..09815ce46 100755 --- a/driver_scripts/driver_grid.hera.sh +++ b/driver_scripts/driver_grid.hera.sh @@ -71,10 +71,13 @@ module list # Set grid specs here. #----------------------------------------------------------------------- -export gtype=uniform # 'uniform', 'stretch', 'nest', +export gtype=regional_esg # 'uniform', 'stretch', 'nest', # 'regional_gfdl', 'regional_esg' export make_gsl_orog=false # 'true' if user needs 'oro' files for GSL # orographic drag suite +export vegsoilt_frac='.true.' # When .false., output dominate soil and + # vegetation type category. When .true., + # output fraction of each category. export veg_type_src="modis.igbp.0.05" # veg type data. # For viirs-based vegetation type data, set to: # 1) "viirs.igbp.0.05" for global 5km data diff --git a/sorc/sfc_climo_gen.fd/driver.F90 b/sorc/sfc_climo_gen.fd/driver.F90 index 0f2605c79..f369d250c 100644 --- a/sorc/sfc_climo_gen.fd/driver.F90 +++ b/sorc/sfc_climo_gen.fd/driver.F90 @@ -81,8 +81,10 @@ program driver call define_source_grid(localpet, npets, input_vegetation_type_file) if (fract_vegsoil_type) then + print*,'- WILL OUTPUT VEGETATION TYPE FRACTION.' call interp2(localpet, input_vegetation_type_file) else + print*,'- WILL OUTPUT DOMINATE VEGETATION TYPE.' method=ESMF_REGRIDMETHOD_NEAREST_STOD call interp(localpet, method, input_vegetation_type_file) endif @@ -141,8 +143,10 @@ program driver if (trim(input_soil_type_file) /= "NULL") then call define_source_grid(localpet, npets, input_soil_type_file) if (fract_vegsoil_type) then + print*,'- WILL OUTPUT SOIL TYPE FRACTION.' call interp2(localpet, input_soil_type_file) else + print*,'- WILL OUTPUT DOMINATE SOIL TYPE.' method=ESMF_REGRIDMETHOD_NEAREST_STOD call interp(localpet, method, input_soil_type_file) endif diff --git a/sorc/sfc_climo_gen.fd/program_setup.f90 b/sorc/sfc_climo_gen.fd/program_setup.f90 index 7297a8594..b7d6425e3 100644 --- a/sorc/sfc_climo_gen.fd/program_setup.f90 +++ b/sorc/sfc_climo_gen.fd/program_setup.f90 @@ -71,7 +71,8 @@ subroutine read_setup_namelist(localpet) input_vegetation_greenness_file, mosaic_file_mdl, & orog_dir_mdl, orog_files_mdl, halo, & vegetation_greenness_method, leaf_area_index_method, & - maximum_snow_albedo_method, snowfree_albedo_method + maximum_snow_albedo_method, snowfree_albedo_method, & + fract_vegsoil_type print*,"- READ SETUP NAMELIST, LOCALPET: ", localpet diff --git a/ush/sfc_climo_gen.sh b/ush/sfc_climo_gen.sh index ddd2bc939..f920366b0 100755 --- a/ush/sfc_climo_gen.sh +++ b/ush/sfc_climo_gen.sh @@ -39,6 +39,7 @@ mosaic_file=${mosaic_file:-$FIX_FV3/C${res}_mosaic.nc} HALO=${HALO:-0} veg_type_src=${veg_type_src:-"modis.igbp.0.05"} VEG_TYPE_FILE=${VEG_TYPE_FILE:-${input_sfc_climo_dir}/vegetation_type.${veg_type_src}.nc} +vegsoilt_frac=${vegsoilt_frac:-.false.} if [ ! -d $SAVE_DIR ]; then mkdir -p $SAVE_DIR @@ -75,6 +76,7 @@ halo=$HALO maximum_snow_albedo_method="bilinear" snowfree_albedo_method="bilinear" vegetation_greenness_method="bilinear" +fract_vegsoil_type=${vegsoilt_frac} / EOF From d99116c009f028af27ef6b75e2f5e97484de8db9 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Mon, 14 Nov 2022 15:36:35 +0000 Subject: [PATCH 11/50] Add computation and output of dominate category. Fixes #709. --- sorc/sfc_climo_gen.fd/interp2.F90 | 9 ++++- sorc/sfc_climo_gen.fd/output2.f90 | 62 ++++++++++++++++++++++--------- 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 index b0960f867..f078d0634 100644 --- a/sorc/sfc_climo_gen.fd/interp2.F90 +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -36,6 +36,7 @@ subroutine interp2(localpet, input_file) real(esmf_kind_r4), allocatable :: data_src_global(:,:) real(esmf_kind_r4), allocatable :: data_src_global2(:,:,:) real(esmf_kind_r4), allocatable :: data_mdl_one_tile(:,:,:) + real(esmf_kind_r4), allocatable :: dom_cat_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: lat_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: sum_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: lon_mdl_one_tile(:,:) @@ -93,6 +94,7 @@ subroutine interp2(localpet, input_file) if (localpet == 0) then allocate(data_src_global2(i_src,j_src,num_categories)) allocate(data_mdl_one_tile(i_mdl,j_mdl,num_categories)) + allocate(dom_cat_mdl_one_tile(i_mdl,j_mdl)) allocate(mask_mdl_one_tile(i_mdl,j_mdl)) allocate(lat_mdl_one_tile(i_mdl,j_mdl)) allocate(sum_mdl_one_tile(i_mdl,j_mdl)) @@ -100,6 +102,7 @@ subroutine interp2(localpet, input_file) else allocate(data_src_global2(0,0,0)) allocate(data_mdl_one_tile(0,0,0)) + allocate(dom_cat_mdl_one_tile(0,0)) allocate(mask_mdl_one_tile(0,0)) allocate(lat_mdl_one_tile(0,0)) allocate(sum_mdl_one_tile(0,0)) @@ -189,14 +192,16 @@ subroutine interp2(localpet, input_file) enddo call search2 (data_mdl_one_tile, mask_mdl_one_tile, i_mdl, j_mdl, num_categories, tile, field_names(1)) print*,'after regrid ',data_mdl_one_tile(i_mdl/2,j_mdl/2,:) - call output2 (data_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile) + dom_cat_mdl_one_tile = 0.0 + dom_cat_mdl_one_tile = maxloc(data_mdl_one_tile,dim=3) + call output2 (data_mdl_one_tile, dom_cat_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile) endif enddo OUTPUT_LOOP status=nf90_close(ncid) - deallocate(data_mdl_one_tile, mask_mdl_one_tile, data_src_global2) + deallocate(data_mdl_one_tile, dom_cat_mdl_one_tile, mask_mdl_one_tile, data_src_global2) deallocate(lat_mdl_one_tile, lon_mdl_one_tile, sum_mdl_one_tile) print*,"- CALL FieldRegridRelease." diff --git a/sorc/sfc_climo_gen.fd/output2.f90 b/sorc/sfc_climo_gen.fd/output2.f90 index 8bb5ee079..7c6870a14 100644 --- a/sorc/sfc_climo_gen.fd/output2.f90 +++ b/sorc/sfc_climo_gen.fd/output2.f90 @@ -13,7 +13,7 @@ !! @param[in] j_mdl j dimensions of tile. !! @param[in] tile Tile number. !! @author George Gayno @date 2018 - subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & + subroutine output2(data_one_tile, dom_cat_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & num_categories, tile) use mpi @@ -30,16 +30,18 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & integer, intent(in) :: i_mdl, j_mdl, tile, num_categories real(esmf_kind_r4), intent(in) :: data_one_tile(i_mdl,j_mdl,num_categories) + real(esmf_kind_r4), intent(in) :: dom_cat_one_tile(i_mdl,j_mdl) real(esmf_kind_r4) :: lat_one_tile(i_mdl,j_mdl) real(esmf_kind_r4), intent(in) :: lon_one_tile(i_mdl,j_mdl) real(esmf_kind_r4) :: sum_one_tile(i_mdl,j_mdl) - + + character(len=200) :: field_names_pct character(len=200) :: out_file character(len=200) :: out_file_with_halo integer :: error integer :: field_idx - integer :: dim_x, dim_y, dim_z, id_data + integer :: dim_x, dim_y, dim_z, id_data_pct, id_data_dom_cat integer :: dim_time, id_times, ierr integer :: header_buffer_val = 16384 integer :: i_out, j_out, id_lat, id_lon, id_sum @@ -113,14 +115,25 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & error = nf90_put_att(ncid(tile), id_lon, "units", "degrees_east") call netcdf_err(error, 'DEFINING GEOLON UNIT ATTRIBUTE' ) - error = nf90_def_var(ncid(tile), trim(field_names(1)), NF90_FLOAT, (/dim_x,dim_y,dim_z,dim_time/), id_data) + field_names_pct = trim(field_names(1)) // "_pct" + error = nf90_def_var(ncid(tile), trim(field_names_pct), NF90_FLOAT, (/dim_x,dim_y,dim_z,dim_time/), id_data_pct) + call netcdf_err(error, 'DEFINING FIELD' ) + error = nf90_put_att(ncid(tile), id_data_pct, "units", "percent coverage each category") + call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) + error = nf90_put_att(ncid(tile), id_data_pct, "missing_value", missing) + call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) + error = nf90_put_att(ncid(tile), id_data_pct, "coordinates", "geolon geolat") + call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) + + error = nf90_def_var(ncid(tile), trim(field_names(1)), NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_data_dom_cat) call netcdf_err(error, 'DEFINING FIELD' ) - error = nf90_put_att(ncid(tile), id_data, "units", "percent coverage each category") + error = nf90_put_att(ncid(tile), id_data_dom_cat, "units", "dominate category") call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid(tile), id_data, "missing_value", missing) + error = nf90_put_att(ncid(tile), id_data_dom_cat, "missing_value", missing) call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid(tile), id_data, "coordinates", "geolon geolat") + error = nf90_put_att(ncid(tile), id_data_dom_cat, "coordinates", "geolon geolat") call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) + error = nf90_def_var(ncid(tile), 'sum', NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_sum) call netcdf_err(error, 'DEFINING FIELD' ) @@ -139,12 +152,14 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLON' ) print*,'- WRITE DATA ' - error = nf90_inq_varid( ncid(tile), field_names(field_idx), id_data) - call netcdf_err(error, 'IN NF90_INQ_VARID' ) - error = nf90_put_var( ncid(tile), id_data, data_one_tile(i_start:i_end,j_start:j_end,:), & + error = nf90_put_var( ncid(tile), id_data_pct, data_one_tile(i_start:i_end,j_start:j_end,:), & start=(/1,1,1,1/), count=(/i_out,j_out,num_categories,1/)) call netcdf_err(error, 'IN NF90_PUT_VAR' ) + error = nf90_put_var( ncid(tile), id_data_dom_cat, dom_cat_one_tile(i_start:i_end,j_start:j_end), & + start=(/1,1,1/), count=(/i_out,j_out,1/)) + call netcdf_err(error, 'IN NF90_PUT_VAR' ) + ! Temporary output of sum of %. sum_one_tile = sum(data_one_tile, dim=3) error = nf90_put_var( ncid(tile), id_sum, sum_one_tile(i_start:i_end,j_start:j_end), & @@ -192,13 +207,22 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & error = nf90_put_att(ncid_with_halo, id_lon, "units", "degrees_east") call netcdf_err(error, 'DEFINING GEOLON UNIT ATTRIBUTE' ) - error = nf90_def_var(ncid_with_halo, field_names(1), NF90_FLOAT, (/dim_x,dim_y,dim_z,dim_time/), id_data) + error = nf90_def_var(ncid_with_halo, field_names_pct, NF90_FLOAT, (/dim_x,dim_y,dim_z,dim_time/), id_data_pct) call netcdf_err(error, 'DEFINING FIELD VARIABLE' ) - error = nf90_put_att(ncid_with_halo, id_data, "units", "percent coverage each category") + error = nf90_put_att(ncid_with_halo, id_data_pct, "units", "percent coverage each category") call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid_with_halo, id_data, "missing_value", missing) + error = nf90_put_att(ncid_with_halo, id_data_pct, "missing_value", missing) call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid_with_halo, id_data, "coordinates", "geolon geolat") + error = nf90_put_att(ncid_with_halo, id_data_pct, "coordinates", "geolon geolat") + call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) + + error = nf90_def_var(ncid(tile), trim(field_names(1)), NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_data_dom_cat) + call netcdf_err(error, 'DEFINING FIELD' ) + error = nf90_put_att(ncid(tile), id_data_dom_cat, "units", "dominate category") + call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) + error = nf90_put_att(ncid(tile), id_data_dom_cat, "missing_value", missing) + call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) + error = nf90_put_att(ncid(tile), id_data_dom_cat, "coordinates", "geolon geolat") call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) error = nf90_enddef(ncid_with_halo, header_buffer_val,4,0,4) @@ -216,13 +240,15 @@ subroutine output2(data_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLON' ) print*,'- WRITE DATA' - error = nf90_inq_varid(ncid_with_halo, field_names(field_idx), id_data) - call netcdf_err(error, 'IN NF90_INQ_VARID' ) - error = nf90_put_var(ncid_with_halo, id_data, data_one_tile, & + error = nf90_put_var(ncid_with_halo, id_data_pct, data_one_tile, & start=(/1,1,1,1/), count=(/i_mdl,j_mdl,num_categories,1/)) call netcdf_err(error, 'IN NF90_PUT_VAR' ) - + + error = nf90_put_var(ncid_with_halo, id_data_dom_cat, dom_cat_one_tile, & + start=(/1,1,1/), count=(/i_mdl,j_mdl,1/)) + call netcdf_err(error, 'IN NF90_PUT_VAR' ) + error = nf90_close(ncid_with_halo) return From bb91f34868c760be12987c4933f4f4f4de51f862 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Mon, 14 Nov 2022 18:44:29 +0000 Subject: [PATCH 12/50] Add output of water category. Fixes #709. --- sorc/sfc_climo_gen.fd/interp2.F90 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 index f078d0634..d268754a8 100644 --- a/sorc/sfc_climo_gen.fd/interp2.F90 +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -30,6 +30,9 @@ subroutine interp2(localpet, input_file) integer :: isrctermprocessing integer :: category, num_categories +!cggg need to read this from file. + integer, parameter :: water_category = 17 + integer(esmf_kind_i4), allocatable :: mask_mdl_one_tile(:,:) integer(esmf_kind_i4), pointer :: unmapped_ptr(:) @@ -192,6 +195,13 @@ subroutine interp2(localpet, input_file) enddo call search2 (data_mdl_one_tile, mask_mdl_one_tile, i_mdl, j_mdl, num_categories, tile, field_names(1)) print*,'after regrid ',data_mdl_one_tile(i_mdl/2,j_mdl/2,:) + do j = 1, j_mdl + do i = 1, i_mdl + if (mask_mdl_one_tile(i,j) == 0) then + data_mdl_one_tile(i,j,water_category) = 1.0 + endif + enddo + enddo dom_cat_mdl_one_tile = 0.0 dom_cat_mdl_one_tile = maxloc(data_mdl_one_tile,dim=3) call output2 (data_mdl_one_tile, dom_cat_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile) From cc929a8a5250e81090437837fb265f42033c09cb Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Tue, 15 Nov 2022 15:17:51 +0000 Subject: [PATCH 13/50] Update logic to work with fractional land/non-land grids. Fixes #709. --- sorc/sfc_climo_gen.fd/interp2.F90 | 43 ++++++++++++++++++++++--- sorc/sfc_climo_gen.fd/model_grid.F90 | 48 ++++++++++++++++++++++++---- 2 files changed, 81 insertions(+), 10 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 index d268754a8..09f062772 100644 --- a/sorc/sfc_climo_gen.fd/interp2.F90 +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -15,7 +15,8 @@ subroutine interp2(localpet, input_file) use netcdf use model_grid, only : grid_mdl, i_mdl, j_mdl, & num_tiles, latitude_field_mdl, & - longitude_field_mdl, mask_field_mdl + longitude_field_mdl, mask_field_mdl, & + land_frac_field_mdl use source_grid use utils use mpi @@ -43,6 +44,7 @@ subroutine interp2(localpet, input_file) real(esmf_kind_r4), allocatable :: lat_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: sum_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: lon_mdl_one_tile(:,:) + real(esmf_kind_r4), allocatable :: land_frac_mdl_one_tile(:,:) type(esmf_regridmethod_flag) :: method type(esmf_field) :: data_field_src @@ -99,6 +101,7 @@ subroutine interp2(localpet, input_file) allocate(data_mdl_one_tile(i_mdl,j_mdl,num_categories)) allocate(dom_cat_mdl_one_tile(i_mdl,j_mdl)) allocate(mask_mdl_one_tile(i_mdl,j_mdl)) + allocate(land_frac_mdl_one_tile(i_mdl,j_mdl)) allocate(lat_mdl_one_tile(i_mdl,j_mdl)) allocate(sum_mdl_one_tile(i_mdl,j_mdl)) allocate(lon_mdl_one_tile(i_mdl,j_mdl)) @@ -107,6 +110,7 @@ subroutine interp2(localpet, input_file) allocate(data_mdl_one_tile(0,0,0)) allocate(dom_cat_mdl_one_tile(0,0)) allocate(mask_mdl_one_tile(0,0)) + allocate(land_frac_mdl_one_tile(0,0)) allocate(lat_mdl_one_tile(0,0)) allocate(sum_mdl_one_tile(0,0)) allocate(lon_mdl_one_tile(0,0)) @@ -183,18 +187,28 @@ subroutine interp2(localpet, input_file) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGather.", rc) + print*,"- CALL FieldGather FOR MODEL GRID LAND FRACTION." + call ESMF_FieldGather(land_frac_field_mdl, land_frac_mdl_one_tile, rootPet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather.", rc) + if (localpet == 0) then print*,'- CALL SEARCH FOR TILE ',tile - sum_mdl_one_tile = sum(data_mdl_one_tile, dim=3) ! use unused variable to now. + +! Where sum is zero, the regridding did not find any input data for the model point +! (ex. and isolated island). Call the search routine at these points. + sum_mdl_one_tile = sum(data_mdl_one_tile, dim=3) do j = 1, j_mdl do i = 1, i_mdl if (mask_mdl_one_tile(i,j) == 1 .and. sum_mdl_one_tile(i,j) == 0.0) then - data_mdl_one_tile(i,j,:) = -9999.9 + data_mdl_one_tile(i,j,:) = -9999.9 ! flag to tell search routine to search. endif enddo enddo call search2 (data_mdl_one_tile, mask_mdl_one_tile, i_mdl, j_mdl, num_categories, tile, field_names(1)) print*,'after regrid ',data_mdl_one_tile(i_mdl/2,j_mdl/2,:) + +! These points are all non-land. Set to 100% of the water category. do j = 1, j_mdl do i = 1, i_mdl if (mask_mdl_one_tile(i,j) == 0) then @@ -202,6 +216,27 @@ subroutine interp2(localpet, input_file) endif enddo enddo + +! For fractional grids, need to rescale the category percentages by the +! fraction of land in the model grid cell. + +! When running with fractional grids, the land_frac_mdl_one_tile array will +! contain a fraction between 0 and 1. When not running with fractional +! grids, this array will contain negative fill values. + + if (maxval(land_frac_mdl_one_tile) > 0.0) then + print*,'before rescale ',land_frac_mdl_one_tile(658,95),data_mdl_one_tile(658,95,:) + do j = 1, j_mdl + do i = 1, i_mdl + if (mask_mdl_one_tile(i,j) == 1) then + data_mdl_one_tile(i,j,:) = data_mdl_one_tile(i,j,:) * land_frac_mdl_one_tile(i,j) + data_mdl_one_tile(i,j,water_category) = 1.0 - land_frac_mdl_one_tile(i,j) + endif + enddo + enddo + print*,'after rescale ',land_frac_mdl_one_tile(658,95),data_mdl_one_tile(658,95,:) + endif +! under fractional grids, how do we define dominate category? dom_cat_mdl_one_tile = 0.0 dom_cat_mdl_one_tile = maxloc(data_mdl_one_tile,dim=3) call output2 (data_mdl_one_tile, dom_cat_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile) @@ -212,7 +247,7 @@ subroutine interp2(localpet, input_file) status=nf90_close(ncid) deallocate(data_mdl_one_tile, dom_cat_mdl_one_tile, mask_mdl_one_tile, data_src_global2) - deallocate(lat_mdl_one_tile, lon_mdl_one_tile, sum_mdl_one_tile) + deallocate(lat_mdl_one_tile, lon_mdl_one_tile, sum_mdl_one_tile, land_frac_mdl_one_tile) print*,"- CALL FieldRegridRelease." call ESMF_FieldRegridRelease(routehandle=regrid_data, rc=rc) diff --git a/sorc/sfc_climo_gen.fd/model_grid.F90 b/sorc/sfc_climo_gen.fd/model_grid.F90 index 9e269ff9e..532245cf5 100644 --- a/sorc/sfc_climo_gen.fd/model_grid.F90 +++ b/sorc/sfc_climo_gen.fd/model_grid.F90 @@ -28,8 +28,16 @@ module model_grid type(esmf_grid), public :: grid_mdl !< ESMF grid object for the model grid. type(esmf_field), public :: data_field_mdl !< ESMF field object that holds the !! data interpolated to model grid. + type(esmf_field), public :: land_frac_field_mdl !< ESMF field object that holds the + !! model land fraction. When running + !! with fractional grids, will be + !! between zero and one. For non- + !! fractional grids, will contain a + !! fill value. type(esmf_field), public :: mask_field_mdl !< ESMF field object that holds the - !! model land mask. + !! model land mask. Equal to '1' if + !! point is partial or all land. Equal + !! to zero is point is all non-land. type(esmf_field), public :: latitude_field_mdl !< ESMF field object that holds the !! model grid latitude. type(esmf_field), public :: longitude_field_mdl !< ESMF field object that holds the @@ -75,6 +83,7 @@ subroutine define_model_grid(localpet, npets) real(esmf_kind_r4), allocatable :: latitude_one_tile(:,:) real(esmf_kind_r4), allocatable :: longitude_one_tile(:,:) + real(esmf_kind_r4), allocatable :: land_frac_one_tile(:,:) !----------------------------------------------------------------------- ! Get the number of tiles from the mosaic file. @@ -214,12 +223,23 @@ subroutine define_model_grid(localpet, npets) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGet", rc) + print*,"- CALL FieldCreate FOR MODEL GRID LAND FRACTION." + land_frac_field_mdl = ESMF_FieldCreate(grid_mdl, & + typekind=ESMF_TYPEKIND_R4, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + name="model grid land fraction", & + rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + if (localpet == 0) then allocate(mask_mdl_one_tile(i_mdl,j_mdl)) + allocate(land_frac_one_tile(i_mdl,j_mdl)) allocate(latitude_one_tile(i_mdl,j_mdl)) allocate(longitude_one_tile(i_mdl,j_mdl)) else allocate(mask_mdl_one_tile(0,0)) + allocate(land_frac_one_tile(0,0)) allocate(latitude_one_tile(0,0)) allocate(longitude_one_tile(0,0)) endif @@ -227,7 +247,7 @@ subroutine define_model_grid(localpet, npets) do tile = 1, num_tiles if (localpet == 0) then the_file = trim(orog_dir_mdl) // trim(orog_files_mdl(tile)) - call get_model_info(trim(the_file), mask_mdl_one_tile, & + call get_model_info(trim(the_file), mask_mdl_one_tile, land_frac_one_tile, & latitude_one_tile, longitude_one_tile, i_mdl, j_mdl) endif @@ -236,6 +256,11 @@ subroutine define_model_grid(localpet, npets) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldScatter", rc) + print*,"- CALL FieldScatter FOR MODEL GRID LAND FRACTION. TILE IS: ", tile + call ESMF_FieldScatter(land_frac_field_mdl, land_frac_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + print*,"- CALL FieldScatter FOR MODEL LATITUDE. TILE IS: ", tile call ESMF_FieldScatter(latitude_field_mdl, latitude_one_tile, rootpet=0, tile=tile, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -282,7 +307,7 @@ end subroutine define_model_grid !! @param[in] idim i dimension of the model tile !! @param[in] jdim j dimension of the model tile !! @author George Gayno @date 2018 - subroutine get_model_info(orog_file, mask, lat2d, lon2d, idim, jdim) + subroutine get_model_info(orog_file, mask, land_frac, lat2d, lon2d, idim, jdim) use esmf use netcdf @@ -297,6 +322,7 @@ subroutine get_model_info(orog_file, mask, lat2d, lon2d, idim, jdim) real(esmf_kind_r4), intent(out) :: lat2d(idim,jdim) real(esmf_kind_r4), intent(out) :: lon2d(idim,jdim) + real(esmf_kind_r4), intent(out) :: land_frac(idim,jdim) integer :: error, lat, lon, i, j integer :: ncid, id_dim, id_var @@ -330,11 +356,17 @@ subroutine get_model_info(orog_file, mask, lat2d, lon2d, idim, jdim) allocate(dummy(idim,jdim)) !----------------------------------------------------------------------- -! If the lake maker was used, there will be a 'lake_frac' record. +! If the lake maker was used, we are running with a fractional +! land/non-land grid and there will be a 'lake_frac' record. ! In that case, land/non-land is determined by 'land_frac'. ! ! If the lake maker was not used, use 'slmsk', which is defined ! as the nint(land_frac). +! +! In summary, if 'mask' is one, the point is all land or +! partial land and surface data will be mapped to it. Otherwise, +! when 'mask' is zero, then the point is all non-land and +! surface data will not be mapped to it. !----------------------------------------------------------------------- error=nf90_inq_varid(ncid, 'lake_frac', id_var) @@ -345,16 +377,17 @@ subroutine get_model_info(orog_file, mask, lat2d, lon2d, idim, jdim) error=nf90_get_var(ncid, id_var, dummy) call netcdf_err(error, "READING SLMSK") mask = nint(dummy) + land_frac = -999. else print*,"- READ LAND FRACTION" error=nf90_inq_varid(ncid, 'land_frac', id_var) call netcdf_err(error, "READING LAND_FRAC ID") - error=nf90_get_var(ncid, id_var, dummy) + error=nf90_get_var(ncid, id_var, land_frac) call netcdf_err(error, "READING LAND_FRAC") mask = 0 do j = 1, lat do i = 1, lon - if (dummy(i,j) > 0.0) then + if (land_frac(i,j) > 0.0) then mask(i,j) = 1 endif enddo @@ -398,6 +431,9 @@ subroutine model_grid_cleanup print*,"- CALL FieldDestroy FOR MODEL GRID LAND MASK." call ESMF_FieldDestroy(mask_field_mdl,rc=rc) + print*,"- CALL FieldDestroy FOR MODEL GRID LAND MASK." + call ESMF_FieldDestroy(land_frac_field_mdl,rc=rc) + print*,"- CALL FieldDestroy FOR MODEL GRID DATA FIELD." call ESMF_FieldDestroy(data_field_mdl,rc=rc) From 4cfe72ee7abdccf3845475218d9a45c142b86edc Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Tue, 15 Nov 2022 21:19:03 +0000 Subject: [PATCH 14/50] Read water flag from file. Fixes #709. --- sorc/sfc_climo_gen.fd/interp2.F90 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 index 09f062772..659cf0157 100644 --- a/sorc/sfc_climo_gen.fd/interp2.F90 +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -27,13 +27,10 @@ subroutine interp2(localpet, input_file) integer :: rc, localpet integer :: i, j, tile, ncid, status - integer :: varid + integer :: varid, water_category integer :: isrctermprocessing integer :: category, num_categories -!cggg need to read this from file. - integer, parameter :: water_category = 17 - integer(esmf_kind_i4), allocatable :: mask_mdl_one_tile(:,:) integer(esmf_kind_i4), pointer :: unmapped_ptr(:) @@ -52,6 +49,7 @@ subroutine interp2(localpet, input_file) type(esmf_routehandle) :: regrid_data type(esmf_polemethod_flag) :: pole + if (localpet == 0) then allocate(data_src_global(i_src,j_src)) else @@ -68,6 +66,9 @@ subroutine interp2(localpet, input_file) call netcdf_err(status, "IN ROUTINE INTERP READING FIELD") print*,'number of cats ',maxval(data_src_global) num_categories = nint(maxval(data_src_global)) + status = nf90_get_att(ncid, varid, 'water_category', water_category) + call netcdf_err(status, "IN ROUTINE INTERP READING water_category") + print*,'water cat ',water_category endif call mpi_bcast(num_categories,1,MPI_INTEGER,0,MPI_COMM_WORLD,status) From 7dc9416fc61817e577adb260f1a4c74762795815 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Wed, 16 Nov 2022 16:23:59 +0000 Subject: [PATCH 15/50] Update wcoss2 driver script comments. Fixes #709. --- driver_scripts/driver_grid.wcoss2.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/driver_scripts/driver_grid.wcoss2.sh b/driver_scripts/driver_grid.wcoss2.sh index b0d1e6587..b294594a2 100755 --- a/driver_scripts/driver_grid.wcoss2.sh +++ b/driver_scripts/driver_grid.wcoss2.sh @@ -6,7 +6,7 @@ #PBS -A GFS-DEV #PBS -l walltime=00:15:00 #PBS -N make_grid -#PBS -l select=1:ncpus=24:mem=200GB +#PBS -l select=1:ncpus=24:mem=500GB #----------------------------------------------------------------------- # Driver script to create a cubic-sphere based model grid on WCOSS2. @@ -69,7 +69,13 @@ module list # Set grid specs here. #----------------------------------------------------------------------- -export gtype=regional_esg # 'uniform', 'stretch', 'nest', +export vegsoilt_frac='.true.' # When true, outputs percent of each + # soil and veg type category and a + # dominate category. When false, only + # outputs the dominate category. A + # Fortran logical, so include the dots. + +export gtype=regional_esg # 'uniform', 'stretch', 'nest', # 'regional_gfdl', 'regional_esg' export make_gsl_orog=false # 'true' if user needs 'oro' files for GSL # orographic drag suite From 933af8b4537558dfc8bf5f64472d9b621c0b5a3c Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Wed, 16 Nov 2022 20:14:14 +0000 Subject: [PATCH 16/50] Simplify the file unit numbers in output2.f90 Fixes #709. --- sorc/sfc_climo_gen.fd/output2.f90 | 75 ++++++++++++++++--------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/output2.f90 b/sorc/sfc_climo_gen.fd/output2.f90 index 7c6870a14..26cf20239 100644 --- a/sorc/sfc_climo_gen.fd/output2.f90 +++ b/sorc/sfc_climo_gen.fd/output2.f90 @@ -46,7 +46,7 @@ subroutine output2(data_one_tile, dom_cat_one_tile, lat_one_tile, lon_one_tile, integer :: header_buffer_val = 16384 integer :: i_out, j_out, id_lat, id_lon, id_sum integer :: i_start, i_end, j_start, j_end - integer, save :: ncid(6), ncid_with_halo + integer :: ncid, ncid_with_halo field_idx = 1 @@ -83,89 +83,90 @@ subroutine output2(data_one_tile, dom_cat_one_tile, lat_one_tile, lon_one_tile, i_out = i_end - i_start + 1 j_out = j_end - j_start + 1 - error = nf90_create(out_file, NF90_NETCDF4, ncid(tile)) + error = nf90_create(out_file, NF90_NETCDF4, ncid) + print*,'ncid is ',ncid call netcdf_err(error, 'ERROR IN NF90_CREATE' ) - error = nf90_def_dim(ncid(tile), 'nx', i_out, dim_x) + error = nf90_def_dim(ncid, 'nx', i_out, dim_x) call netcdf_err(error, 'DEFINING NX DIMENSION' ) - error = nf90_def_dim(ncid(tile), 'ny', j_out, dim_y) + error = nf90_def_dim(ncid, 'ny', j_out, dim_y) call netcdf_err(error, 'DEFINING NY DIMENSION' ) - error = nf90_def_dim(ncid(tile), 'num_categories', num_categories, dim_z) + error = nf90_def_dim(ncid, 'num_categories', num_categories, dim_z) call netcdf_err(error, 'DEFINING NZ DIMENSION' ) - error = nf90_def_dim(ncid(tile), 'time', num_time_recs, dim_time) + error = nf90_def_dim(ncid, 'time', num_time_recs, dim_time) call netcdf_err(error, 'DEFINING TIME DIMENSION' ) - error = nf90_def_var(ncid(tile), 'time', NF90_FLOAT, dim_time, id_times) + error = nf90_def_var(ncid, 'time', NF90_FLOAT, dim_time, id_times) call netcdf_err(error, 'DEFINING TIME VARIABLE' ) - error = nf90_put_att(ncid(tile), id_times, "units", "days since 2015-1-1") + error = nf90_put_att(ncid, id_times, "units", "days since 2015-1-1") call netcdf_err(error, 'DEFINING TIME ATTRIBUTE' ) if (len_trim(source) > 0) then - error = nf90_put_att(ncid(tile), nf90_global, 'source', source) + error = nf90_put_att(ncid, nf90_global, 'source', source) call netcdf_err(error, 'DEFINING GLOBAL SOURCE ATTRIBUTE' ) endif - error = nf90_def_var(ncid(tile), 'geolat', NF90_FLOAT, (/dim_x,dim_y/), id_lat) + error = nf90_def_var(ncid, 'geolat', NF90_FLOAT, (/dim_x,dim_y/), id_lat) call netcdf_err(error, 'DEFINING GEOLAT FIELD' ) - error = nf90_put_att(ncid(tile), id_lat, "long_name", "Latitude") + error = nf90_put_att(ncid, id_lat, "long_name", "Latitude") call netcdf_err(error, 'DEFINING GEOLAT NAME ATTRIBUTE' ) - error = nf90_put_att(ncid(tile), id_lat, "units", "degrees_north") + error = nf90_put_att(ncid, id_lat, "units", "degrees_north") call netcdf_err(error, 'DEFINING GEOLAT UNIT ATTRIBUTE' ) - error = nf90_def_var(ncid(tile), 'geolon', NF90_FLOAT, (/dim_x,dim_y/), id_lon) + error = nf90_def_var(ncid, 'geolon', NF90_FLOAT, (/dim_x,dim_y/), id_lon) call netcdf_err(error, 'DEFINING GEOLON FIELD' ) - error = nf90_put_att(ncid(tile), id_lon, "long_name", "Longitude") + error = nf90_put_att(ncid, id_lon, "long_name", "Longitude") call netcdf_err(error, 'DEFINING GEOLON NAME ATTRIBUTE' ) - error = nf90_put_att(ncid(tile), id_lon, "units", "degrees_east") + error = nf90_put_att(ncid, id_lon, "units", "degrees_east") call netcdf_err(error, 'DEFINING GEOLON UNIT ATTRIBUTE' ) field_names_pct = trim(field_names(1)) // "_pct" - error = nf90_def_var(ncid(tile), trim(field_names_pct), NF90_FLOAT, (/dim_x,dim_y,dim_z,dim_time/), id_data_pct) + error = nf90_def_var(ncid, trim(field_names_pct), NF90_FLOAT, (/dim_x,dim_y,dim_z,dim_time/), id_data_pct) call netcdf_err(error, 'DEFINING FIELD' ) - error = nf90_put_att(ncid(tile), id_data_pct, "units", "percent coverage each category") + error = nf90_put_att(ncid, id_data_pct, "units", "percent coverage each category") call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid(tile), id_data_pct, "missing_value", missing) + error = nf90_put_att(ncid, id_data_pct, "missing_value", missing) call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid(tile), id_data_pct, "coordinates", "geolon geolat") + error = nf90_put_att(ncid, id_data_pct, "coordinates", "geolon geolat") call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) - error = nf90_def_var(ncid(tile), trim(field_names(1)), NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_data_dom_cat) + error = nf90_def_var(ncid, trim(field_names(1)), NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_data_dom_cat) call netcdf_err(error, 'DEFINING FIELD' ) - error = nf90_put_att(ncid(tile), id_data_dom_cat, "units", "dominate category") + error = nf90_put_att(ncid, id_data_dom_cat, "units", "dominate category") call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid(tile), id_data_dom_cat, "missing_value", missing) + error = nf90_put_att(ncid, id_data_dom_cat, "missing_value", missing) call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid(tile), id_data_dom_cat, "coordinates", "geolon geolat") + error = nf90_put_att(ncid, id_data_dom_cat, "coordinates", "geolon geolat") call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) - error = nf90_def_var(ncid(tile), 'sum', NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_sum) + error = nf90_def_var(ncid, 'sum', NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_sum) call netcdf_err(error, 'DEFINING FIELD' ) - error = nf90_enddef(ncid(tile), header_buffer_val,4,0,4) + error = nf90_enddef(ncid, header_buffer_val,4,0,4) call netcdf_err(error, 'IN NF90_ENDDEF' ) - error = nf90_put_var( ncid(tile), id_times, day_of_rec) + error = nf90_put_var( ncid, id_times, day_of_rec) call netcdf_err(error, 'WRITING TIME FIELD' ) - error = nf90_put_var( ncid(tile), id_lat, lat_one_tile(i_start:i_end,j_start:j_end), & + error = nf90_put_var( ncid, id_lat, lat_one_tile(i_start:i_end,j_start:j_end), & start=(/1,1/), count=(/i_out,j_out/)) call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLAT' ) - error = nf90_put_var( ncid(tile), id_lon, lon_one_tile(i_start:i_end,j_start:j_end), & + error = nf90_put_var( ncid, id_lon, lon_one_tile(i_start:i_end,j_start:j_end), & start=(/1,1/), count=(/i_out,j_out/)) call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLON' ) print*,'- WRITE DATA ' - error = nf90_put_var( ncid(tile), id_data_pct, data_one_tile(i_start:i_end,j_start:j_end,:), & + error = nf90_put_var( ncid, id_data_pct, data_one_tile(i_start:i_end,j_start:j_end,:), & start=(/1,1,1,1/), count=(/i_out,j_out,num_categories,1/)) call netcdf_err(error, 'IN NF90_PUT_VAR' ) - error = nf90_put_var( ncid(tile), id_data_dom_cat, dom_cat_one_tile(i_start:i_end,j_start:j_end), & + error = nf90_put_var( ncid, id_data_dom_cat, dom_cat_one_tile(i_start:i_end,j_start:j_end), & start=(/1,1,1/), count=(/i_out,j_out,1/)) call netcdf_err(error, 'IN NF90_PUT_VAR' ) ! Temporary output of sum of %. sum_one_tile = sum(data_one_tile, dim=3) - error = nf90_put_var( ncid(tile), id_sum, sum_one_tile(i_start:i_end,j_start:j_end), & + error = nf90_put_var( ncid, id_sum, sum_one_tile(i_start:i_end,j_start:j_end), & start=(/1,1,1/), count=(/i_out,j_out,1/)) - error = nf90_close(ncid(tile)) + error = nf90_close(ncid) !---------------------------------------------------------------------- ! For regional nests, also output files including the halo @@ -181,7 +182,7 @@ subroutine output2(data_one_tile, dom_cat_one_tile, lat_one_tile, lon_one_tile, call netcdf_err(error, 'DEFINING NX DIMENSION' ) error = nf90_def_dim(ncid_with_halo, 'ny', j_mdl, dim_y) call netcdf_err(error, 'DEFINING NY DIMENSION' ) - error = nf90_def_dim(ncid(tile), 'num_categories', num_categories, dim_z) + error = nf90_def_dim(ncid_with_halo, 'num_categories', num_categories, dim_z) call netcdf_err(error, 'DEFINING NZ DIMENSION' ) error = nf90_def_dim(ncid_with_halo, 'time', num_time_recs, dim_time) call netcdf_err(error, 'DEFINING TIME DIMENSION' ) @@ -216,13 +217,13 @@ subroutine output2(data_one_tile, dom_cat_one_tile, lat_one_tile, lon_one_tile, error = nf90_put_att(ncid_with_halo, id_data_pct, "coordinates", "geolon geolat") call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) - error = nf90_def_var(ncid(tile), trim(field_names(1)), NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_data_dom_cat) + error = nf90_def_var(ncid_with_halo, trim(field_names(1)), NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_data_dom_cat) call netcdf_err(error, 'DEFINING FIELD' ) - error = nf90_put_att(ncid(tile), id_data_dom_cat, "units", "dominate category") + error = nf90_put_att(ncid_with_halo, id_data_dom_cat, "units", "dominate category") call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid(tile), id_data_dom_cat, "missing_value", missing) + error = nf90_put_att(ncid_with_halo, id_data_dom_cat, "missing_value", missing) call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid(tile), id_data_dom_cat, "coordinates", "geolon geolat") + error = nf90_put_att(ncid_with_halo, id_data_dom_cat, "coordinates", "geolon geolat") call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) error = nf90_enddef(ncid_with_halo, header_buffer_val,4,0,4) From 33cefde386ebd6ea530065cc7a7b7bb83f71ff29 Mon Sep 17 00:00:00 2001 From: George Gayno Date: Thu, 17 Nov 2022 20:42:16 +0000 Subject: [PATCH 17/50] Deallocate unneeded memory as soon as possible in interp2.F90 Fixes #709. --- sorc/sfc_climo_gen.fd/interp2.F90 | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 index 659cf0157..13002b80c 100644 --- a/sorc/sfc_climo_gen.fd/interp2.F90 +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -135,6 +135,8 @@ subroutine interp2(localpet, input_file) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldScatter.", rc) + deallocate(data_src_global2) + isrctermprocessing = 1 method = ESMF_REGRIDMETHOD_CONSERVE @@ -166,6 +168,12 @@ subroutine interp2(localpet, input_file) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldRegrid.", rc) + print*,"- CALL FieldRegridRelease." + call ESMF_FieldRegridRelease(routehandle=regrid_data, rc=rc) + + print*,"- CALL FieldDestroy." + call ESMF_FieldDestroy(data_field_src, rc=rc) + OUTPUT_LOOP : do tile = 1, num_tiles print*,"- CALL FieldGather FOR MODEL LATITUDE." @@ -247,13 +255,12 @@ subroutine interp2(localpet, input_file) status=nf90_close(ncid) - deallocate(data_mdl_one_tile, dom_cat_mdl_one_tile, mask_mdl_one_tile, data_src_global2) + deallocate(data_mdl_one_tile, dom_cat_mdl_one_tile, mask_mdl_one_tile) deallocate(lat_mdl_one_tile, lon_mdl_one_tile, sum_mdl_one_tile, land_frac_mdl_one_tile) - print*,"- CALL FieldRegridRelease." - call ESMF_FieldRegridRelease(routehandle=regrid_data, rc=rc) - print*,"- CALL FieldDestroy." - call ESMF_FieldDestroy(data_field_src, rc=rc) + call ESMF_FieldDestroy(data_field_mdl, rc=rc) + + call mpi_barrier(mpi_comm_world, rc) end subroutine interp2 From 86f97dfa41540aa79407edfbc852b80edc87fcd5 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Mon, 21 Nov 2022 19:23:37 +0000 Subject: [PATCH 18/50] Simplify output2 by adding subroutine to do file write. Fixes #709. --- sorc/sfc_climo_gen.fd/output2.f90 | 185 ++++++++++-------------------- 1 file changed, 62 insertions(+), 123 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/output2.f90 b/sorc/sfc_climo_gen.fd/output2.f90 index 26cf20239..8d14c6b19 100644 --- a/sorc/sfc_climo_gen.fd/output2.f90 +++ b/sorc/sfc_climo_gen.fd/output2.f90 @@ -18,11 +18,9 @@ subroutine output2(data_one_tile, dom_cat_one_tile, lat_one_tile, lon_one_tile, use mpi use esmf - use netcdf - use utils - use source_grid, only : field_names, source, & - num_time_recs, day_of_rec - use model_grid, only : missing, grid_tiles + use source_grid, only : field_names, & + num_time_recs + use model_grid, only : grid_tiles use program_setup, only : halo implicit none @@ -33,20 +31,14 @@ subroutine output2(data_one_tile, dom_cat_one_tile, lat_one_tile, lon_one_tile, real(esmf_kind_r4), intent(in) :: dom_cat_one_tile(i_mdl,j_mdl) real(esmf_kind_r4) :: lat_one_tile(i_mdl,j_mdl) real(esmf_kind_r4), intent(in) :: lon_one_tile(i_mdl,j_mdl) - real(esmf_kind_r4) :: sum_one_tile(i_mdl,j_mdl) - character(len=200) :: field_names_pct character(len=200) :: out_file character(len=200) :: out_file_with_halo - integer :: error integer :: field_idx - integer :: dim_x, dim_y, dim_z, id_data_pct, id_data_dom_cat - integer :: dim_time, id_times, ierr - integer :: header_buffer_val = 16384 - integer :: i_out, j_out, id_lat, id_lon, id_sum + integer :: ierr + integer :: i_out, j_out integer :: i_start, i_end, j_start, j_end - integer :: ncid, ncid_with_halo field_idx = 1 @@ -68,32 +60,72 @@ subroutine output2(data_one_tile, dom_cat_one_tile, lat_one_tile, lon_one_tile, !---------------------------------------------------------------------- if (halo > 0) then - print*,"- WILL REMOVE HALO REGION OF ", halo, " ROWS/COLS." + print*,"- WILL WRITE WITHOUT HALO REGION OF ", halo, " ROWS/COLS." i_start = 1 + halo i_end = i_mdl - halo j_start = 1 + halo j_end = j_mdl - halo + i_out = i_end - i_start + 1 + j_out = j_end - j_start + 1 + call writeit(out_file, i_out, j_out, num_categories, num_time_recs, & + lat_one_tile(i_start:i_end,j_start:j_end), & + lon_one_tile(i_start:i_end,j_start:j_end), & + data_one_tile(i_start:i_end,j_start:j_end,:), & + dom_cat_one_tile(i_start:i_end,j_start:j_end) ) + print*,"- WILL WRITE FULL DOMAIN INCLUDING HALO." + call writeit(out_file_with_halo, i_mdl, j_mdl, num_categories, num_time_recs, & + lat_one_tile, lon_one_tile, data_one_tile, dom_cat_one_tile) else - i_start = 1 - i_end = i_mdl - j_start = 1 - j_end = j_mdl + print*,"- WILL WRITE DATA." + call writeit(out_file, i_mdl, j_mdl, num_categories, num_time_recs, & + lat_one_tile, lon_one_tile, data_one_tile, dom_cat_one_tile) endif - i_out = i_end - i_start + 1 - j_out = j_end - j_start + 1 + return + + end subroutine output2 + + subroutine writeit(out_file, iout, jout, num_categories, num_time_recs, & + latitude, longitude, data_pct, dominate_cat) + + use esmf + use netcdf + use utils + use source_grid, only : day_of_rec, source, field_names + use model_grid, only : missing + + implicit none + + character(len=*), intent(in) :: out_file + + integer, intent(in) :: iout, jout, num_categories, num_time_recs + + real(esmf_kind_r4), intent(in) :: latitude(iout,jout) + real(esmf_kind_r4), intent(in) :: longitude(iout,jout) + real(esmf_kind_r4), intent(in) :: data_pct(iout,jout,num_categories) + real(esmf_kind_r4), intent(in) :: dominate_cat(iout,jout) + + character(len=200) :: field_names_pct + integer :: header_buffer_val = 16384 + integer :: ncid, dim_x, dim_y, dim_z, dim_time + integer :: id_times, id_lat, id_lon, id_data_pct + integer :: id_data_dom_cat, id_sum + integer :: error + real :: sum_all(iout,jout) + + print*,"- OPEN AND WRITE: ",trim(out_file) error = nf90_create(out_file, NF90_NETCDF4, ncid) - print*,'ncid is ',ncid call netcdf_err(error, 'ERROR IN NF90_CREATE' ) - error = nf90_def_dim(ncid, 'nx', i_out, dim_x) + error = nf90_def_dim(ncid, 'nx', iout, dim_x) call netcdf_err(error, 'DEFINING NX DIMENSION' ) - error = nf90_def_dim(ncid, 'ny', j_out, dim_y) + error = nf90_def_dim(ncid, 'ny', jout, dim_y) call netcdf_err(error, 'DEFINING NY DIMENSION' ) error = nf90_def_dim(ncid, 'num_categories', num_categories, dim_z) call netcdf_err(error, 'DEFINING NZ DIMENSION' ) error = nf90_def_dim(ncid, 'time', num_time_recs, dim_time) call netcdf_err(error, 'DEFINING TIME DIMENSION' ) + error = nf90_def_var(ncid, 'time', NF90_FLOAT, dim_time, id_times) call netcdf_err(error, 'DEFINING TIME VARIABLE' ) error = nf90_put_att(ncid, id_times, "units", "days since 2015-1-1") @@ -139,119 +171,26 @@ subroutine output2(data_one_tile, dom_cat_one_tile, lat_one_tile, lon_one_tile, call netcdf_err(error, 'DEFINING FIELD' ) error = nf90_enddef(ncid, header_buffer_val,4,0,4) - call netcdf_err(error, 'IN NF90_ENDDEF' ) error = nf90_put_var( ncid, id_times, day_of_rec) call netcdf_err(error, 'WRITING TIME FIELD' ) - error = nf90_put_var( ncid, id_lat, lat_one_tile(i_start:i_end,j_start:j_end), & - start=(/1,1/), count=(/i_out,j_out/)) + error = nf90_put_var( ncid, id_lat, latitude) call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLAT' ) - error = nf90_put_var( ncid, id_lon, lon_one_tile(i_start:i_end,j_start:j_end), & - start=(/1,1/), count=(/i_out,j_out/)) + error = nf90_put_var( ncid, id_lon, longitude) call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLON' ) - print*,'- WRITE DATA ' - error = nf90_put_var( ncid, id_data_pct, data_one_tile(i_start:i_end,j_start:j_end,:), & - start=(/1,1,1,1/), count=(/i_out,j_out,num_categories,1/)) + error = nf90_put_var( ncid, id_data_pct, data_pct) call netcdf_err(error, 'IN NF90_PUT_VAR' ) - error = nf90_put_var( ncid, id_data_dom_cat, dom_cat_one_tile(i_start:i_end,j_start:j_end), & - start=(/1,1,1/), count=(/i_out,j_out,1/)) + error = nf90_put_var( ncid, id_data_dom_cat, dominate_cat) call netcdf_err(error, 'IN NF90_PUT_VAR' ) ! Temporary output of sum of %. - sum_one_tile = sum(data_one_tile, dim=3) - error = nf90_put_var( ncid, id_sum, sum_one_tile(i_start:i_end,j_start:j_end), & - start=(/1,1,1/), count=(/i_out,j_out,1/)) + sum_all = sum(data_pct, dim=3) + error = nf90_put_var( ncid, id_sum, sum_all) error = nf90_close(ncid) -!---------------------------------------------------------------------- -! For regional nests, also output files including the halo -!---------------------------------------------------------------------- - - if (halo == 0) return - - print*,"- WRITE OUT FILES THAT INCLUDE HALO REGION." - - error = nf90_create(out_file_with_halo, NF90_NETCDF4, ncid_with_halo) - call netcdf_err(error, 'IN NF90_CREATE' ) - error = nf90_def_dim(ncid_with_halo, 'nx', i_mdl, dim_x) - call netcdf_err(error, 'DEFINING NX DIMENSION' ) - error = nf90_def_dim(ncid_with_halo, 'ny', j_mdl, dim_y) - call netcdf_err(error, 'DEFINING NY DIMENSION' ) - error = nf90_def_dim(ncid_with_halo, 'num_categories', num_categories, dim_z) - call netcdf_err(error, 'DEFINING NZ DIMENSION' ) - error = nf90_def_dim(ncid_with_halo, 'time', num_time_recs, dim_time) - call netcdf_err(error, 'DEFINING TIME DIMENSION' ) - error = nf90_def_var(ncid_with_halo, 'time', NF90_FLOAT, dim_time, id_times) - call netcdf_err(error, 'DEFINING TIME VARIABLE' ) - error = nf90_put_att(ncid_with_halo, id_times, "units", "days since 2015-1-1") - call netcdf_err(error, 'DEFINING TIME ATTRIBUTE' ) - if (len_trim(source) > 0) then - error = nf90_put_att(ncid_with_halo, nf90_global, 'source', source) - call netcdf_err(error, 'DEFINING GLOBAL SOURCE ATTRIBUTE' ) - endif - - error = nf90_def_var(ncid_with_halo, 'geolat', NF90_FLOAT, (/dim_x,dim_y/), id_lat) - call netcdf_err(error, 'DEFINING GEOLAT FIELD' ) - error = nf90_put_att(ncid_with_halo, id_lat, "long_name", "Latitude") - call netcdf_err(error, 'DEFINING GEOLAT NAME ATTRIBUTE' ) - error = nf90_put_att(ncid_with_halo, id_lat, "units", "degrees_north") - call netcdf_err(error, 'DEFINING GEOLAT UNIT ATTRIBUTE' ) - error = nf90_def_var(ncid_with_halo, 'geolon', NF90_FLOAT, (/dim_x,dim_y/), id_lon) - call netcdf_err(error, 'DEFINING GEOLON FIELD' ) - error = nf90_put_att(ncid_with_halo, id_lon, "long_name", "Longitude") - call netcdf_err(error, 'DEFINING GEOLON NAME ATTRIBUTE' ) - error = nf90_put_att(ncid_with_halo, id_lon, "units", "degrees_east") - call netcdf_err(error, 'DEFINING GEOLON UNIT ATTRIBUTE' ) - - error = nf90_def_var(ncid_with_halo, field_names_pct, NF90_FLOAT, (/dim_x,dim_y,dim_z,dim_time/), id_data_pct) - call netcdf_err(error, 'DEFINING FIELD VARIABLE' ) - error = nf90_put_att(ncid_with_halo, id_data_pct, "units", "percent coverage each category") - call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid_with_halo, id_data_pct, "missing_value", missing) - call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid_with_halo, id_data_pct, "coordinates", "geolon geolat") - call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) - - error = nf90_def_var(ncid_with_halo, trim(field_names(1)), NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_data_dom_cat) - call netcdf_err(error, 'DEFINING FIELD' ) - error = nf90_put_att(ncid_with_halo, id_data_dom_cat, "units", "dominate category") - call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid_with_halo, id_data_dom_cat, "missing_value", missing) - call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid_with_halo, id_data_dom_cat, "coordinates", "geolon geolat") - call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) - - error = nf90_enddef(ncid_with_halo, header_buffer_val,4,0,4) - call netcdf_err(error, 'WRITING HEADER ENDDEF' ) - - error = nf90_put_var(ncid_with_halo, id_times, day_of_rec) - call netcdf_err(error, 'WRITING TIME VARIABLE' ) - - error = nf90_put_var( ncid_with_halo, id_lat, lat_one_tile, & - start=(/1,1/), count=(/i_mdl,j_mdl/)) - call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLAT' ) - - error = nf90_put_var( ncid_with_halo, id_lon, lon_one_tile, & - start=(/1,1/), count=(/i_mdl,j_mdl/)) - call netcdf_err(error, 'IN NF90_PUT_VAR FOR GEOLON' ) - - print*,'- WRITE DATA' - - error = nf90_put_var(ncid_with_halo, id_data_pct, data_one_tile, & - start=(/1,1,1,1/), count=(/i_mdl,j_mdl,num_categories,1/)) - call netcdf_err(error, 'IN NF90_PUT_VAR' ) - - error = nf90_put_var(ncid_with_halo, id_data_dom_cat, dom_cat_one_tile, & - start=(/1,1,1/), count=(/i_mdl,j_mdl,1/)) - call netcdf_err(error, 'IN NF90_PUT_VAR' ) - - error = nf90_close(ncid_with_halo) - - return - - end subroutine output2 + end subroutine writeit From d5a349fc643f6f37db6005e75ed3560ed5820737 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Mon, 21 Nov 2022 19:29:01 +0000 Subject: [PATCH 19/50] Rename output2.f90 to a more descriptive name. Fixes #709. --- sorc/sfc_climo_gen.fd/{output2.f90 => output_frac_cats.F90} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename sorc/sfc_climo_gen.fd/{output2.f90 => output_frac_cats.F90} (100%) diff --git a/sorc/sfc_climo_gen.fd/output2.f90 b/sorc/sfc_climo_gen.fd/output_frac_cats.F90 similarity index 100% rename from sorc/sfc_climo_gen.fd/output2.f90 rename to sorc/sfc_climo_gen.fd/output_frac_cats.F90 From 28e70e755ddad668b1550a78e172cfaeb7bcd089 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Mon, 21 Nov 2022 22:01:03 +0000 Subject: [PATCH 20/50] Cleanup and rename search routine. More cleanup to output module. Fixes #709. --- sorc/sfc_climo_gen.fd/interp2.F90 | 5 +- sorc/sfc_climo_gen.fd/output_frac_cats.F90 | 72 +++++++++++++------ .../{search2.f90 => search_frac_cats.f90} | 56 +++++++-------- 3 files changed, 76 insertions(+), 57 deletions(-) rename sorc/sfc_climo_gen.fd/{search2.f90 => search_frac_cats.f90} (62%) diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp2.F90 index 13002b80c..64207b5ec 100644 --- a/sorc/sfc_climo_gen.fd/interp2.F90 +++ b/sorc/sfc_climo_gen.fd/interp2.F90 @@ -18,6 +18,7 @@ subroutine interp2(localpet, input_file) longitude_field_mdl, mask_field_mdl, & land_frac_field_mdl use source_grid + use output_frac_cats, only : output_driver use utils use mpi @@ -214,7 +215,7 @@ subroutine interp2(localpet, input_file) endif enddo enddo - call search2 (data_mdl_one_tile, mask_mdl_one_tile, i_mdl, j_mdl, num_categories, tile, field_names(1)) + call search_frac_cats (data_mdl_one_tile, mask_mdl_one_tile, i_mdl, j_mdl, num_categories, tile, field_names(1)) print*,'after regrid ',data_mdl_one_tile(i_mdl/2,j_mdl/2,:) ! These points are all non-land. Set to 100% of the water category. @@ -248,7 +249,7 @@ subroutine interp2(localpet, input_file) ! under fractional grids, how do we define dominate category? dom_cat_mdl_one_tile = 0.0 dom_cat_mdl_one_tile = maxloc(data_mdl_one_tile,dim=3) - call output2 (data_mdl_one_tile, dom_cat_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile) + call output_driver (data_mdl_one_tile, dom_cat_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile) endif enddo OUTPUT_LOOP diff --git a/sorc/sfc_climo_gen.fd/output_frac_cats.F90 b/sorc/sfc_climo_gen.fd/output_frac_cats.F90 index 8d14c6b19..31736806b 100644 --- a/sorc/sfc_climo_gen.fd/output_frac_cats.F90 +++ b/sorc/sfc_climo_gen.fd/output_frac_cats.F90 @@ -1,25 +1,39 @@ !> @file -!! @brief Output model data for a single tile and a single record. -!! @author George Gayno @date 2018 +!! @brief Write model categorical data for a single tile. +!! @author George Gayno NCEP/EMC @date 2022 -!> Output model data for a single tile and a single -!! record in netcdf format. +!> Output categorical data such as vegetation type. Include +!! percentage of each category within a model grid box and +!! the dominate category. !! -!! @param[in] data_one_tile Data to be output (single tile). -!! @param[in] lat_one_tile Latitude of tile. -!! @param[in] lon_one_tile Longitude of tile. -!! @param[in] field_idx Index of field within field name array. -!! @param[in] i_mdl i dimensions of tile. -!! @param[in] j_mdl j dimensions of tile. +!! @author George Gayno NCEP/EMC @date 2022 + module output_frac_cats + + implicit none + + private + + public :: output_driver + + contains + +!> Driver routine to output model categorical data. +!! +!! @param[in] data_one_tile The percentage of each category within a model grid cell. +!! @param[in] dom_cat_one_tile The dominate category within a model grid cell. +!! @param[in] lat_one_tile Latitude of each model grid cell. +!! @param[in] lon_one_tile Longitude of each model grid cell. +!! @param[in] i_mdl i dimension of model grid. +!! @param[in] j_mdl j dimension of model grid. +!! @param[in] num_categories Number of categories. !! @param[in] tile Tile number. -!! @author George Gayno @date 2018 - subroutine output2(data_one_tile, dom_cat_one_tile, lat_one_tile, lon_one_tile, i_mdl, j_mdl, & - num_categories, tile) +!! @author George Gayno @date 2022 + subroutine output_driver(data_one_tile, dom_cat_one_tile, lat_one_tile, lon_one_tile, & + i_mdl, j_mdl, num_categories, tile) use mpi use esmf - use source_grid, only : field_names, & - num_time_recs + use source_grid, only : field_names use model_grid, only : grid_tiles use program_setup, only : halo @@ -29,7 +43,7 @@ subroutine output2(data_one_tile, dom_cat_one_tile, lat_one_tile, lon_one_tile, real(esmf_kind_r4), intent(in) :: data_one_tile(i_mdl,j_mdl,num_categories) real(esmf_kind_r4), intent(in) :: dom_cat_one_tile(i_mdl,j_mdl) - real(esmf_kind_r4) :: lat_one_tile(i_mdl,j_mdl) + real(esmf_kind_r4), intent(in) :: lat_one_tile(i_mdl,j_mdl) real(esmf_kind_r4), intent(in) :: lon_one_tile(i_mdl,j_mdl) character(len=200) :: out_file @@ -67,38 +81,48 @@ subroutine output2(data_one_tile, dom_cat_one_tile, lat_one_tile, lon_one_tile, j_end = j_mdl - halo i_out = i_end - i_start + 1 j_out = j_end - j_start + 1 - call writeit(out_file, i_out, j_out, num_categories, num_time_recs, & + call writeit(out_file, i_out, j_out, num_categories, & lat_one_tile(i_start:i_end,j_start:j_end), & lon_one_tile(i_start:i_end,j_start:j_end), & data_one_tile(i_start:i_end,j_start:j_end,:), & dom_cat_one_tile(i_start:i_end,j_start:j_end) ) print*,"- WILL WRITE FULL DOMAIN INCLUDING HALO." - call writeit(out_file_with_halo, i_mdl, j_mdl, num_categories, num_time_recs, & + call writeit(out_file_with_halo, i_mdl, j_mdl, num_categories, & lat_one_tile, lon_one_tile, data_one_tile, dom_cat_one_tile) else print*,"- WILL WRITE DATA." - call writeit(out_file, i_mdl, j_mdl, num_categories, num_time_recs, & + call writeit(out_file, i_mdl, j_mdl, num_categories, & lat_one_tile, lon_one_tile, data_one_tile, dom_cat_one_tile) endif return - end subroutine output2 + end subroutine output_driver - subroutine writeit(out_file, iout, jout, num_categories, num_time_recs, & +!> Write data to a netcdf file. +!! +!! @param[in] out_file Output file name. +!! @param[in] iout i-dimension of data. +!! @param[in] jout j-dimension of data. +!! @param[in] num_categories Number of categories. +!! @param[in] latitude Latitude of data. +!! @param[in] latitude Longitude of data. +!! @param[in] data_pct Percentage of each category in each model grid cell. +!! @param[in] dominate_cat Dominate category in each model grid cell. + subroutine writeit(out_file, iout, jout, num_categories, & latitude, longitude, data_pct, dominate_cat) use esmf use netcdf use utils - use source_grid, only : day_of_rec, source, field_names + use source_grid, only : day_of_rec, source, field_names, num_time_recs use model_grid, only : missing implicit none character(len=*), intent(in) :: out_file - integer, intent(in) :: iout, jout, num_categories, num_time_recs + integer, intent(in) :: iout, jout, num_categories real(esmf_kind_r4), intent(in) :: latitude(iout,jout) real(esmf_kind_r4), intent(in) :: longitude(iout,jout) @@ -194,3 +218,5 @@ subroutine writeit(out_file, iout, jout, num_categories, num_time_recs, & error = nf90_close(ncid) end subroutine writeit + + end module output_frac_cats diff --git a/sorc/sfc_climo_gen.fd/search2.f90 b/sorc/sfc_climo_gen.fd/search_frac_cats.f90 similarity index 62% rename from sorc/sfc_climo_gen.fd/search2.f90 rename to sorc/sfc_climo_gen.fd/search_frac_cats.f90 index 5246bfb3f..09ead8929 100644 --- a/sorc/sfc_climo_gen.fd/search2.f90 +++ b/sorc/sfc_climo_gen.fd/search_frac_cats.f90 @@ -1,48 +1,45 @@ !> @file -!! @brief Replace undefined values on the model grid with a valid -!! value at a nearby neighbor. This routine works for fractional -!! categorical fields. +!! @brief Replace undefined values on the model grid. !! @author George Gayno @date 2022 -!> Replace undefined values on the model grid with a valid -!! value at a nearby neighbor. Undefined values are typically +!> Replace undefined values on the model grid with valid +!! values at a nearby neighbor. Undefined values are typically !! associated with isolated islands where there is no source data. !! Routine searches a neighborhood with a radius of 100 grid points. -!! If no valid value is found, a default value is used. This +!! If no valid values are found, a default value is used. This !! routine works for one tile of a cubed sphere grid. It does -!! not consider valid values at adjacent faces. That is a future -!! upgrade. +!! not consider valid values at adjacent faces. This routine +!! works for fractional categorical fields, such as soil +!! type. !! -!! @note This routine works for fractional categorical fields. -!! -!! @param[inout] field - input: field before missing values are replaced -!! - output: field after missing values are replaced -!! @param[in] mask field bitmap. Field defined where mask=1 -!! @param[in] idim i dimension of tile -!! @param[in] jdim j dimension of tile -!! @param[in] num_categories number of veg/soil categories -!! @param[in] tile tile number -!! @param[in] field_name field name +!! @param[inout] field - input: Field before missing values are replaced. +!! - output: Field after missing values are replaced. +!! @param[in] mask Field bitmap. Field defined where mask=1. +!! @param[in] idim i dimension of tile. +!! @param[in] jdim j dimension of tile. +!! @param[in] num_categories Number of veg/soil categories. +!! @param[in] tile Tile number. +!! @param[in] field_name Field name. !! @author George Gayno @date 2022 - subroutine search2 (field, mask, idim, jdim, num_categories, tile, field_name) + subroutine search_frac_cats (field, mask, idim, jdim, num_categories, tile, field_name) use mpi use esmf implicit none - character(len=*) :: field_name - integer, intent(in) :: idim, jdim, tile, num_categories integer(esmf_kind_i4), intent(in) :: mask(idim,jdim) real(esmf_kind_r4), intent(inout) :: field(idim,jdim,num_categories) + character(len=*) :: field_name + integer :: i, j, krad, ii, jj integer :: istart, iend integer :: jstart, jend integer :: ierr - integer :: default_category + integer :: default_category real(esmf_kind_r4), allocatable :: field_save(:,:,:) @@ -92,10 +89,9 @@ subroutine search2 (field, mask, idim, jdim, num_categories, tile, field_name) if (jj < 1 .or. jj > jdim) cycle JJ_LOOP if (ii < 1 .or. ii > idim) cycle II_LOOP - print*,'in search ',ii,jj,mask(ii,jj),maxval(field_save(ii,jj,:)) - if (mask(ii,jj) == 1 .and. maxval(field_save(ii,jj,:)) > 0.0) then + if (mask(ii,jj) == 1 .and. maxval(field_save(ii,jj,:)) > 0.0) then field(i,j,:) = field_save(ii,jj,:) - write(6,100) tile,i,j,ii,jj,field(i,j,1) + write(6,100) tile,i,j,ii,jj cycle I_LOOP endif @@ -115,13 +111,9 @@ subroutine search2 (field, mask, idim, jdim, num_categories, tile, field_name) enddo I_LOOP enddo J_LOOP - print*,'after search 59/166 ',field(59,166,:) - print*,'after search 60/167 ',field(60,167,:) - print*,'after search 55/168 ',field(55,168,:) - print*,'after search 56/169 ',field(55,168,:) deallocate(field_save) - 100 format(1x,"- MISSING2 POINT TILE: ",i2," I/J: ",i5,i5," SET TO VALUE AT: ",i5,i5,". NEW VALUE IS: ",f8.3) - 101 format(1x,"- MISSING2 POINT TILE: ",i2," I/J: ",i5,i5," SET TO DEFAULT VALUE OF: ",f8.3) + 100 format(1x,"- MISSING POINT TILE: ",i2," I/J: ",i5,i5," SET TO VALUE AT: ",i5,i5) + 101 format(1x,"- MISSING POINT TILE: ",i2," I/J: ",i5,i5," SET TO DEFAULT VALUE OF: ",i3) - end subroutine search2 + end subroutine search_frac_cats From d90eb6041bd80d40ee9614d32051cb318e1469d5 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Mon, 21 Nov 2022 22:05:42 +0000 Subject: [PATCH 21/50] Fix error in CMakeLists.txt. Fixes #709. --- sorc/sfc_climo_gen.fd/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/CMakeLists.txt b/sorc/sfc_climo_gen.fd/CMakeLists.txt index 20118b456..f6618c27c 100644 --- a/sorc/sfc_climo_gen.fd/CMakeLists.txt +++ b/sorc/sfc_climo_gen.fd/CMakeLists.txt @@ -8,17 +8,17 @@ set(lib_src interp2.F90 model_grid.F90 output.f90 - output2.f90 + output_frac_cats.F90 program_setup.f90 search.f90 - search2.f90 + search_frac_cats.f90 source_grid.F90 utils.f90) set(exe_src driver.F90) if(CMAKE_Fortran_COMPILER_ID MATCHES "^(Intel)$") - set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -r8") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -r8 -warn unused") elseif(CMAKE_Fortran_COMPILER_ID MATCHES "^(GNU)$") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -ffree-line-length-0 -fdefault-real-8") endif() From 209f0b1e97a6f2cde6d2269f6d0a721761b9a436 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Tue, 29 Nov 2022 21:11:03 +0000 Subject: [PATCH 22/50] Rename the interpolation routine to something more descriptive. Fixes #709. --- sorc/sfc_climo_gen.fd/CMakeLists.txt | 2 +- sorc/sfc_climo_gen.fd/{interp2.F90 => interp_frac_cats.F90} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename sorc/sfc_climo_gen.fd/{interp2.F90 => interp_frac_cats.F90} (100%) diff --git a/sorc/sfc_climo_gen.fd/CMakeLists.txt b/sorc/sfc_climo_gen.fd/CMakeLists.txt index f6618c27c..5a42f2261 100644 --- a/sorc/sfc_climo_gen.fd/CMakeLists.txt +++ b/sorc/sfc_climo_gen.fd/CMakeLists.txt @@ -5,7 +5,7 @@ set(lib_src interp.F90 - interp2.F90 + interp_frac_cats.F90 model_grid.F90 output.f90 output_frac_cats.F90 diff --git a/sorc/sfc_climo_gen.fd/interp2.F90 b/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 similarity index 100% rename from sorc/sfc_climo_gen.fd/interp2.F90 rename to sorc/sfc_climo_gen.fd/interp_frac_cats.F90 From 14adb2a22deb9d9d705b85abd0f5ccbbe32e5e44 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Tue, 29 Nov 2022 21:31:03 +0000 Subject: [PATCH 23/50] Updates for new routine name. Fixes #709. --- sorc/sfc_climo_gen.fd/driver.F90 | 4 ++-- sorc/sfc_climo_gen.fd/interp_frac_cats.F90 | 25 +++++++++++----------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/driver.F90 b/sorc/sfc_climo_gen.fd/driver.F90 index f369d250c..251108e15 100644 --- a/sorc/sfc_climo_gen.fd/driver.F90 +++ b/sorc/sfc_climo_gen.fd/driver.F90 @@ -82,7 +82,7 @@ program driver call define_source_grid(localpet, npets, input_vegetation_type_file) if (fract_vegsoil_type) then print*,'- WILL OUTPUT VEGETATION TYPE FRACTION.' - call interp2(localpet, input_vegetation_type_file) + call interp_frac_cats(localpet, input_vegetation_type_file) else print*,'- WILL OUTPUT DOMINATE VEGETATION TYPE.' method=ESMF_REGRIDMETHOD_NEAREST_STOD @@ -144,7 +144,7 @@ program driver call define_source_grid(localpet, npets, input_soil_type_file) if (fract_vegsoil_type) then print*,'- WILL OUTPUT SOIL TYPE FRACTION.' - call interp2(localpet, input_soil_type_file) + call interp_frac_cats(localpet, input_soil_type_file) else print*,'- WILL OUTPUT DOMINATE SOIL TYPE.' method=ESMF_REGRIDMETHOD_NEAREST_STOD diff --git a/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 b/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 index 64207b5ec..09da578c3 100644 --- a/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 +++ b/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 @@ -1,15 +1,16 @@ !> @file -!! @brief Read the input source data and interpolate it to the -!! model grid. -!! @author George Gayno @date 2018 +!! @brief Read the input cateogorical source data and +!! interpolate it to the model grid. +!! @author George Gayno @date 2022 !> Read the input source data and interpolate it to the -!! model grid. +!! model grid. Outputs the percentage of each category +!! within a model grid box and the dominate category. !! !! @param[in] localpet this mpi task !! @param[in] input_file filename of input source data. -!! @author George Gayno @date 2018 - subroutine interp2(localpet, input_file) +!! @author George Gayno @date 2022 + subroutine interp_frac_cats(localpet, input_file) use esmf use netcdf @@ -26,11 +27,12 @@ subroutine interp2(localpet, input_file) character(len=*), intent(in) :: input_file - integer :: rc, localpet - integer :: i, j, tile, ncid, status + integer, intent(in) :: localpet + + integer :: i, j, tile, ncid, status, rc integer :: varid, water_category integer :: isrctermprocessing - integer :: category, num_categories + integer :: category, num_categories integer(esmf_kind_i4), allocatable :: mask_mdl_one_tile(:,:) integer(esmf_kind_i4), pointer :: unmapped_ptr(:) @@ -44,12 +46,11 @@ subroutine interp2(localpet, input_file) real(esmf_kind_r4), allocatable :: lon_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: land_frac_mdl_one_tile(:,:) - type(esmf_regridmethod_flag) :: method + type(esmf_regridmethod_flag) :: method type(esmf_field) :: data_field_src type(esmf_field) :: data_field_mdl type(esmf_routehandle) :: regrid_data type(esmf_polemethod_flag) :: pole - if (localpet == 0) then allocate(data_src_global(i_src,j_src)) @@ -264,4 +265,4 @@ subroutine interp2(localpet, input_file) call mpi_barrier(mpi_comm_world, rc) - end subroutine interp2 + end subroutine interp_frac_cats From 43a405e197be85d7166b3808559138255a55d58d Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Thu, 1 Dec 2022 16:11:19 +0000 Subject: [PATCH 24/50] Add fractional grid logical flag to the sfc_climo_gen utility script. Fixes #709 --- util/sfc_climo_gen/run.wcoss2.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/util/sfc_climo_gen/run.wcoss2.sh b/util/sfc_climo_gen/run.wcoss2.sh index 11916b37b..44e6cdba9 100755 --- a/util/sfc_climo_gen/run.wcoss2.sh +++ b/util/sfc_climo_gen/run.wcoss2.sh @@ -13,7 +13,7 @@ #PBS -A GFS-DEV #PBS -N grid_fv3 #PBS -l walltime=00:10:00 -#PBS -l select=1:ncpus=24:mem=75GB +#PBS -l select=1:ncpus=24:mem=250GB set -x @@ -76,6 +76,12 @@ export veg_type_src="modis.igbp.0.05" export soil_type_src="statsgo.0.05" +export vegsoilt_frac='.true.' # When true, outputs percent of each + # soil and veg type category and a + # dominate category. When false, only + # outputs the dominate category. A + # Fortran logical, so include the dots. + #------------------------------------- # Set working directory and directory where output files will be saved. #------------------------------------- From 1b6dbcb6d7e7606f60e0a7ca1d9771dc7a7b4f67 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Thu, 1 Dec 2022 16:34:33 +0000 Subject: [PATCH 25/50] Clean up some comments in program_setup.f90 Fixes #709. --- sorc/sfc_climo_gen.fd/program_setup.f90 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/program_setup.f90 b/sorc/sfc_climo_gen.fd/program_setup.f90 index b7d6425e3..b91e68de2 100644 --- a/sorc/sfc_climo_gen.fd/program_setup.f90 +++ b/sorc/sfc_climo_gen.fd/program_setup.f90 @@ -35,16 +35,21 @@ module program_setup character(len=500), public :: orog_dir_mdl = "NULL" !< Directory containing the model grid orography files. character(len=500), public :: orog_files_mdl(6) = "NULL" !< Model grid orography filenames. - character(len=50), public :: leaf_area_index_method='bilinear' !< Interpolation method for leaf area index. Conservative or bilinear (default). - character(len=50), public :: maximum_snow_albedo_method='bilinear' !< Interpolation method for max snow albedo. Conservative or bilinear (default). - character(len=50), public :: snowfree_albedo_method='bilinear' !< Interpolation method for snowfree albedo. Conservative or bilinear (default). - character(len=50), public :: vegetation_greenness_method='bilinear' !< Interpolation method for vegetation greenness. Conservative or bilinear (default). + character(len=50), public :: leaf_area_index_method='bilinear' !< Interpolation method for leaf area index. + !! Conservative or bilinear (default). + character(len=50), public :: maximum_snow_albedo_method='bilinear' !< Interpolation method for max snow albedo. + !! Conservative or bilinear (default). + character(len=50), public :: snowfree_albedo_method='bilinear' !< Interpolation method for snowfree albedo. + !! Conservative or bilinear (default). + character(len=50), public :: vegetation_greenness_method='bilinear' !< Interpolation method for vegetation greenness. + !! Conservative or bilinear (default). integer, public :: halo = 0 !< Number of row/cols defining the lateral !! boundary halo. Used for regional nests. logical, public :: fract_vegsoil_type = .false. !< When true, output the percentage of each soil - !! and vegetation type category. + !! and vegetation type category, and the dominate + !! category within a model grid box. public :: read_setup_namelist From 1268330bd9724532b967785424d6733d1460ac5f Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Thu, 1 Dec 2022 18:35:39 +0000 Subject: [PATCH 26/50] Some cleanup to model_grid.F90. Fixes #709. --- sorc/sfc_climo_gen.fd/model_grid.F90 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/model_grid.F90 b/sorc/sfc_climo_gen.fd/model_grid.F90 index 532245cf5..abc6b4b37 100644 --- a/sorc/sfc_climo_gen.fd/model_grid.F90 +++ b/sorc/sfc_climo_gen.fd/model_grid.F90 @@ -4,7 +4,7 @@ !> This module defines the model grid. !! -!! Variables named with 'mdl' refer to the model grid. +!! Variables named with '_mdl' refer to the model grid. !! !! @author George Gayno @date 2018 module model_grid @@ -273,7 +273,7 @@ subroutine define_model_grid(localpet, npets) enddo - deallocate(mask_mdl_one_tile, latitude_one_tile, longitude_one_tile) + deallocate(mask_mdl_one_tile, latitude_one_tile, longitude_one_tile, land_frac_one_tile) print*,"- CALL GridAddItem FOR MODEL GRID." call ESMF_GridAddItem(grid_mdl, & @@ -298,10 +298,11 @@ end subroutine define_model_grid !> Get model information !! -!! Read model land/sea mask and lat/lon from the orography file. +!! Read model land/sea mask, land fraction and lat/lon from the orography file. !! !! @param[in] orog_file the orography file -!! @param[out] mask land/sea mask +!! @param[out] mask land/sea mask 0-all non-land; 1-some land. +!! @param[out] land_frac land fraction between 0 and 1. !! @param[out] lat2d latitude !! @param[out] lon2d longitude !! @param[in] idim i dimension of the model tile @@ -431,7 +432,7 @@ subroutine model_grid_cleanup print*,"- CALL FieldDestroy FOR MODEL GRID LAND MASK." call ESMF_FieldDestroy(mask_field_mdl,rc=rc) - print*,"- CALL FieldDestroy FOR MODEL GRID LAND MASK." + print*,"- CALL FieldDestroy FOR MODEL GRID LAND FRACTION." call ESMF_FieldDestroy(land_frac_field_mdl,rc=rc) print*,"- CALL FieldDestroy FOR MODEL GRID DATA FIELD." From 38c451965b6c4aab65b88bc80142837b1b71e96a Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Thu, 1 Dec 2022 18:42:32 +0000 Subject: [PATCH 27/50] Adjust some print statements in driver.F90 Fixes #709. --- sorc/sfc_climo_gen.fd/driver.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/driver.F90 b/sorc/sfc_climo_gen.fd/driver.F90 index 251108e15..ee8361e5d 100644 --- a/sorc/sfc_climo_gen.fd/driver.F90 +++ b/sorc/sfc_climo_gen.fd/driver.F90 @@ -81,7 +81,7 @@ program driver call define_source_grid(localpet, npets, input_vegetation_type_file) if (fract_vegsoil_type) then - print*,'- WILL OUTPUT VEGETATION TYPE FRACTION.' + print*,'- WILL OUTPUT VEGETATION TYPE FRACTION AND DOMINATE CATEGORY.' call interp_frac_cats(localpet, input_vegetation_type_file) else print*,'- WILL OUTPUT DOMINATE VEGETATION TYPE.' @@ -143,7 +143,7 @@ program driver if (trim(input_soil_type_file) /= "NULL") then call define_source_grid(localpet, npets, input_soil_type_file) if (fract_vegsoil_type) then - print*,'- WILL OUTPUT SOIL TYPE FRACTION.' + print*,'- WILL OUTPUT SOIL TYPE FRACTION AND DOMINATE CATEGORY.' call interp_frac_cats(localpet, input_soil_type_file) else print*,'- WILL OUTPUT DOMINATE SOIL TYPE.' From f443ca4d057e45b471583581f265af260c6efce4 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Thu, 1 Dec 2022 18:48:08 +0000 Subject: [PATCH 28/50] Fix doxygen in output_frac_cats.F90 Fixes #709. --- sorc/sfc_climo_gen.fd/output_frac_cats.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sorc/sfc_climo_gen.fd/output_frac_cats.F90 b/sorc/sfc_climo_gen.fd/output_frac_cats.F90 index 31736806b..e117f0876 100644 --- a/sorc/sfc_climo_gen.fd/output_frac_cats.F90 +++ b/sorc/sfc_climo_gen.fd/output_frac_cats.F90 @@ -106,7 +106,7 @@ end subroutine output_driver !! @param[in] jout j-dimension of data. !! @param[in] num_categories Number of categories. !! @param[in] latitude Latitude of data. -!! @param[in] latitude Longitude of data. +!! @param[in] longitude Longitude of data. !! @param[in] data_pct Percentage of each category in each model grid cell. !! @param[in] dominate_cat Dominate category in each model grid cell. subroutine writeit(out_file, iout, jout, num_categories, & From bb7492e42532e39b1f39a0e87f5e41ffdd6ea704 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Thu, 1 Dec 2022 19:02:20 +0000 Subject: [PATCH 29/50] Adjust comments in interp.F90. Fixes #709. --- sorc/sfc_climo_gen.fd/interp.F90 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sorc/sfc_climo_gen.fd/interp.F90 b/sorc/sfc_climo_gen.fd/interp.F90 index 540985ebd..ab91d918f 100644 --- a/sorc/sfc_climo_gen.fd/interp.F90 +++ b/sorc/sfc_climo_gen.fd/interp.F90 @@ -186,7 +186,11 @@ subroutine interp(localpet, method, input_file) enddo -! These fields are adjusted at landice. +! Adjust some fields at permanent land ice points. These points are identified by the +! 'permanent ice' vegetation type category. +! +! When outputting the fraction of each vegetation type, land ice points are +! not defined. So don't do this adjustment. if (.not. fract_vegsoil_type) then select case (trim(field_names(n))) From dcf39aff2ae079ea638f099d90ec36f8d470aa8e Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Thu, 1 Dec 2022 19:43:06 +0000 Subject: [PATCH 30/50] Adjust comments in interp_frac_cats.F90 Fixes #709. --- sorc/sfc_climo_gen.fd/interp_frac_cats.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 b/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 index 09da578c3..1ea2c851c 100644 --- a/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 +++ b/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 @@ -1,6 +1,7 @@ !> @file !! @brief Read the input cateogorical source data and -!! interpolate it to the model grid. +!! interpolate percent of each category to the model grid. +!! !! @author George Gayno @date 2022 !> Read the input source data and interpolate it to the From 271966300a26abc56013fec49fdfa2fca79c5a91 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Wed, 7 Dec 2022 20:38:04 +0000 Subject: [PATCH 31/50] Update 'readthedocs' for new option. Fixes #709. --- docs/source/ufs_utils.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/ufs_utils.rst b/docs/source/ufs_utils.rst index 6ae0ae5ae..bcb8b95dc 100644 --- a/docs/source/ufs_utils.rst +++ b/docs/source/ufs_utils.rst @@ -511,6 +511,7 @@ Program execution is controlled via a namelist. The namelist variables are: * maximum_snow_albedo_method - interpolation method for this field. Bilinear or conservative. Default is bilinear. * snowfree_albedo_method - interpolation method for this field. Bilinear or conservative. Default is bilinear. * vegetation_greenness_method - interpolation method for this field. Bilinear or conservative. Default is bilinear. + * vegsoilt_frac - When 'true', outputs the dominate soil and vegetation type, and the fraction of each category. When 'false', only outputs the dominate categories. Default is 'false'. Program inputs and outputs -------------------------- From 0368ddda3f59e7d91e3e792cab6d427a50770165 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Wed, 7 Dec 2022 21:12:02 +0000 Subject: [PATCH 32/50] More readthedocs updates. Fixes #709. --- docs/source/ufs_utils.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/source/ufs_utils.rst b/docs/source/ufs_utils.rst index bcb8b95dc..17a91cb1b 100644 --- a/docs/source/ufs_utils.rst +++ b/docs/source/ufs_utils.rst @@ -484,10 +484,13 @@ Location of the source code: ./sorc/sfc_climo_gen.fd. Brief description of each * driver.F90 - The main driver routine. * interp.F90 - The interpolation driver routine. Reads the input source data and interpolates it to the model grid. + * interp_frac_cats.F90 - Same as interp.F90, but for computing the fraction of each soil and vegetation type category. (When namelist variable 'vegsoilt_frac' is true). * model_grid.F90 - Defines the ESMF grid object for the model grid. * output.f90 - Writes the output surface data to a NetCDF file. For regional grids, will output separate files with and without the halo. + * output_frac_cats.f90 - Same as output.f90, but for writing fractional soil and vegetation type. (When namelist variable 'vegsoilt_frac' is true). * program_setup.f90 - Reads the namelist and sets up program execution. * search.f90 - Replace undefined values on the model grid with a valid value at a nearby neighbor. Undefined values are typically associated with isolated islands where there is no source data. + * search_frac_cats.f90 - Same as search.f90, but for the fractional soil and vegetation type option. (When namelist variable 'vegsoilt_frac' is true). * source_grid.F90 - Reads the grid specifications and land/sea mask for the source data. Sets up the ESMF grid object for the source grid. * utils.f90 - Contains error handling utility routines. From 8366bc36b632a2fd2ced3a74eb2006ac3e11a0a9 Mon Sep 17 00:00:00 2001 From: George Gayno Date: Fri, 9 Dec 2022 20:07:38 +0000 Subject: [PATCH 33/50] Update Hera build module to point to Gerhard's ESMF test branch. Fixes #709. --- modulefiles/build.hera.intel.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modulefiles/build.hera.intel.lua b/modulefiles/build.hera.intel.lua index d82571889..b523fdf54 100644 --- a/modulefiles/build.hera.intel.lua +++ b/modulefiles/build.hera.intel.lua @@ -58,8 +58,7 @@ load(pathJoin("netcdf", netcdf_ver)) nccmp_ver=os.getenv("nccmp_ver") or "1.8.9.0" load(pathJoin("nccmp", nccmp_ver)) -esmf_ver=os.getenv("esmf_ver") or "8.2.1b04" -load(pathJoin("esmf", esmf_ver)) +setenv("ESMFMKFILE","/scratch1/NCEPDEV/da/George.Gayno/noscrub/esmf.git/esmf/lib/libO/Linux.intel.64.intelmpi.default/esmf.mk") nco_ver=os.getenv("nco_ver") or "4.9.1" load(pathJoin("nco", nco_ver)) From 96531796eea21ed9925f98a631971e6c6c2e7f5b Mon Sep 17 00:00:00 2001 From: George Gayno Date: Tue, 13 Dec 2022 18:36:24 +0000 Subject: [PATCH 34/50] Add comment for using bigmem nodes in Hera grid driver script. Fixes #709. --- driver_scripts/driver_grid.hera.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/driver_scripts/driver_grid.hera.sh b/driver_scripts/driver_grid.hera.sh index ba216083d..5c0363528 100755 --- a/driver_scripts/driver_grid.hera.sh +++ b/driver_scripts/driver_grid.hera.sh @@ -6,6 +6,7 @@ #SBATCH -o log.fv3_grid_driver #SBATCH -e log.fv3_grid_driver #SBATCH --nodes=1 --ntasks-per-node=24 +##SBATCH --partition=bigmem #SBATCH -q debug #SBATCH -t 00:30:00 From 116b79ac23335a90cb23e0a0a6f58a09faeebb28 Mon Sep 17 00:00:00 2001 From: George Gayno Date: Mon, 19 Dec 2022 16:47:57 +0000 Subject: [PATCH 35/50] Update all grid scripts. Fixes #709. --- driver_scripts/driver_grid.hera.sh | 8 +++++--- driver_scripts/driver_grid.jet.sh | 6 ++++++ driver_scripts/driver_grid.orion.sh | 6 ++++++ driver_scripts/driver_grid.wcoss2.sh | 2 +- ush/sfc_climo_gen.sh | 4 ++++ util/sfc_climo_gen/run.wcoss2.sh | 2 +- 6 files changed, 23 insertions(+), 5 deletions(-) diff --git a/driver_scripts/driver_grid.hera.sh b/driver_scripts/driver_grid.hera.sh index 5c0363528..8bec8ad1c 100755 --- a/driver_scripts/driver_grid.hera.sh +++ b/driver_scripts/driver_grid.hera.sh @@ -8,7 +8,7 @@ #SBATCH --nodes=1 --ntasks-per-node=24 ##SBATCH --partition=bigmem #SBATCH -q debug -#SBATCH -t 00:30:00 +#SBATCH -t 00:10:00 #----------------------------------------------------------------------- # Driver script to create a cubic-sphere based model grid on Hera. @@ -79,9 +79,11 @@ export gtype=uniform # 'uniform', 'stretch', 'nest', export make_gsl_orog=false # When 'true' will output 'oro' files for # the GSL orographic drag suite. -export vegsoilt_frac='.true.' # When .false., output dominate soil and +export vegsoilt_frac='.false.' # When .false., output dominate soil and # vegetation type category. When .true., - # output fraction of each category. + # output fraction of each category and + # the dominate category. A Fortran logical, + # so include the dots. export veg_type_src="modis.igbp.0.05" # Vegetation type data. # For viirs-based vegetation type data, set to: diff --git a/driver_scripts/driver_grid.jet.sh b/driver_scripts/driver_grid.jet.sh index 62869e540..848167db8 100755 --- a/driver_scripts/driver_grid.jet.sh +++ b/driver_scripts/driver_grid.jet.sh @@ -78,6 +78,12 @@ export gtype=uniform # 'uniform', 'stretch', 'nest', export make_gsl_orog=false # When 'true' will output 'oro' files for # the GSL orographic drag suite. +export vegsoilt_frac='.false.' # When true, outputs percent of each + # soil and veg type category and a + # dominate category. When false, only + # outputs the dominate category. A + # Fortran logical, so include the dots. + export veg_type_src="modis.igbp.0.05" # Vegetation type data. # For viirs-based vegetation type data, set to: # 1) "viirs.igbp.0.1" for global 0.10-deg data diff --git a/driver_scripts/driver_grid.orion.sh b/driver_scripts/driver_grid.orion.sh index f0a74a33e..42a1b8f13 100755 --- a/driver_scripts/driver_grid.orion.sh +++ b/driver_scripts/driver_grid.orion.sh @@ -77,6 +77,12 @@ export gtype=regional_esg # 'uniform', 'stretch', 'nest', export make_gsl_orog=false # When 'true' will output 'oro' files for # the GSL orographic drag suite. +export vegsoilt_frac='.false.' # When true, outputs percent of each + # soil and veg type category and a + # dominate category. When false, only + # outputs the dominate category. A + # Fortran logical, so include the dots. + export veg_type_src="modis.igbp.0.05" # Vegetation type data. # For viirs-based vegetation type data, set to: # 1) "viirs.igbp.0.1" for global 0.10-deg data diff --git a/driver_scripts/driver_grid.wcoss2.sh b/driver_scripts/driver_grid.wcoss2.sh index b2dd8b374..97504e383 100755 --- a/driver_scripts/driver_grid.wcoss2.sh +++ b/driver_scripts/driver_grid.wcoss2.sh @@ -76,7 +76,7 @@ export gtype=regional_esg # 'uniform', 'stretch', 'nest', export make_gsl_orog=false # When 'true' will output 'oro' files for # the GSL orographic drag suite. -export vegsoilt_frac='.true.' # When true, outputs percent of each +export vegsoilt_frac='.false.' # When true, outputs percent of each # soil and veg type category and a # dominate category. When false, only # outputs the dominate category. A diff --git a/ush/sfc_climo_gen.sh b/ush/sfc_climo_gen.sh index 922fa1b7f..4e9242aa0 100755 --- a/ush/sfc_climo_gen.sh +++ b/ush/sfc_climo_gen.sh @@ -25,6 +25,10 @@ # WORK_DIR Temporary working directory # SOIL_TYPE_FILE Path/name of input soil type data. # VEG_TYPE_FILE Path/name of input vegetation type data. +# vegsoilt_frac When true, outputs dominate soil and +# vegetation type category and the +# fractional value of each category. +# When false, outputs dominate category. #------------------------------------------------------------------------- set -eux diff --git a/util/sfc_climo_gen/run.wcoss2.sh b/util/sfc_climo_gen/run.wcoss2.sh index fdc433110..a96eceeec 100755 --- a/util/sfc_climo_gen/run.wcoss2.sh +++ b/util/sfc_climo_gen/run.wcoss2.sh @@ -79,7 +79,7 @@ export veg_type_src="modis.igbp.0.05" export soil_type_src="statsgo.0.05" -export vegsoilt_frac='.true.' # When true, outputs percent of each +export vegsoilt_frac='.false.' # When true, outputs percent of each # soil and veg type category and a # dominate category. When false, only # outputs the dominate category. A From cd4eb0f19ad8cc17092b91b4985f987fcdcadf88 Mon Sep 17 00:00:00 2001 From: George Gayno Date: Mon, 19 Dec 2022 16:54:19 +0000 Subject: [PATCH 36/50] Remove debugging flag. Fixes #709. --- sorc/sfc_climo_gen.fd/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sorc/sfc_climo_gen.fd/CMakeLists.txt b/sorc/sfc_climo_gen.fd/CMakeLists.txt index 5a42f2261..a9103106f 100644 --- a/sorc/sfc_climo_gen.fd/CMakeLists.txt +++ b/sorc/sfc_climo_gen.fd/CMakeLists.txt @@ -18,7 +18,7 @@ set(lib_src set(exe_src driver.F90) if(CMAKE_Fortran_COMPILER_ID MATCHES "^(Intel)$") - set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -r8 -warn unused") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -r8") elseif(CMAKE_Fortran_COMPILER_ID MATCHES "^(GNU)$") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -ffree-line-length-0 -fdefault-real-8") endif() From 306cd434fc4cada86abafdccf912b3da1256f7da Mon Sep 17 00:00:00 2001 From: George Gayno Date: Tue, 20 Dec 2022 16:29:34 +0000 Subject: [PATCH 37/50] Add unit test for namelist read routine. Fixes #709. --- cmake/mpiexec.hera | 2 +- tests/sfc_climo_gen/CMakeLists.txt | 12 +++++- tests/sfc_climo_gen/data/fort.41 | 20 +++++++++ tests/sfc_climo_gen/ftst_program_setup.F90 | 48 ++++++++++++++++++++++ 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 tests/sfc_climo_gen/data/fort.41 create mode 100644 tests/sfc_climo_gen/ftst_program_setup.F90 diff --git a/cmake/mpiexec.hera b/cmake/mpiexec.hera index e82f1e9da..23bec1047 100755 --- a/cmake/mpiexec.hera +++ b/cmake/mpiexec.hera @@ -6,7 +6,7 @@ # $2+ - Executable and its arguments # -ACCOUNT=gsd-fv3 +ACCOUNT=fv3-cpu QOS=debug NP=$1 diff --git a/tests/sfc_climo_gen/CMakeLists.txt b/tests/sfc_climo_gen/CMakeLists.txt index 82e90207f..0067900d7 100644 --- a/tests/sfc_climo_gen/CMakeLists.txt +++ b/tests/sfc_climo_gen/CMakeLists.txt @@ -33,10 +33,20 @@ include_directories(${PROJECT_SOURCE_DIR}) execute_process( COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/LSanSuppress.supp ${CMAKE_CURRENT_BINARY_DIR}/LSanSuppress.supp) +execute_process( COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/data/fort.41 ${CMAKE_CURRENT_BINARY_DIR}/fort.41) + add_executable(ftst_interp ftst_interp.F90) target_link_libraries(ftst_interp sfc_climo_gen_lib) -# Cause test to be run with MPI. +add_executable(ftst_pgm_setup ftst_program_setup.F90) +target_link_libraries(ftst_pgm_setup sfc_climo_gen_lib) + +add_mpi_test(sfc_climo_gen-ftst_pgm_setup + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/ftst_pgm_setup + NUMPROCS 1 + TIMEOUT 60) + add_mpi_test(sfc_climo_gen-ftst_interp EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/ftst_interp NUMPROCS 1 diff --git a/tests/sfc_climo_gen/data/fort.41 b/tests/sfc_climo_gen/data/fort.41 new file mode 100644 index 000000000..dfc739da4 --- /dev/null +++ b/tests/sfc_climo_gen/data/fort.41 @@ -0,0 +1,20 @@ + &config + input_leaf_area_index_file="leaf" + input_facsf_file="facsf" + input_substrate_temperature_file="substrate_temp" + input_maximum_snow_albedo_file="maxsnow_alb" + input_snowfree_albedo_file="snowfree_alb" + input_slope_type_file="slope" + input_soil_type_file="soil_type" + input_soil_color_file="soil_color" + input_vegetation_type_file="veg_type" + input_vegetation_greenness_file="greenness" + mosaic_file_mdl="mosaic.nc" + orog_dir_mdl="./orog" + orog_files_mdl="oro.tile1.nc","oro.tile2.nc","oro.tile3.nc","oro.tile4.nc","oro.tile5.nc","oro.tile6.nc" + leaf_area_index_method="bilinear" + maximum_snow_albedo_method="conserve" + snowfree_albedo_method="bilinear" + vegetation_greenness_method="conserve" + halo=4 + / diff --git a/tests/sfc_climo_gen/ftst_program_setup.F90 b/tests/sfc_climo_gen/ftst_program_setup.F90 new file mode 100644 index 000000000..8b991d205 --- /dev/null +++ b/tests/sfc_climo_gen/ftst_program_setup.F90 @@ -0,0 +1,48 @@ +! Unit test for sfc_climo_gen utility, program_setup.f90. + +program ftst_pgm_setup + use program_setup + use mpi + implicit none + + integer :: my_rank, ierr + + call mpi_init(ierr) + call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr) + + if (my_rank .eq. 0) print*,"Starting test of program_setup." + if (my_rank .eq. 0) print*,"Call routine read_setup_namelist." + + call read_setup_namelist(my_rank) + + if (trim(input_leaf_area_index_file) /= "leaf") stop 2 + if (trim(input_facsf_file) /= "facsf") stop 4 + if (trim(input_substrate_temperature_file) /= "substrate_temp") stop 6 + if (trim(input_maximum_snow_albedo_file) /= "maxsnow_alb") stop 8 + if (trim(input_snowfree_albedo_file) /= "snowfree_alb") stop 10 + if (trim(input_slope_type_file) /= "slope") stop 12 + if (trim(input_soil_type_file) /= "soil_type") stop 14 + if (trim(input_soil_color_file) /= "soil_color") stop 16 + if (trim(input_vegetation_type_file) /= "veg_type") stop 18 + if (trim(input_vegetation_greenness_file) /= "greenness") stop 20 + if (trim(mosaic_file_mdl) /= "mosaic.nc") stop 22 + if (trim(orog_dir_mdl) /= "./orog") stop 24 + if (trim(orog_files_mdl(1)) /= "oro.tile1.nc") stop 26 + if (trim(orog_files_mdl(2)) /= "oro.tile2.nc") stop 28 + if (trim(orog_files_mdl(3)) /= "oro.tile3.nc") stop 30 + if (trim(orog_files_mdl(4)) /= "oro.tile4.nc") stop 32 + if (trim(orog_files_mdl(5)) /= "oro.tile5.nc") stop 34 + if (trim(orog_files_mdl(6)) /= "oro.tile6.nc") stop 36 + if (trim(leaf_area_index_method) /= "bilinear") stop 38 + if (trim(maximum_snow_albedo_method) /= "conserve") stop 40 + if (trim(snowfree_albedo_method) /= "bilinear") stop 42 + if (trim(vegetation_greenness_method) /= "conserve") stop 44 + if (halo /= 4) stop 46 + + if (my_rank .eq. 0) print*, "OK" + + if (my_rank .eq. 0) print*, "SUCCESS!" + + call mpi_finalize(ierr) + +end program ftst_pgm_setup From 80603b3d11602f22835d17bd70d1eebd42ec01a5 Mon Sep 17 00:00:00 2001 From: George Gayno Date: Tue, 20 Dec 2022 17:42:40 +0000 Subject: [PATCH 38/50] Add newest namelist variable to new unit test. Fixes #709. --- tests/sfc_climo_gen/data/fort.41 | 1 + tests/sfc_climo_gen/ftst_program_setup.F90 | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/sfc_climo_gen/data/fort.41 b/tests/sfc_climo_gen/data/fort.41 index dfc739da4..c42cf7df9 100644 --- a/tests/sfc_climo_gen/data/fort.41 +++ b/tests/sfc_climo_gen/data/fort.41 @@ -17,4 +17,5 @@ snowfree_albedo_method="bilinear" vegetation_greenness_method="conserve" halo=4 + fract_vegsoil_type=.true. / diff --git a/tests/sfc_climo_gen/ftst_program_setup.F90 b/tests/sfc_climo_gen/ftst_program_setup.F90 index 8b991d205..e63115e8e 100644 --- a/tests/sfc_climo_gen/ftst_program_setup.F90 +++ b/tests/sfc_climo_gen/ftst_program_setup.F90 @@ -37,6 +37,7 @@ program ftst_pgm_setup if (trim(maximum_snow_albedo_method) /= "conserve") stop 40 if (trim(snowfree_albedo_method) /= "bilinear") stop 42 if (trim(vegetation_greenness_method) /= "conserve") stop 44 + if (.not. fract_vegsoil_type) stop 46 if (halo /= 4) stop 46 if (my_rank .eq. 0) print*, "OK" From 64a9bd04bca995f28f4e6b34ec6e8082e29bcb6d Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Wed, 21 Dec 2022 21:38:10 +0000 Subject: [PATCH 39/50] Change definition of dominate category when processing fractional land/nonland grids. Fixes #709. --- sorc/sfc_climo_gen.fd/interp_frac_cats.F90 | 28 ++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 b/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 index 1ea2c851c..d068a7cdf 100644 --- a/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 +++ b/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 @@ -30,8 +30,8 @@ subroutine interp_frac_cats(localpet, input_file) integer, intent(in) :: localpet - integer :: i, j, tile, ncid, status, rc - integer :: varid, water_category + integer :: i, j, tile, cat, ncid, status, rc + integer :: varid, water_category, max_cat integer :: isrctermprocessing integer :: category, num_categories @@ -46,6 +46,7 @@ subroutine interp_frac_cats(localpet, input_file) real(esmf_kind_r4), allocatable :: sum_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: lon_mdl_one_tile(:,:) real(esmf_kind_r4), allocatable :: land_frac_mdl_one_tile(:,:) + real(esmf_kind_r4) :: max_frac type(esmf_regridmethod_flag) :: method type(esmf_field) :: data_field_src @@ -237,20 +238,33 @@ subroutine interp_frac_cats(localpet, input_file) ! grids, this array will contain negative fill values. if (maxval(land_frac_mdl_one_tile) > 0.0) then - print*,'before rescale ',land_frac_mdl_one_tile(658,95),data_mdl_one_tile(658,95,:) + print*,'before rescale ',tile,land_frac_mdl_one_tile(42,82),data_mdl_one_tile(42,82,:) do j = 1, j_mdl do i = 1, i_mdl if (mask_mdl_one_tile(i,j) == 1) then data_mdl_one_tile(i,j,:) = data_mdl_one_tile(i,j,:) * land_frac_mdl_one_tile(i,j) data_mdl_one_tile(i,j,water_category) = 1.0 - land_frac_mdl_one_tile(i,j) + max_frac = 0.0 + max_cat = -9 + do cat = 1, num_categories + if (cat == water_category) cycle + if(data_mdl_one_tile(i,j,cat) > max_frac) then + max_frac = data_mdl_one_tile(i,j,cat) + max_cat = cat + endif + enddo + dom_cat_mdl_one_tile(i,j) = max_cat + else + dom_cat_mdl_one_tile(i,j) = water_category endif enddo enddo - print*,'after rescale ',land_frac_mdl_one_tile(658,95),data_mdl_one_tile(658,95,:) + print*,'after rescale ',tile,land_frac_mdl_one_tile(42,82),data_mdl_one_tile(42,82,:) + else ! non-fractonal grids. + dom_cat_mdl_one_tile = 0.0 + dom_cat_mdl_one_tile = maxloc(data_mdl_one_tile,dim=3) endif -! under fractional grids, how do we define dominate category? - dom_cat_mdl_one_tile = 0.0 - dom_cat_mdl_one_tile = maxloc(data_mdl_one_tile,dim=3) + print*,'dominate cat ',tile,dom_cat_mdl_one_tile(42,82) call output_driver (data_mdl_one_tile, dom_cat_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile) endif From b19b2f83b1d776d58d18a446d399c5ada862b99e Mon Sep 17 00:00:00 2001 From: George Gayno Date: Tue, 27 Dec 2022 18:41:19 +0000 Subject: [PATCH 40/50] Point to original esmf library instead of my local copy. Fixes #709. --- modulefiles/build.hera.intel.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modulefiles/build.hera.intel.lua b/modulefiles/build.hera.intel.lua index b523fdf54..7c0824aa0 100644 --- a/modulefiles/build.hera.intel.lua +++ b/modulefiles/build.hera.intel.lua @@ -58,7 +58,9 @@ load(pathJoin("netcdf", netcdf_ver)) nccmp_ver=os.getenv("nccmp_ver") or "1.8.9.0" load(pathJoin("nccmp", nccmp_ver)) -setenv("ESMFMKFILE","/scratch1/NCEPDEV/da/George.Gayno/noscrub/esmf.git/esmf/lib/libO/Linux.intel.64.intelmpi.default/esmf.mk") +-- setenv("ESMFMKFILE","/scratch1/NCEPDEV/da/George.Gayno/noscrub/esmf.git/esmf/lib/libO/Linux.intel.64.intelmpi.default/esmf.mk") +nccmp_ver=os.getenv("esmf_ver") or "8.2.1b04" +load(pathJoin("esmf", esmf_ver)) nco_ver=os.getenv("nco_ver") or "4.9.1" load(pathJoin("nco", nco_ver)) From c63846a76256147ea29e8ba749b50e0cc4efe386 Mon Sep 17 00:00:00 2001 From: George Gayno Date: Wed, 28 Dec 2022 19:15:53 +0000 Subject: [PATCH 41/50] Comment out write of 'sum' of each category record. This was for testing only. Fixes #709. --- sorc/sfc_climo_gen.fd/output_frac_cats.F90 | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/output_frac_cats.F90 b/sorc/sfc_climo_gen.fd/output_frac_cats.F90 index e117f0876..0710108bc 100644 --- a/sorc/sfc_climo_gen.fd/output_frac_cats.F90 +++ b/sorc/sfc_climo_gen.fd/output_frac_cats.F90 @@ -133,10 +133,11 @@ subroutine writeit(out_file, iout, jout, num_categories, & integer :: header_buffer_val = 16384 integer :: ncid, dim_x, dim_y, dim_z, dim_time integer :: id_times, id_lat, id_lon, id_data_pct - integer :: id_data_dom_cat, id_sum + integer :: id_data_dom_cat +!integer :: id_sum integer :: error - real :: sum_all(iout,jout) +!real :: sum_all(iout,jout) print*,"- OPEN AND WRITE: ",trim(out_file) error = nf90_create(out_file, NF90_NETCDF4, ncid) @@ -191,8 +192,8 @@ subroutine writeit(out_file, iout, jout, num_categories, & error = nf90_put_att(ncid, id_data_dom_cat, "coordinates", "geolon geolat") call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) - error = nf90_def_var(ncid, 'sum', NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_sum) - call netcdf_err(error, 'DEFINING FIELD' ) +!error = nf90_def_var(ncid, 'sum', NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_sum) +!call netcdf_err(error, 'DEFINING FIELD' ) error = nf90_enddef(ncid, header_buffer_val,4,0,4) @@ -212,8 +213,8 @@ subroutine writeit(out_file, iout, jout, num_categories, & call netcdf_err(error, 'IN NF90_PUT_VAR' ) ! Temporary output of sum of %. - sum_all = sum(data_pct, dim=3) - error = nf90_put_var( ncid, id_sum, sum_all) +!sum_all = sum(data_pct, dim=3) +!error = nf90_put_var( ncid, id_sum, sum_all) error = nf90_close(ncid) From a5a9fe6c1222c12d49bac8645b366f9713b6e61c Mon Sep 17 00:00:00 2001 From: George Gayno Date: Fri, 6 Jan 2023 15:07:51 -0600 Subject: [PATCH 42/50] Remove unused 'missing' attribute from soil/veg files. Fixes #709. --- sorc/sfc_climo_gen.fd/output_frac_cats.F90 | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sorc/sfc_climo_gen.fd/output_frac_cats.F90 b/sorc/sfc_climo_gen.fd/output_frac_cats.F90 index 0710108bc..a639b1b92 100644 --- a/sorc/sfc_climo_gen.fd/output_frac_cats.F90 +++ b/sorc/sfc_climo_gen.fd/output_frac_cats.F90 @@ -116,7 +116,6 @@ subroutine writeit(out_file, iout, jout, num_categories, & use netcdf use utils use source_grid, only : day_of_rec, source, field_names, num_time_recs - use model_grid, only : missing implicit none @@ -178,8 +177,6 @@ subroutine writeit(out_file, iout, jout, num_categories, & call netcdf_err(error, 'DEFINING FIELD' ) error = nf90_put_att(ncid, id_data_pct, "units", "percent coverage each category") call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid, id_data_pct, "missing_value", missing) - call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) error = nf90_put_att(ncid, id_data_pct, "coordinates", "geolon geolat") call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) @@ -187,8 +184,6 @@ subroutine writeit(out_file, iout, jout, num_categories, & call netcdf_err(error, 'DEFINING FIELD' ) error = nf90_put_att(ncid, id_data_dom_cat, "units", "dominate category") call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) - error = nf90_put_att(ncid, id_data_dom_cat, "missing_value", missing) - call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) error = nf90_put_att(ncid, id_data_dom_cat, "coordinates", "geolon geolat") call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) From 01efea0cd91e722dda2eddcee4bf58324d2e26f8 Mon Sep 17 00:00:00 2001 From: George Gayno Date: Mon, 9 Jan 2023 08:31:29 -0600 Subject: [PATCH 43/50] Add consistency test for new functionality. Fixes #709. --- reg_tests/grid_gen/driver.orion.sh | 19 ++++-- reg_tests/grid_gen/esg.regional.pct.cat.sh | 75 ++++++++++++++++++++++ 2 files changed, 89 insertions(+), 5 deletions(-) create mode 100755 reg_tests/grid_gen/esg.regional.pct.cat.sh diff --git a/reg_tests/grid_gen/driver.orion.sh b/reg_tests/grid_gen/driver.orion.sh index 08cdd2e1b..4c8bc0e28 100755 --- a/reg_tests/grid_gen/driver.orion.sh +++ b/reg_tests/grid_gen/driver.orion.sh @@ -82,7 +82,7 @@ TEST3=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_ -o $LOG_FILE3 -e $LOG_FILE3 ./gfdl.regional.sh) #----------------------------------------------------------------------------- -# ESG regional grid +# ESG regional grid (output dominate soil/vegetation type). #----------------------------------------------------------------------------- LOG_FILE4=${LOG_FILE}04 @@ -90,19 +90,28 @@ TEST4=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_ -o $LOG_FILE4 -e $LOG_FILE4 ./esg.regional.sh) #----------------------------------------------------------------------------- -# Regional grid with GSL gravity wave drag fields. +# ESG regional grid (output percent of each soil and vegetation type and +# the dominate category). #----------------------------------------------------------------------------- LOG_FILE5=${LOG_FILE}05 -TEST5=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J reg.gsl.gwd \ - -o $LOG_FILE5 -e $LOG_FILE5 ./regional.gsl.gwd.sh) +TEST5=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J esg.regional.pct.cat \ + -o $LOG_FILE5 -e $LOG_FILE5 ./esg.regional.pct.cat.sh) + +#----------------------------------------------------------------------------- +# Regional grid with GSL gravity wave drag fields. +#----------------------------------------------------------------------------- + +LOG_FILE6=${LOG_FILE}06 +TEST6=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J reg.gsl.gwd \ + -o $LOG_FILE6 -e $LOG_FILE6 ./regional.gsl.gwd.sh) #----------------------------------------------------------------------------- # Create summary log. #----------------------------------------------------------------------------- sbatch --nodes=1 -t 0:01:00 -A $PROJECT_CODE -J grid_summary -o $LOG_FILE -e $LOG_FILE \ - -q $QUEUE -d afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5 << EOF + -q $QUEUE -d afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6 << EOF #!/bin/bash grep -a '<<<' ${LOG_FILE}* > $SUM_FILE EOF diff --git a/reg_tests/grid_gen/esg.regional.pct.cat.sh b/reg_tests/grid_gen/esg.regional.pct.cat.sh new file mode 100755 index 000000000..1083e9b5c --- /dev/null +++ b/reg_tests/grid_gen/esg.regional.pct.cat.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +#----------------------------------------------------------------------- +# Create a regional esg grid. Output dominate soil and vegetation +# categories and well as the percentage of each category. +# Compare output to a set of baseline files using the 'nccmp' +# utility. This script is run by the machine specific driver script. +#----------------------------------------------------------------------- + +set -x + +TEST_NAME="esg.regional.pct.cat" +export TEMP_DIR=${WORK_DIR}/${TEST_NAME}.work +export out_dir=${WORK_DIR}/${TEST_NAME} + +export gtype=regional_esg +export target_lon=-97.5 # Center longitude of the highest resolution tile +export target_lat=35.5 # Center latitude of the highest resolution tile +export idim=1301 # Dimension of grid in 'i' direction +export jdim=600 # Dimension of grid in 'j' direction +export delx=0.0145 # Grid spacing in degrees in 'i' direction +export dely=0.0145 # Grid spacing in degrees in 'j' direction +export halo=3 +export vegsoilt_frac=.true. # Output dominate soil/veg categories as well + # as the percentage of each category. + +NCCMP=${NCCMP:-$(which nccmp)} + +#----------------------------------------------------------------------- +# Start script. +#----------------------------------------------------------------------- + +echo "Starting at: " `date` + +$home_dir/ush/fv3gfs_driver_grid.sh + +iret=$? +if [ $iret -ne 0 ]; then + set +x + echo "<<< ESG REGIONAL PERCENT CATEGORY TEST FAILED. <<<" + exit $iret +fi + +echo "Ending at: " `date` + +#----------------------------------------------------------------------------- +# Compare output to baseline set of data. +#----------------------------------------------------------------------------- + +cd $out_dir/C3113 + +test_failed=0 +for files in *tile*.nc ./fix_sfc/*tile*.nc +do + if [ -f $files ]; then + echo CHECK $files + $NCCMP -dmfqS $files $HOMEreg/${TEST_NAME}/$files + iret=$? + if [ $iret -ne 0 ]; then + test_failed=1 + fi + fi +done + +set +x +if [ $test_failed -ne 0 ]; then + echo "<<< ESG REGIONAL PERCENT CATEGORY TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $home_dir/reg_tests/update_baseline.sh "${HOMEreg}/.." "${TEST_NAME}" $commit_num + fi +else + echo "<<< ESG REGIONAL PERCENT CATEGORY TEST PASSED. >>>" +fi + +exit 0 From 9a2f72c8a9ea239053d0e189ff37f76b5a0bf03d Mon Sep 17 00:00:00 2001 From: George Gayno Date: Mon, 9 Jan 2023 15:24:03 +0000 Subject: [PATCH 44/50] Update Jet driver script for new consistency test. Fixes #709. --- reg_tests/grid_gen/driver.jet.sh | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/reg_tests/grid_gen/driver.jet.sh b/reg_tests/grid_gen/driver.jet.sh index fc5b6aa27..aa1ae6978 100755 --- a/reg_tests/grid_gen/driver.jet.sh +++ b/reg_tests/grid_gen/driver.jet.sh @@ -84,7 +84,7 @@ TEST3=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_ --partition=xjet -o $LOG_FILE3 -e $LOG_FILE3 ./gfdl.regional.sh) #----------------------------------------------------------------------------- -# ESG regional grid +# ESG regional grid (output dominate soil/vegetation type). #----------------------------------------------------------------------------- LOG_FILE4=${LOG_FILE}04 @@ -92,19 +92,28 @@ TEST4=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_ --partition=xjet -o $LOG_FILE4 -e $LOG_FILE4 ./esg.regional.sh) #----------------------------------------------------------------------------- -# Regional GSL gravity wave drag. +# ESG regional grid (output percent of each soil and vegetation type and +# the dominate category). #----------------------------------------------------------------------------- LOG_FILE5=${LOG_FILE}05 -TEST5=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J reg.gsl.gwd \ - --partition=xjet -o $LOG_FILE5 -e $LOG_FILE5 ./regional.gsl.gwd.sh) +TEST5=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J esg.regional.pct.cat \ + --partition=xjet -o $LOG_FILE5 -e $LOG_FILE5 ./esg.regional.pct.cat.sh) + +#----------------------------------------------------------------------------- +# Regional GSL gravity wave drag. +#----------------------------------------------------------------------------- + +LOG_FILE6=${LOG_FILE}06 +TEST6=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J reg.gsl.gwd \ + --partition=xjet -o $LOG_FILE6 -e $LOG_FILE6 ./regional.gsl.gwd.sh) #----------------------------------------------------------------------------- # Create summary log. #----------------------------------------------------------------------------- sbatch --partition=xjet --nodes=1 -t 0:01:00 -A $PROJECT_CODE -J grid_summary -o $LOG_FILE -e $LOG_FILE \ - -q $QUEUE -d afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5 << EOF + -q $QUEUE -d afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6 << EOF #!/bin/bash grep -a '<<<' ${LOG_FILE}* > $SUM_FILE EOF From eccfe40c829bfe6a22bcb0316a0643e813496ba0 Mon Sep 17 00:00:00 2001 From: George Gayno Date: Mon, 9 Jan 2023 15:41:38 +0000 Subject: [PATCH 45/50] Update hera driver script for new consistency test. Fixes #709. --- reg_tests/grid_gen/driver.hera.sh | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/reg_tests/grid_gen/driver.hera.sh b/reg_tests/grid_gen/driver.hera.sh index fc7199374..64f5ed28f 100755 --- a/reg_tests/grid_gen/driver.hera.sh +++ b/reg_tests/grid_gen/driver.hera.sh @@ -86,7 +86,7 @@ TEST3=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_ -o $LOG_FILE3 -e $LOG_FILE3 ./gfdl.regional.sh) #----------------------------------------------------------------------------- -# esg regional grid +# ESG regional grid (output dominate soil/vegetation type). #----------------------------------------------------------------------------- LOG_FILE4=${LOG_FILE}04 @@ -94,19 +94,28 @@ TEST4=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_ -o $LOG_FILE4 -e $LOG_FILE4 ./esg.regional.sh) #----------------------------------------------------------------------------- -# Regional GSL gravity wave drag test. +# ESG regional grid (output percent of each soil and vegetation type and +# the dominate category). #----------------------------------------------------------------------------- LOG_FILE5=${LOG_FILE}05 -TEST5=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J reg.gsl.gwd \ - -o $LOG_FILE5 -e $LOG_FILE5 ./regional.gsl.gwd.sh) +TEST5=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J esg.regional.pct.cat \ + -o $LOG_FILE5 -e $LOG_FILE5 ./esg.regional.pct.cat.sh) + +#----------------------------------------------------------------------------- +# Regional GSL gravity wave drag test. +#----------------------------------------------------------------------------- + +LOG_FILE6=${LOG_FILE}06 +TEST6=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J reg.gsl.gwd \ + -o $LOG_FILE6 -e $LOG_FILE6 ./regional.gsl.gwd.sh) #----------------------------------------------------------------------------- # Create summary log. #----------------------------------------------------------------------------- sbatch --nodes=1 -t 0:01:00 -A $PROJECT_CODE -J grid_summary -o $LOG_FILE -e $LOG_FILE \ - --open-mode=append -q $QUEUE -d afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5 << EOF + --open-mode=append -q $QUEUE -d afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6 << EOF #!/bin/bash grep -a '<<<' ${LOG_FILE}* > $SUM_FILE EOF From e0ab34cfca455f8c59a48177b4c3394ced09c8a5 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Mon, 9 Jan 2023 16:00:14 +0000 Subject: [PATCH 46/50] Update wcoss2 driver script for new consistency test. Fixes #709. --- reg_tests/grid_gen/driver.wcoss2.sh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/reg_tests/grid_gen/driver.wcoss2.sh b/reg_tests/grid_gen/driver.wcoss2.sh index efa7a8f44..280d30bf2 100755 --- a/reg_tests/grid_gen/driver.wcoss2.sh +++ b/reg_tests/grid_gen/driver.wcoss2.sh @@ -87,7 +87,7 @@ TEST3=$(qsub -V -o $LOG_FILE3 -e $LOG_FILE3 -q $QUEUE -A $PROJECT_CODE -l wallti -N gfdl.regional -l select=1:ncpus=30:mem=40GB $PWD/gfdl.regional.sh) #----------------------------------------------------------------------------- -# esg regional grid +# ESG regional grid (output dominate soil/vegetation type). #----------------------------------------------------------------------------- LOG_FILE4=${LOG_FILE}04 @@ -95,11 +95,20 @@ TEST4=$(qsub -V -o $LOG_FILE4 -e $LOG_FILE4 -q $QUEUE -A $PROJECT_CODE -l wallti -N esg.regional -l select=1:ncpus=30:mem=40GB $PWD/esg.regional.sh) #----------------------------------------------------------------------------- -# Regional GSL gravity wave drag test. +# ESG regional grid (output percent of each soil and vegetation type and +# the dominate category). #----------------------------------------------------------------------------- LOG_FILE5=${LOG_FILE}05 TEST5=$(qsub -V -o $LOG_FILE5 -e $LOG_FILE5 -q $QUEUE -A $PROJECT_CODE -l walltime=00:07:00 \ + -N esg.regional.pct.cat -l select=1:ncpus=30:mem=40GB $PWD/esg.regional.pct.cat.sh) + +#----------------------------------------------------------------------------- +# Regional GSL gravity wave drag test. +#----------------------------------------------------------------------------- + +LOG_FILE6=${LOG_FILE}06 +TEST6=$(qsub -V -o $LOG_FILE6 -e $LOG_FILE6 -q $QUEUE -A $PROJECT_CODE -l walltime=00:07:00 \ -N rsg.gsl.gwd -l select=1:ncpus=30:mem=40GB $PWD/regional.gsl.gwd.sh) #----------------------------------------------------------------------------- @@ -107,7 +116,7 @@ TEST5=$(qsub -V -o $LOG_FILE5 -e $LOG_FILE5 -q $QUEUE -A $PROJECT_CODE -l wallti #----------------------------------------------------------------------------- qsub -V -o ${LOG_FILE} -e ${LOG_FILE} -q $QUEUE -A $PROJECT_CODE -l walltime=00:02:00 \ - -N grid_summary -l select=1:ncpus=1:mem=100MB -W depend=afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5 << EOF + -N grid_summary -l select=1:ncpus=1:mem=100MB -W depend=afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6 << EOF #!/bin/bash cd ${this_dir} grep -a '<<<' ${LOG_FILE}* | grep -v echo > $SUM_FILE From 17fa799ef08e5bc0f80206e936536844b2c3cf2c Mon Sep 17 00:00:00 2001 From: George Gayno Date: Mon, 9 Jan 2023 16:16:19 +0000 Subject: [PATCH 47/50] Revert to origin esmf version for Hera build. Fixes #709. --- modulefiles/build.hera.intel.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modulefiles/build.hera.intel.lua b/modulefiles/build.hera.intel.lua index 7c0824aa0..e72494593 100644 --- a/modulefiles/build.hera.intel.lua +++ b/modulefiles/build.hera.intel.lua @@ -59,7 +59,7 @@ nccmp_ver=os.getenv("nccmp_ver") or "1.8.9.0" load(pathJoin("nccmp", nccmp_ver)) -- setenv("ESMFMKFILE","/scratch1/NCEPDEV/da/George.Gayno/noscrub/esmf.git/esmf/lib/libO/Linux.intel.64.intelmpi.default/esmf.mk") -nccmp_ver=os.getenv("esmf_ver") or "8.2.1b04" +esmf_ver=os.getenv("esmf_ver") or "8.2.1b04" load(pathJoin("esmf", esmf_ver)) nco_ver=os.getenv("nco_ver") or "4.9.1" From b483cc8eebe08c029c6fc469dd58dc89aee006b8 Mon Sep 17 00:00:00 2001 From: George Gayno Date: Mon, 30 Jan 2023 15:59:11 +0000 Subject: [PATCH 48/50] Minor updates the Hera grid driver script. Fixes #709. --- driver_scripts/driver_grid.hera.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/driver_scripts/driver_grid.hera.sh b/driver_scripts/driver_grid.hera.sh index 8bec8ad1c..43fe01321 100755 --- a/driver_scripts/driver_grid.hera.sh +++ b/driver_scripts/driver_grid.hera.sh @@ -8,7 +8,7 @@ #SBATCH --nodes=1 --ntasks-per-node=24 ##SBATCH --partition=bigmem #SBATCH -q debug -#SBATCH -t 00:10:00 +#SBATCH -t 00:20:00 #----------------------------------------------------------------------- # Driver script to create a cubic-sphere based model grid on Hera. @@ -24,8 +24,9 @@ # Note: The sfc_climo_gen program only runs with an # mpi task count that is a multiple of six. This is # an ESMF library requirement. Large grids may require -# tasks spread across multiple nodes. The orography code -# benefits from threads. +# tasks spread across multiple nodes or to be run on +# 'bigmem' nodes (#SBATCH --partition=bigmem). The +# orography code benefits from threads. # # To run, do the following: # From 8ecba17317b8db894b3be2aecaf4f620708b32e0 Mon Sep 17 00:00:00 2001 From: "George.Gayno" Date: Mon, 6 Feb 2023 14:17:14 +0000 Subject: [PATCH 49/50] Fix spelling mistakes. Fixes #709. --- driver_scripts/driver_grid.hera.sh | 4 ++-- driver_scripts/driver_grid.jet.sh | 4 ++-- driver_scripts/driver_grid.orion.sh | 4 ++-- driver_scripts/driver_grid.wcoss2.sh | 4 ++-- reg_tests/grid_gen/driver.hera.sh | 4 ++-- reg_tests/grid_gen/driver.jet.sh | 4 ++-- reg_tests/grid_gen/driver.orion.sh | 4 ++-- reg_tests/grid_gen/driver.wcoss2.sh | 4 ++-- reg_tests/grid_gen/esg.regional.pct.cat.sh | 4 ++-- sorc/sfc_climo_gen.fd/driver.F90 | 8 ++++---- sorc/sfc_climo_gen.fd/interp_frac_cats.F90 | 4 +--- sorc/sfc_climo_gen.fd/output_frac_cats.F90 | 14 +++++++------- sorc/sfc_climo_gen.fd/program_setup.f90 | 2 +- ush/sfc_climo_gen.sh | 4 ++-- 14 files changed, 33 insertions(+), 35 deletions(-) diff --git a/driver_scripts/driver_grid.hera.sh b/driver_scripts/driver_grid.hera.sh index 43fe01321..3f10f6095 100755 --- a/driver_scripts/driver_grid.hera.sh +++ b/driver_scripts/driver_grid.hera.sh @@ -80,10 +80,10 @@ export gtype=uniform # 'uniform', 'stretch', 'nest', export make_gsl_orog=false # When 'true' will output 'oro' files for # the GSL orographic drag suite. -export vegsoilt_frac='.false.' # When .false., output dominate soil and +export vegsoilt_frac='.false.' # When .false., output dominant soil and # vegetation type category. When .true., # output fraction of each category and - # the dominate category. A Fortran logical, + # the dominant category. A Fortran logical, # so include the dots. export veg_type_src="modis.igbp.0.05" # Vegetation type data. diff --git a/driver_scripts/driver_grid.jet.sh b/driver_scripts/driver_grid.jet.sh index 848167db8..2a9ef3e9f 100755 --- a/driver_scripts/driver_grid.jet.sh +++ b/driver_scripts/driver_grid.jet.sh @@ -80,8 +80,8 @@ export make_gsl_orog=false # When 'true' will output 'oro' files for export vegsoilt_frac='.false.' # When true, outputs percent of each # soil and veg type category and a - # dominate category. When false, only - # outputs the dominate category. A + # dominant category. When false, only + # outputs the dominant category. A # Fortran logical, so include the dots. export veg_type_src="modis.igbp.0.05" # Vegetation type data. diff --git a/driver_scripts/driver_grid.orion.sh b/driver_scripts/driver_grid.orion.sh index 42a1b8f13..3b56094c3 100755 --- a/driver_scripts/driver_grid.orion.sh +++ b/driver_scripts/driver_grid.orion.sh @@ -79,8 +79,8 @@ export make_gsl_orog=false # When 'true' will output 'oro' files for export vegsoilt_frac='.false.' # When true, outputs percent of each # soil and veg type category and a - # dominate category. When false, only - # outputs the dominate category. A + # dominant category. When false, only + # outputs the dominant category. A # Fortran logical, so include the dots. export veg_type_src="modis.igbp.0.05" # Vegetation type data. diff --git a/driver_scripts/driver_grid.wcoss2.sh b/driver_scripts/driver_grid.wcoss2.sh index 97504e383..1a9c4bfb3 100755 --- a/driver_scripts/driver_grid.wcoss2.sh +++ b/driver_scripts/driver_grid.wcoss2.sh @@ -78,8 +78,8 @@ export make_gsl_orog=false # When 'true' will output 'oro' files for export vegsoilt_frac='.false.' # When true, outputs percent of each # soil and veg type category and a - # dominate category. When false, only - # outputs the dominate category. A + # dominant category. When false, only + # outputs the dominant category. A # Fortran logical, so include the dots. export veg_type_src="modis.igbp.0.05" # Vegetation type data. diff --git a/reg_tests/grid_gen/driver.hera.sh b/reg_tests/grid_gen/driver.hera.sh index 64f5ed28f..ef3b37b1c 100755 --- a/reg_tests/grid_gen/driver.hera.sh +++ b/reg_tests/grid_gen/driver.hera.sh @@ -86,7 +86,7 @@ TEST3=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_ -o $LOG_FILE3 -e $LOG_FILE3 ./gfdl.regional.sh) #----------------------------------------------------------------------------- -# ESG regional grid (output dominate soil/vegetation type). +# ESG regional grid (output dominant soil/vegetation type). #----------------------------------------------------------------------------- LOG_FILE4=${LOG_FILE}04 @@ -95,7 +95,7 @@ TEST4=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_ #----------------------------------------------------------------------------- # ESG regional grid (output percent of each soil and vegetation type and -# the dominate category). +# the dominant category). #----------------------------------------------------------------------------- LOG_FILE5=${LOG_FILE}05 diff --git a/reg_tests/grid_gen/driver.jet.sh b/reg_tests/grid_gen/driver.jet.sh index aa1ae6978..2d3f5fcfc 100755 --- a/reg_tests/grid_gen/driver.jet.sh +++ b/reg_tests/grid_gen/driver.jet.sh @@ -84,7 +84,7 @@ TEST3=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_ --partition=xjet -o $LOG_FILE3 -e $LOG_FILE3 ./gfdl.regional.sh) #----------------------------------------------------------------------------- -# ESG regional grid (output dominate soil/vegetation type). +# ESG regional grid (output dominant soil/vegetation type). #----------------------------------------------------------------------------- LOG_FILE4=${LOG_FILE}04 @@ -93,7 +93,7 @@ TEST4=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_ #----------------------------------------------------------------------------- # ESG regional grid (output percent of each soil and vegetation type and -# the dominate category). +# the dominant category). #----------------------------------------------------------------------------- LOG_FILE5=${LOG_FILE}05 diff --git a/reg_tests/grid_gen/driver.orion.sh b/reg_tests/grid_gen/driver.orion.sh index 4c8bc0e28..a3a60e678 100755 --- a/reg_tests/grid_gen/driver.orion.sh +++ b/reg_tests/grid_gen/driver.orion.sh @@ -82,7 +82,7 @@ TEST3=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_ -o $LOG_FILE3 -e $LOG_FILE3 ./gfdl.regional.sh) #----------------------------------------------------------------------------- -# ESG regional grid (output dominate soil/vegetation type). +# ESG regional grid (output dominant soil/vegetation type). #----------------------------------------------------------------------------- LOG_FILE4=${LOG_FILE}04 @@ -91,7 +91,7 @@ TEST4=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_ #----------------------------------------------------------------------------- # ESG regional grid (output percent of each soil and vegetation type and -# the dominate category). +# the dominant category). #----------------------------------------------------------------------------- LOG_FILE5=${LOG_FILE}05 diff --git a/reg_tests/grid_gen/driver.wcoss2.sh b/reg_tests/grid_gen/driver.wcoss2.sh index 280d30bf2..da8b9d0ed 100755 --- a/reg_tests/grid_gen/driver.wcoss2.sh +++ b/reg_tests/grid_gen/driver.wcoss2.sh @@ -87,7 +87,7 @@ TEST3=$(qsub -V -o $LOG_FILE3 -e $LOG_FILE3 -q $QUEUE -A $PROJECT_CODE -l wallti -N gfdl.regional -l select=1:ncpus=30:mem=40GB $PWD/gfdl.regional.sh) #----------------------------------------------------------------------------- -# ESG regional grid (output dominate soil/vegetation type). +# ESG regional grid (output dominant soil/vegetation type). #----------------------------------------------------------------------------- LOG_FILE4=${LOG_FILE}04 @@ -96,7 +96,7 @@ TEST4=$(qsub -V -o $LOG_FILE4 -e $LOG_FILE4 -q $QUEUE -A $PROJECT_CODE -l wallti #----------------------------------------------------------------------------- # ESG regional grid (output percent of each soil and vegetation type and -# the dominate category). +# the dominant category). #----------------------------------------------------------------------------- LOG_FILE5=${LOG_FILE}05 diff --git a/reg_tests/grid_gen/esg.regional.pct.cat.sh b/reg_tests/grid_gen/esg.regional.pct.cat.sh index 1083e9b5c..2afbed9e1 100755 --- a/reg_tests/grid_gen/esg.regional.pct.cat.sh +++ b/reg_tests/grid_gen/esg.regional.pct.cat.sh @@ -1,7 +1,7 @@ #!/bin/bash #----------------------------------------------------------------------- -# Create a regional esg grid. Output dominate soil and vegetation +# Create a regional esg grid. Output dominant soil and vegetation # categories and well as the percentage of each category. # Compare output to a set of baseline files using the 'nccmp' # utility. This script is run by the machine specific driver script. @@ -21,7 +21,7 @@ export jdim=600 # Dimension of grid in 'j' direction export delx=0.0145 # Grid spacing in degrees in 'i' direction export dely=0.0145 # Grid spacing in degrees in 'j' direction export halo=3 -export vegsoilt_frac=.true. # Output dominate soil/veg categories as well +export vegsoilt_frac=.true. # Output dominant soil/veg categories as well # as the percentage of each category. NCCMP=${NCCMP:-$(which nccmp)} diff --git a/sorc/sfc_climo_gen.fd/driver.F90 b/sorc/sfc_climo_gen.fd/driver.F90 index 481fcb0a9..520cc99d8 100644 --- a/sorc/sfc_climo_gen.fd/driver.F90 +++ b/sorc/sfc_climo_gen.fd/driver.F90 @@ -81,10 +81,10 @@ program driver call define_source_grid(localpet, npets, input_vegetation_type_file) if (fract_vegsoil_type) then - print*,'- WILL OUTPUT VEGETATION TYPE FRACTION AND DOMINATE CATEGORY.' + print*,'- WILL OUTPUT VEGETATION TYPE FRACTION AND DOMINANT CATEGORY.' call interp_frac_cats(localpet, input_vegetation_type_file) else - print*,'- WILL OUTPUT DOMINATE VEGETATION TYPE.' + print*,'- WILL OUTPUT DOMINANT VEGETATION TYPE.' method=ESMF_REGRIDMETHOD_NEAREST_STOD call interp(localpet, method, input_vegetation_type_file) endif @@ -143,10 +143,10 @@ program driver if (trim(input_soil_type_file) /= "NULL") then call define_source_grid(localpet, npets, input_soil_type_file) if (fract_vegsoil_type) then - print*,'- WILL OUTPUT SOIL TYPE FRACTION AND DOMINATE CATEGORY.' + print*,'- WILL OUTPUT SOIL TYPE FRACTION AND DOMINANT CATEGORY.' call interp_frac_cats(localpet, input_soil_type_file) else - print*,'- WILL OUTPUT DOMINATE SOIL TYPE.' + print*,'- WILL OUTPUT DOMINANT SOIL TYPE.' method=ESMF_REGRIDMETHOD_NEAREST_STOD call interp(localpet, method, input_soil_type_file) endif diff --git a/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 b/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 index d068a7cdf..d82091acf 100644 --- a/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 +++ b/sorc/sfc_climo_gen.fd/interp_frac_cats.F90 @@ -6,7 +6,7 @@ !> Read the input source data and interpolate it to the !! model grid. Outputs the percentage of each category -!! within a model grid box and the dominate category. +!! within a model grid box and the dominant category. !! !! @param[in] localpet this mpi task !! @param[in] input_file filename of input source data. @@ -259,12 +259,10 @@ subroutine interp_frac_cats(localpet, input_file) endif enddo enddo - print*,'after rescale ',tile,land_frac_mdl_one_tile(42,82),data_mdl_one_tile(42,82,:) else ! non-fractonal grids. dom_cat_mdl_one_tile = 0.0 dom_cat_mdl_one_tile = maxloc(data_mdl_one_tile,dim=3) endif - print*,'dominate cat ',tile,dom_cat_mdl_one_tile(42,82) call output_driver (data_mdl_one_tile, dom_cat_mdl_one_tile, lat_mdl_one_tile, lon_mdl_one_tile, i_mdl, j_mdl, num_categories, tile) endif diff --git a/sorc/sfc_climo_gen.fd/output_frac_cats.F90 b/sorc/sfc_climo_gen.fd/output_frac_cats.F90 index a639b1b92..732eced58 100644 --- a/sorc/sfc_climo_gen.fd/output_frac_cats.F90 +++ b/sorc/sfc_climo_gen.fd/output_frac_cats.F90 @@ -4,7 +4,7 @@ !> Output categorical data such as vegetation type. Include !! percentage of each category within a model grid box and -!! the dominate category. +!! the dominant category. !! !! @author George Gayno NCEP/EMC @date 2022 module output_frac_cats @@ -20,7 +20,7 @@ module output_frac_cats !> Driver routine to output model categorical data. !! !! @param[in] data_one_tile The percentage of each category within a model grid cell. -!! @param[in] dom_cat_one_tile The dominate category within a model grid cell. +!! @param[in] dom_cat_one_tile The dominant category within a model grid cell. !! @param[in] lat_one_tile Latitude of each model grid cell. !! @param[in] lon_one_tile Longitude of each model grid cell. !! @param[in] i_mdl i dimension of model grid. @@ -108,9 +108,9 @@ end subroutine output_driver !! @param[in] latitude Latitude of data. !! @param[in] longitude Longitude of data. !! @param[in] data_pct Percentage of each category in each model grid cell. -!! @param[in] dominate_cat Dominate category in each model grid cell. +!! @param[in] dominant_cat Dominant category in each model grid cell. subroutine writeit(out_file, iout, jout, num_categories, & - latitude, longitude, data_pct, dominate_cat) + latitude, longitude, data_pct, dominant_cat) use esmf use netcdf @@ -126,7 +126,7 @@ subroutine writeit(out_file, iout, jout, num_categories, & real(esmf_kind_r4), intent(in) :: latitude(iout,jout) real(esmf_kind_r4), intent(in) :: longitude(iout,jout) real(esmf_kind_r4), intent(in) :: data_pct(iout,jout,num_categories) - real(esmf_kind_r4), intent(in) :: dominate_cat(iout,jout) + real(esmf_kind_r4), intent(in) :: dominant_cat(iout,jout) character(len=200) :: field_names_pct integer :: header_buffer_val = 16384 @@ -182,7 +182,7 @@ subroutine writeit(out_file, iout, jout, num_categories, & error = nf90_def_var(ncid, trim(field_names(1)), NF90_FLOAT, (/dim_x,dim_y,dim_time/), id_data_dom_cat) call netcdf_err(error, 'DEFINING FIELD' ) - error = nf90_put_att(ncid, id_data_dom_cat, "units", "dominate category") + error = nf90_put_att(ncid, id_data_dom_cat, "units", "dominant category") call netcdf_err(error, 'DEFINING FIELD ATTRIBUTE' ) error = nf90_put_att(ncid, id_data_dom_cat, "coordinates", "geolon geolat") call netcdf_err(error, 'DEFINING COORD ATTRIBUTE' ) @@ -204,7 +204,7 @@ subroutine writeit(out_file, iout, jout, num_categories, & error = nf90_put_var( ncid, id_data_pct, data_pct) call netcdf_err(error, 'IN NF90_PUT_VAR' ) - error = nf90_put_var( ncid, id_data_dom_cat, dominate_cat) + error = nf90_put_var( ncid, id_data_dom_cat, dominant_cat) call netcdf_err(error, 'IN NF90_PUT_VAR' ) ! Temporary output of sum of %. diff --git a/sorc/sfc_climo_gen.fd/program_setup.f90 b/sorc/sfc_climo_gen.fd/program_setup.f90 index fbf1d8f0f..6c1a9068c 100644 --- a/sorc/sfc_climo_gen.fd/program_setup.f90 +++ b/sorc/sfc_climo_gen.fd/program_setup.f90 @@ -49,7 +49,7 @@ module program_setup !! boundary halo. Used for regional nests. logical, public :: fract_vegsoil_type = .false. !< When true, output the percentage of each soil - !! and vegetation type category, and the dominate + !! and vegetation type category, and the dominant !! category within a model grid box. public :: read_setup_namelist diff --git a/ush/sfc_climo_gen.sh b/ush/sfc_climo_gen.sh index 4e9242aa0..020ec0d13 100755 --- a/ush/sfc_climo_gen.sh +++ b/ush/sfc_climo_gen.sh @@ -25,10 +25,10 @@ # WORK_DIR Temporary working directory # SOIL_TYPE_FILE Path/name of input soil type data. # VEG_TYPE_FILE Path/name of input vegetation type data. -# vegsoilt_frac When true, outputs dominate soil and +# vegsoilt_frac When true, outputs dominant soil and # vegetation type category and the # fractional value of each category. -# When false, outputs dominate category. +# When false, outputs dominant category. #------------------------------------------------------------------------- set -eux From 05d02936e413c56eade28ec095090ae2dce5292f Mon Sep 17 00:00:00 2001 From: George Gayno Date: Thu, 16 Feb 2023 14:31:23 +0000 Subject: [PATCH 50/50] Revert cmake/mpexec.hera file. Fixes #709. --- cmake/mpiexec.hera | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/mpiexec.hera b/cmake/mpiexec.hera index 23bec1047..e82f1e9da 100755 --- a/cmake/mpiexec.hera +++ b/cmake/mpiexec.hera @@ -6,7 +6,7 @@ # $2+ - Executable and its arguments # -ACCOUNT=fv3-cpu +ACCOUNT=gsd-fv3 QOS=debug NP=$1