diff --git a/.gitmodules b/.gitmodules index 9a8d99ac..e11a5553 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,7 +20,7 @@ [submodule "ncar-physics"] path = src/physics/ncar_ccpp url = https://github.com/ESCOMP/atmospheric_physics - fxtag = 0af2e2b80bc2f8597b685bf08b0917233ce84afa + fxtag = bb7c61028c1d6ead2c09b2c58cfbbfb3c3638a51 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics [submodule "rrtmgp-data"] diff --git a/src/physics/ncar_ccpp b/src/physics/ncar_ccpp index 0af2e2b8..bb7c6102 160000 --- a/src/physics/ncar_ccpp +++ b/src/physics/ncar_ccpp @@ -1 +1 @@ -Subproject commit 0af2e2b80bc2f8597b685bf08b0917233ce84afa +Subproject commit bb7c61028c1d6ead2c09b2c58cfbbfb3c3638a51 diff --git a/src/physics/utils/pio_reader.F90 b/src/physics/utils/pio_reader.F90 index b2b502ca..b0fcf4ce 100644 --- a/src/physics/utils/pio_reader.F90 +++ b/src/physics/utils/pio_reader.F90 @@ -30,11 +30,26 @@ module pio_reader private type(file_handle_t) :: sima_pio_fh !PIO File handle type contains - procedure :: open_file => open_netcdf_file - procedure :: close_file => close_netcdf_file - procedure :: get_var_int => get_netcdf_var_int - procedure :: get_var_real => get_netcdf_var_real - procedure :: get_var_char => get_netcdf_var_char + procedure :: open_file => open_netcdf_file + procedure :: close_file => close_netcdf_file + procedure :: get_var_int_0d => get_netcdf_var_int_0d + procedure :: get_var_int_1d => get_netcdf_var_int_1d + procedure :: get_var_int_2d => get_netcdf_var_int_2d + procedure :: get_var_int_3d => get_netcdf_var_int_3d + procedure :: get_var_int_4d => get_netcdf_var_int_4d + procedure :: get_var_int_5d => get_netcdf_var_int_5d + procedure :: get_var_real_0d => get_netcdf_var_real_0d + procedure :: get_var_real_1d => get_netcdf_var_real_1d + procedure :: get_var_real_2d => get_netcdf_var_real_2d + procedure :: get_var_real_3d => get_netcdf_var_real_3d + procedure :: get_var_real_4d => get_netcdf_var_real_4d + procedure :: get_var_real_5d => get_netcdf_var_real_5d + procedure :: get_var_char_0d => get_netcdf_var_char_0d + procedure :: get_var_char_1d => get_netcdf_var_char_1d + procedure :: get_var_char_2d => get_netcdf_var_char_2d + procedure :: get_var_char_3d => get_netcdf_var_char_3d + procedure :: get_var_char_4d => get_netcdf_var_char_4d + procedure :: get_var_char_5d => get_netcdf_var_char_5d end type pio_reader_t contains @@ -102,7 +117,2162 @@ subroutine close_netcdf_file(this, errmsg, errcode) errmsg = '' end subroutine close_netcdf_file - subroutine get_netcdf_var_int(this, varname, var, errmsg, errcode) + ! ------------------------------------------------------------------ + ! Integer interfaces + ! ------------------------------------------------------------------ + + subroutine get_netcdf_var_int_0d(this, varname, var, errmsg, errcode) + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + integer, pointer, intent(out) :: var !Integer variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + !Local variables: + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + + integer :: i !loop control variable + !---------------------- + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + errcode = 0 + if(ndims /= 0) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data: + var = huge(1) + errcode = pio_get_var(pio_file_handle, var_id, var) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_int_0d + + subroutine get_netcdf_var_int_1d(this, varname, var, errmsg, errcode) + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + integer, pointer, intent(out) :: var(:) !Integer variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + !Local variables: + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + + integer :: i !loop control variable + !---------------------- + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + errcode = 0 + if(ndims /= 1) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension size + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + end do + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data: + allocate(var(dim_sizes(1)), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:) = huge(1) + errcode = pio_get_var(pio_file_handle, var_id, var(:)) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_int_1d + + subroutine get_netcdf_var_int_2d(this, varname, var, errmsg, errcode) + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + integer, pointer, intent(out) :: var(:,:) !Integer variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + !Local variables: + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + + integer :: i !loop control variable + !---------------------- + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + errcode = 0 + if(ndims /= 2) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension sizes + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + end do + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data: + allocate(var(dim_sizes(1), dim_sizes(2)), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:,:) = huge(1) + errcode = pio_get_var(pio_file_handle, var_id, var(:,:)) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_int_2d + + subroutine get_netcdf_var_int_3d(this, varname, var, errmsg, errcode) + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + integer, pointer, intent(out) :: var(:,:,:) !Integer variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + !Local variables: + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + + integer :: i !loop control variable + !---------------------- + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + errcode = 0 + if(ndims /= 3) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + end do + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data: + allocate(var(dim_sizes(1), dim_sizes(2), dim_sizes(3)), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:,:,:) = huge(1) + errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:)) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_int_3d + + subroutine get_netcdf_var_int_4d(this, varname, var, errmsg, errcode) + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + integer, pointer, intent(out) :: var(:,:,:,:) !Integer variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + !Local variables: + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + + integer :: i !loop control variable + !---------------------- + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + errcode = 0 + if(ndims /= 4) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + end do + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data: + allocate(var(dim_sizes(1), dim_sizes(2), dim_sizes(3), dim_sizes(4)), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:,:,:,:) = huge(1) + errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:,:)) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_int_4d + + subroutine get_netcdf_var_int_5d(this, varname, var, errmsg, errcode) + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + integer, pointer, intent(out) :: var(:,:,:,:,:) !Integer variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + !Local variables: + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + + integer :: i !loop control variable + !---------------------- + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + errcode = 0 + if(ndims /= 5) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + end do + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data: + allocate(var(dim_sizes(1), dim_sizes(2), dim_sizes(3), dim_sizes(4), dim_sizes(5)), & + stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:,:,:,:,:) = huge(1) + errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:,:,:)) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_int_5d + + ! ------------------------------------------------------------------ + ! Real interfaces + ! ------------------------------------------------------------------ + + subroutine get_netcdf_var_real_0d(this, varname, var, errmsg, errcode) + use ccpp_kinds, only: kind_phys + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + real(kind_phys), pointer, intent(out) :: var !Real variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + + integer :: i !loop control variable + !---------------------- + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + errcode = 0 + if(ndims /= 0) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data: + var = huge(1._kind_phys) + errcode = pio_get_var(pio_file_handle, var_id, var) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_real_0d + + subroutine get_netcdf_var_real_1d(this, varname, var, errmsg, errcode) + use ccpp_kinds, only: kind_phys + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + real(kind_phys), pointer, intent(out) :: var(:) !Real variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + + integer :: i !loop control variable + !---------------------- + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + errcode = 0 + if(ndims /= 1) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + end do + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data: + allocate(var(dim_sizes(1)), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:) = huge(1._kind_phys) + errcode = pio_get_var(pio_file_handle, var_id, var(:)) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_real_1d + + subroutine get_netcdf_var_real_2d(this, varname, var, errmsg, errcode) + use ccpp_kinds, only: kind_phys + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + real(kind_phys), pointer, intent(out) :: var(:,:) !Real variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + + integer :: i !loop control variable + !---------------------- + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + errcode = 0 + if(ndims /= 2) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + end do + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data: + allocate(var(dim_sizes(1), dim_sizes(2)), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:,:) = huge(1._kind_phys) + errcode = pio_get_var(pio_file_handle, var_id, var(:,:)) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_real_2d + + subroutine get_netcdf_var_real_3d(this, varname, var, errmsg, errcode) + use ccpp_kinds, only: kind_phys + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + real(kind_phys), pointer, intent(out) :: var(:,:,:) !Real variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + + integer :: i !loop control variable + !---------------------- + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + errcode = 0 + if(ndims /= 3) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + end do + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data: + allocate(var(dim_sizes(1), dim_sizes(2), dim_sizes(3)), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:,:,:) = huge(1._kind_phys) + errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:)) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_real_3d + + subroutine get_netcdf_var_real_4d(this, varname, var, errmsg, errcode) + use ccpp_kinds, only: kind_phys + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + real(kind_phys), pointer, intent(out) :: var(:,:,:,:) !Real variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + + integer :: i !loop control variable + !---------------------- + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + errcode = 0 + if(ndims /= 4) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + end do + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data: + allocate(var(dim_sizes(1), dim_sizes(2), dim_sizes(3), dim_sizes(4)), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:,:,:,:) = huge(1._kind_phys) + errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:,:)) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_real_4d + + subroutine get_netcdf_var_real_5d(this, varname, var, errmsg, errcode) + use ccpp_kinds, only: kind_phys + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + real(kind_phys), pointer, intent(out) :: var(:,:,:,:,:) !Real variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + + integer :: i !loop control variable + !---------------------- + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + errcode = 0 + if(ndims /= 5) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + end do + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data: + allocate(var(dim_sizes(1), dim_sizes(2), dim_sizes(3), dim_sizes(4), dim_sizes(5)), & + stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:,:,:,:,:) = huge(1._kind_phys) + errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:,:,:)) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_real_5d + + ! ------------------------------------------------------------------ + ! Character interfaces + ! ------------------------------------------------------------------ + + subroutine get_netcdf_var_char_0d(this, varname, var, errmsg, errcode) + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + use pio_types, only: PIO_CHAR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + character(len=:), pointer, intent(out) :: var !Character variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + !Local variables: + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: nc_type !NetCDF variable type + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + integer :: i !loop control variable + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable type and number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, xtype=nc_type, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that variable is a character array + !(as we cannot currently handle string-type variables): + if(nc_type /= PIO_CHAR) then + errcode = not_char_type_err + errmsg = "NetCDF Variable '"//varname//"' is not a character array. File can be found here: "//file_path + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + + !NOTE: NetCDF supports both character arrays and string-type + !data depending on the NetCDF version, so the dimensions + !might be one larger than the actual array size if it + !includes the character length as a dimension as well. + !Ideally the actual type would be checked and handled + !differently, but for now just assume a character array + !and check for ndims = rank+1 + errcode = 0 + if(ndims /= 1) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + end do + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data. Note that the first dimenstion + !is the length of the character array, so need to start + !the dim_sizes allocation count at index two: + allocate(character(dim_sizes(1)) :: var, stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var = 'UNSET' + errcode = pio_get_var(pio_file_handle, var_id, var) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_char_0d + + subroutine get_netcdf_var_char_1d(this, varname, var, errmsg, errcode) + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + use pio_types, only: PIO_CHAR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + character(len=:), pointer, intent(out) :: var(:) !Character variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + !Local variables: + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: nc_type !NetCDF variable type + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + integer :: i !loop control variable + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable type and number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, xtype=nc_type, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that variable is a character array + !(as we cannot currently handle string-type variables): + if(nc_type /= PIO_CHAR) then + errcode = not_char_type_err + errmsg = "NetCDF Variable '"//varname//"' is not a character array. File can be found here: "//file_path + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + + !NOTE: NetCDF supports both character arrays and string-type + !data depending on the NetCDF version, so the dimensions + !might be one larger than the actual array size if it + !includes the character length as a dimension as well. + !Ideally the actual type would be checked and handled + !differently, but for now just assume a character array + !and check for ndims = rank+1 + errcode = 0 + if(ndims /= 2) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + end do + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data. Note that the first dimenstion + !is the length of the character array, so need to start + !the dim_sizes allocation count at index two: + allocate(character(dim_sizes(1)) :: var(dim_sizes(2)), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:) = 'UNSET' + errcode = pio_get_var(pio_file_handle, var_id, var(:)) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_char_1d + + subroutine get_netcdf_var_char_2d(this, varname, var, errmsg, errcode) + use pio, only: pio_inq_varid + use pio, only: pio_inq_dimlen + use pio, only: pio_inquire_variable + use pio, only: pio_seterrorhandling + use pio, only: pio_get_var + use pio, only: PIO_NOERR + use pio, only: PIO_BCAST_ERROR + use pio_types, only: PIO_CHAR + + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + character(len=:), pointer, intent(out) :: var(:,:) !Character variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + + !Local variables: + type(file_desc_t) :: pio_file_handle !File handle type used by PIO + character(len=cl) :: file_path !Path to NetCDF file + integer :: err_handling !PIO error handling code + integer :: var_id !NetCDF variable ID + integer :: nc_type !NetCDF variable type + integer :: ndims !Number of variable dimensions on NetCDF file + integer, allocatable :: dim_ids(:) !Variable dimension IDs + integer, allocatable :: dim_sizes(:) !Variable dimension sizes + integer :: i !loop control variable + + !Check if file is open: + if(.not.this%sima_pio_fh%is_file_open) then + !File isn't actually open, so throw an error + errcode = file_not_open_err + errmsg = "File '"//this%sima_pio_fh%file_path//"' is not open, need to call 'open_file' first." + return + end if + + !Extract open file information: + pio_file_handle = this%sima_pio_fh%pio_fh + file_path = this%sima_pio_fh%file_path + + !Force PIO to send an error code instead of dying: + call pio_seterrorhandling(pio_file_handle, PIO_BCAST_ERROR, oldmethod=err_handling) + + !Look for variable on file: + errcode = pio_inq_varid(pio_file_handle, varname, var_id) + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable type and number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, xtype=nc_type, ndims=ndims) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that variable is a character array + !(as we cannot currently handle string-type variables): + if(nc_type /= PIO_CHAR) then + errcode = not_char_type_err + errmsg = "NetCDF Variable '"//varname//"' is not a character array. File can be found here: "//file_path + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Check that the variable rank as specified by the caller + !matches what is found on the NetCDF file: + + !NOTE: NetCDF supports both character arrays and string-type + !data depending on the NetCDF version, so the dimensions + !might be one larger than the actual array size if it + !includes the character length as a dimension as well. + !Ideally the actual type would be checked and handled + !differently, but for now just assume a character array + !and check for ndims = rank+1 + errcode = 0 + if(ndims /= 3) then + errcode = bad_var_rank_err + errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + end do + + !Now attempt to allocate and initialize variable, and + !read-in the NetCDF data. Note that the first dimenstion + !is the length of the character array, so need to start + !the dim_sizes allocation count at index two: + allocate(character(dim_sizes(1)) :: var(dim_sizes(2), dim_sizes(3)), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:,:) = 'UNSET' + errcode = pio_get_var(pio_file_handle, var_id, var(:,:)) + + if (errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_get_var_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + + !Variable was successfully read, so properly set the error + !code and message: + errcode = 0 + errmsg = '' + end subroutine get_netcdf_var_char_2d + + subroutine get_netcdf_var_char_3d(this, varname, var, errmsg, errcode) use pio, only: pio_inq_varid use pio, only: pio_inq_dimlen use pio, only: pio_inquire_variable @@ -110,24 +2280,24 @@ subroutine get_netcdf_var_int(this, varname, var, errmsg, errcode) use pio, only: pio_get_var use pio, only: PIO_NOERR use pio, only: PIO_BCAST_ERROR + use pio_types, only: PIO_CHAR - class(pio_reader_t), intent(in) :: this - character(len=*), intent(in) :: varname - integer, pointer, intent(out) :: var(..) !Character variable that file data will be read to. - integer, intent(out) :: errcode !Error code - character(len=*), intent(out) :: errmsg !Error message + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + character(len=:), pointer, intent(out) :: var(:,:,:) !Character variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message !Local variables: type(file_desc_t) :: pio_file_handle !File handle type used by PIO character(len=cl) :: file_path !Path to NetCDF file integer :: err_handling !PIO error handling code integer :: var_id !NetCDF variable ID + integer :: nc_type !NetCDF variable type integer :: ndims !Number of variable dimensions on NetCDF file integer, allocatable :: dim_ids(:) !Variable dimension IDs integer, allocatable :: dim_sizes(:) !Variable dimension sizes - - integer :: i !loop control variable - !---------------------- + integer :: i !loop control variable !Check if file is open: if(.not.this%sima_pio_fh%is_file_open) then @@ -146,7 +2316,7 @@ subroutine get_netcdf_var_int(this, varname, var, errmsg, errcode) !Look for variable on file: errcode = pio_inq_varid(pio_file_handle, varname, var_id) - if(errcode /= PIO_NOERR) then + if (errcode /= PIO_NOERR) then !Extract error message from PIO: call get_pio_errmsg(pio_inq_var_id_err, errcode, errmsg) @@ -155,8 +2325,8 @@ subroutine get_netcdf_var_int(this, varname, var, errmsg, errcode) return end if - !Get number of variable dimensions on file: - errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + !Get variable type and number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, xtype=nc_type, ndims=ndims) if(errcode /= PIO_NOERR) then !Extract error message from PIO: call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) @@ -166,145 +2336,88 @@ subroutine get_netcdf_var_int(this, varname, var, errmsg, errcode) return end if + !Check that variable is a character array + !(as we cannot currently handle string-type variables): + if(nc_type /= PIO_CHAR) then + errcode = not_char_type_err + errmsg = "NetCDF Variable '"//varname//"' is not a character array. File can be found here: "//file_path + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + !Check that the variable rank as specified by the caller !matches what is found on the NetCDF file: + + !NOTE: NetCDF supports both character arrays and string-type + !data depending on the NetCDF version, so the dimensions + !might be one larger than the actual array size if it + !includes the character length as a dimension as well. + !Ideally the actual type would be checked and handled + !differently, but for now just assume a character array + !and check for ndims = rank+1 errcode = 0 - select rank(var) - rank(0) - if(ndims /= 0) errcode = bad_var_rank_err - rank(1) - if(ndims /= 1) errcode = bad_var_rank_err - rank(2) - if(ndims /= 2) errcode = bad_var_rank_err - rank(3) - if(ndims /= 3) errcode = bad_var_rank_err - rank(4) - if(ndims /= 4) errcode = bad_var_rank_err - rank(5) - if(ndims /= 5) errcode = bad_var_rank_err - rank default - !PIO can only handle up to 5 dimensions, - !so error out if array rank is greater than that. - errcode = too_high_rank_err - errmsg = "Unsupported rank for variable '"//varname//"'" - return - end select - if(errcode == bad_var_rank_err) then + if(ndims /= 4) then + errcode = bad_var_rank_err errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" !Reset PIO back to original error handling method: call pio_seterrorhandling(pio_file_handle, err_handling) return end if - !Get variable dimension sizes, if applicable: - if(ndims > 0) then - !Allocate NetCDF variable dimension ID array: - allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if - !Get variable dimension IDs: - errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) if(errcode /= PIO_NOERR) then !Extract error message from PIO: - call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) - - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) - !Allocate NetCDF variable dimension sizes array: - allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then !Reset PIO back to original error handling method: call pio_seterrorhandling(pio_file_handle, err_handling) return end if - - !Get dimension sizes: - do i = 1, ndims - errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) - if(errcode /= PIO_NOERR) then - !Extract error message from PIO: - call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) - - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - end do - end if + end do !Now attempt to allocate and initialize variable, and - !read-in the NetCDF data: - select rank(var) - rank(0) - - var = huge(1) - errcode = pio_get_var(pio_file_handle, var_id, var) - - rank(1) - - allocate(var(dim_sizes(1)), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:) = huge(1) - errcode = pio_get_var(pio_file_handle, var_id, var(:)) - - rank(2) - - allocate(var(dim_sizes(1), dim_sizes(2)), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:,:) = huge(1) - errcode = pio_get_var(pio_file_handle, var_id, var(:,:)) - - rank(3) - - allocate(var(dim_sizes(1), dim_sizes(2), dim_sizes(3)), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:,:,:) = huge(1) - errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:)) - - rank(4) - - allocate(var(dim_sizes(1), dim_sizes(2), dim_sizes(3), dim_sizes(4)), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:,:,:,:) = huge(1) - errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:,:)) - - rank(5) - - allocate(var(dim_sizes(1), dim_sizes(2), dim_sizes(3), dim_sizes(4), dim_sizes(5)), & - stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:,:,:,:,:) = huge(1) - errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:,:,:)) - - !No default needed as it was already checked above. - end select + !read-in the NetCDF data. Note that the first dimenstion + !is the length of the character array, so need to start + !the dim_sizes allocation count at index two: + allocate(character(dim_sizes(1)) :: var(dim_sizes(2), dim_sizes(3), dim_sizes(4)), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:,:,:) = 'UNSET' + errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:)) if (errcode /= PIO_NOERR) then !Extract error message from PIO: @@ -322,10 +2435,9 @@ subroutine get_netcdf_var_int(this, varname, var, errmsg, errcode) !code and message: errcode = 0 errmsg = '' - end subroutine get_netcdf_var_int + end subroutine get_netcdf_var_char_3d - subroutine get_netcdf_var_real(this, varname, var, errmsg, errcode) - use ccpp_kinds, only: kind_phys + subroutine get_netcdf_var_char_4d(this, varname, var, errmsg, errcode) use pio, only: pio_inq_varid use pio, only: pio_inq_dimlen use pio, only: pio_inquire_variable @@ -333,23 +2445,24 @@ subroutine get_netcdf_var_real(this, varname, var, errmsg, errcode) use pio, only: pio_get_var use pio, only: PIO_NOERR use pio, only: PIO_BCAST_ERROR + use pio_types, only: PIO_CHAR - class(pio_reader_t), intent(in) :: this - character(len=*), intent(in) :: varname - real(kind_phys), pointer, intent(out) :: var(..) !Character variable that file data will be read to. - integer, intent(out) :: errcode !Error code - character(len=*), intent(out) :: errmsg !Error message + class(pio_reader_t), intent(in) :: this + character(len=*), intent(in) :: varname + character(len=:), pointer, intent(out) :: var(:,:,:,:) !Character variable that file data will be read to. + integer, intent(out) :: errcode !Error code + character(len=*), intent(out) :: errmsg !Error message + !Local variables: type(file_desc_t) :: pio_file_handle !File handle type used by PIO character(len=cl) :: file_path !Path to NetCDF file integer :: err_handling !PIO error handling code integer :: var_id !NetCDF variable ID + integer :: nc_type !NetCDF variable type integer :: ndims !Number of variable dimensions on NetCDF file integer, allocatable :: dim_ids(:) !Variable dimension IDs integer, allocatable :: dim_sizes(:) !Variable dimension sizes - - integer :: i !loop control variable - !---------------------- + integer :: i !loop control variable !Check if file is open: if(.not.this%sima_pio_fh%is_file_open) then @@ -377,8 +2490,8 @@ subroutine get_netcdf_var_real(this, varname, var, errmsg, errcode) return end if - !Get number of variable dimensions on file: - errcode = pio_inquire_variable(pio_file_handle, var_id, ndims=ndims) + !Get variable type and number of variable dimensions on file: + errcode = pio_inquire_variable(pio_file_handle, var_id, xtype=nc_type, ndims=ndims) if(errcode /= PIO_NOERR) then !Extract error message from PIO: call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) @@ -388,146 +2501,89 @@ subroutine get_netcdf_var_real(this, varname, var, errmsg, errcode) return end if + !Check that variable is a character array + !(as we cannot currently handle string-type variables): + if(nc_type /= PIO_CHAR) then + errcode = not_char_type_err + errmsg = "NetCDF Variable '"//varname//"' is not a character array. File can be found here: "//file_path + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + !Check that the variable rank as specified by the caller !matches what is found on the NetCDF file: + + !NOTE: NetCDF supports both character arrays and string-type + !data depending on the NetCDF version, so the dimensions + !might be one larger than the actual array size if it + !includes the character length as a dimension as well. + !Ideally the actual type would be checked and handled + !differently, but for now just assume a character array + !and check for ndims = rank+1 errcode = 0 - select rank(var) - rank(0) - if(ndims /= 0) errcode = bad_var_rank_err - rank(1) - if(ndims /= 1) errcode = bad_var_rank_err - rank(2) - if(ndims /= 2) errcode = bad_var_rank_err - rank(3) - if(ndims /= 3) errcode = bad_var_rank_err - rank(4) - if(ndims /= 4) errcode = bad_var_rank_err - rank(5) - if(ndims /= 5) errcode = bad_var_rank_err - rank default - !PIO can only handle up to 5 dimensions, - !so error out if array rank is greater than that. - errcode = too_high_rank_err - errmsg = "Unsupported rank for variable '"//varname//"'" - return - end select - if(errcode == bad_var_rank_err) then + if(ndims /= 5) then + errcode = bad_var_rank_err errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" !Reset PIO back to original error handling method: call pio_seterrorhandling(pio_file_handle, err_handling) return end if - !Get variable dimension sizes, if applicable: - if(ndims > 0) then - !Allocate NetCDF variable dimension ID array: - allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if - !Get variable dimension IDs: - errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) if(errcode /= PIO_NOERR) then !Extract error message from PIO: - call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) - - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) - !Allocate NetCDF variable dimension sizes array: - allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then !Reset PIO back to original error handling method: call pio_seterrorhandling(pio_file_handle, err_handling) return end if - - !Get dimension sizes: - do i = 1, ndims - errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) - if(errcode /= PIO_NOERR) then - !Extract error message from PIO: - call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) - - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - end do - - end if + end do !Now attempt to allocate and initialize variable, and - !read-in the NetCDF data: - select rank(var) - rank(0) - - var = huge(1._kind_phys) - errcode = pio_get_var(pio_file_handle, var_id, var) - - rank(1) - - allocate(var(dim_sizes(1)), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:) = huge(1._kind_phys) - errcode = pio_get_var(pio_file_handle, var_id, var(:)) - - rank(2) - - allocate(var(dim_sizes(1), dim_sizes(2)), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:,:) = huge(1._kind_phys) - errcode = pio_get_var(pio_file_handle, var_id, var(:,:)) - - rank(3) - - allocate(var(dim_sizes(1), dim_sizes(2), dim_sizes(3)), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:,:,:) = huge(1._kind_phys) - errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:)) - - rank(4) - - allocate(var(dim_sizes(1), dim_sizes(2), dim_sizes(3), dim_sizes(4)), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:,:,:,:) = huge(1._kind_phys) - errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:,:)) - - rank(5) - - allocate(var(dim_sizes(1), dim_sizes(2), dim_sizes(3), dim_sizes(4), dim_sizes(5)), & - stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:,:,:,:,:) = huge(1._kind_phys) - errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:,:,:)) - - !No default needed as it was already checked above. - end select + !read-in the NetCDF data. Note that the first dimenstion + !is the length of the character array, so need to start + !the dim_sizes allocation count at index two: + allocate(character(dim_sizes(1)) :: var(dim_sizes(2), dim_sizes(3), dim_sizes(4), dim_sizes(5)), & + stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:,:,:,:) = 'UNSET' + errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:,:)) if (errcode /= PIO_NOERR) then !Extract error message from PIO: @@ -545,9 +2601,9 @@ subroutine get_netcdf_var_real(this, varname, var, errmsg, errcode) !code and message: errcode = 0 errmsg = '' - end subroutine get_netcdf_var_real + end subroutine get_netcdf_var_char_4d - subroutine get_netcdf_var_char(this, varname, var, errmsg, errcode) + subroutine get_netcdf_var_char_5d(this, varname, var, errmsg, errcode) use pio, only: pio_inq_varid use pio, only: pio_inq_dimlen use pio, only: pio_inquire_variable @@ -559,7 +2615,7 @@ subroutine get_netcdf_var_char(this, varname, var, errmsg, errcode) class(pio_reader_t), intent(in) :: this character(len=*), intent(in) :: varname - character(len=:), pointer, intent(out) :: var(..) !Character variable that file data will be read to. + character(len=:), pointer, intent(out) :: var(:,:,:,:,:) !Character variable that file data will be read to. integer, intent(out) :: errcode !Error code character(len=*), intent(out) :: errmsg !Error message @@ -632,152 +2688,68 @@ subroutine get_netcdf_var_char(this, varname, var, errmsg, errcode) !differently, but for now just assume a character array !and check for ndims = rank+1 errcode = 0 - select rank(var) - rank(0) - if(ndims /= 1) errcode = bad_var_rank_err - rank(1) - if(ndims /= 2) errcode = bad_var_rank_err - rank(2) - if(ndims /= 3) errcode = bad_var_rank_err - rank(3) - if(ndims /= 4) errcode = bad_var_rank_err - rank(4) - if(ndims /= 5) errcode = bad_var_rank_err - rank(5) - if(ndims /= 6) errcode = bad_var_rank_err - rank default - !PIO can only handle up to 5 dimensions, - !so error out if array rank is greater than that. - errcode = too_high_rank_err - errmsg = "Unsupported rank for variable '"//varname//"'" - return - end select - if(errcode == bad_var_rank_err) then + if(ndims /= 6) then + errcode = bad_var_rank_err errmsg = "Variable '"//varname//"' isn't declared with the correct number of dimensions" !Reset PIO back to original error handling method: call pio_seterrorhandling(pio_file_handle, err_handling) return end if - !Get variable dimension sizes, if applicable: - if(ndims > 0) then - !Allocate NetCDF variable dimension ID array: - allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if + !Get variable dimension sizes: + !Allocate NetCDF variable dimension ID array: + allocate(dim_ids(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Get variable dimension IDs: + errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + if(errcode /= PIO_NOERR) then + !Extract error message from PIO: + call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) + + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + + !Allocate NetCDF variable dimension sizes array: + allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if - !Get variable dimension IDs: - errcode = pio_inquire_variable(pio_file_handle, var_id, dimids=dim_ids) + !Get dimension sizes: + do i = 1, ndims + errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) if(errcode /= PIO_NOERR) then !Extract error message from PIO: - call get_pio_errmsg(pio_inq_var_info_err, errcode, errmsg) - - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if + call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) - !Allocate NetCDF variable dimension sizes array: - allocate(dim_sizes(ndims), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then !Reset PIO back to original error handling method: call pio_seterrorhandling(pio_file_handle, err_handling) return end if - - !Get dimension sizes: - do i = 1, ndims - errcode = pio_inq_dimlen(pio_file_handle, dim_ids(i), dim_sizes(i)) - if(errcode /= PIO_NOERR) then - !Extract error message from PIO: - call get_pio_errmsg(pio_inq_dim_len_err, errcode, errmsg) - - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - end do - - end if + end do !Now attempt to allocate and initialize variable, and !read-in the NetCDF data. Note that the first dimenstion !is the length of the character array, so need to start !the dim_sizes allocation count at index two: - select rank(var) - rank(0) - - allocate(character(dim_sizes(1)) :: var, stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var = 'UNSET' - errcode = pio_get_var(pio_file_handle, var_id, var) - - rank(1) - - allocate(character(dim_sizes(1)) :: var(dim_sizes(2)), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:) = 'UNSET' - errcode = pio_get_var(pio_file_handle, var_id, var(:)) - - rank(2) - - allocate(character(dim_sizes(1)) :: var(dim_sizes(2), dim_sizes(3)), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:,:) = 'UNSET' - errcode = pio_get_var(pio_file_handle, var_id, var(:,:)) - - rank(3) - - allocate(character(dim_sizes(1)) :: var(dim_sizes(2), dim_sizes(3), dim_sizes(4)), stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:,:,:) = 'UNSET' - errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:)) - - rank(4) - - allocate(character(dim_sizes(1)) :: var(dim_sizes(2), dim_sizes(3), dim_sizes(4), dim_sizes(5)), & - stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:,:,:,:) = 'UNSET' - errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:,:)) - - rank(5) - - allocate(character(dim_sizes(1)) :: var(dim_sizes(2), dim_sizes(3), dim_sizes(4), dim_sizes(5), dim_sizes(6)), & - stat=errcode, errmsg=errmsg) - if(errcode /= 0) then - !Reset PIO back to original error handling method: - call pio_seterrorhandling(pio_file_handle, err_handling) - return - end if - var(:,:,:,:,:) = 'UNSET' - errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:,:,:)) - - !No default needed as it was already checked above. - end select + allocate(character(dim_sizes(1)) :: var(dim_sizes(2), dim_sizes(3), dim_sizes(4), dim_sizes(5), dim_sizes(6)), & + stat=errcode, errmsg=errmsg) + if(errcode /= 0) then + !Reset PIO back to original error handling method: + call pio_seterrorhandling(pio_file_handle, err_handling) + return + end if + var(:,:,:,:,:) = 'UNSET' + errcode = pio_get_var(pio_file_handle, var_id, var(:,:,:,:,:)) if (errcode /= PIO_NOERR) then !Extract error message from PIO: @@ -795,7 +2767,7 @@ subroutine get_netcdf_var_char(this, varname, var, errmsg, errcode) !code and message: errcode = 0 errmsg = '' - end subroutine get_netcdf_var_char + end subroutine get_netcdf_var_char_5d subroutine get_pio_errmsg(caller_errcode, errcode, errmsg) !Set error message based off PIO error code,