From ca25594d33431778ba37878387d9903e73e1bf65 Mon Sep 17 00:00:00 2001 From: Robert Hallberg Date: Tue, 26 Jan 2021 18:59:01 -0500 Subject: [PATCH 1/4] Removed unused module use statements for I/O Removed module use statements for unused subroutines from MOM_io of for the entire netcdf module. All answers are bitwise identical. --- config_src/coupled_driver/ocean_model_MOM.F90 | 2 +- config_src/solo_driver/user_surface_forcing.F90 | 1 - src/core/MOM_open_boundary.F90 | 5 ++--- src/framework/MOM_diag_remap.F90 | 2 -- src/initialization/MOM_coord_initialization.F90 | 2 -- src/initialization/MOM_fixed_initialization.F90 | 3 --- 6 files changed, 3 insertions(+), 12 deletions(-) diff --git a/config_src/coupled_driver/ocean_model_MOM.F90 b/config_src/coupled_driver/ocean_model_MOM.F90 index edb06dc9ba..f635e886a5 100644 --- a/config_src/coupled_driver/ocean_model_MOM.F90 +++ b/config_src/coupled_driver/ocean_model_MOM.F90 @@ -35,7 +35,7 @@ module ocean_model_mod use MOM_forcing_type, only : forcing_diagnostics, mech_forcing_diags use MOM_get_input, only : Get_MOM_Input, directories use MOM_grid, only : ocean_grid_type -use MOM_io, only : close_file, file_exists, read_data, write_version_number, stdout +use MOM_io, only : write_version_number, stdout use MOM_marine_ice, only : iceberg_forces, iceberg_fluxes, marine_ice_init, marine_ice_CS use MOM_restart, only : MOM_restart_CS, save_restart use MOM_string_functions, only : uppercase diff --git a/config_src/solo_driver/user_surface_forcing.F90 b/config_src/solo_driver/user_surface_forcing.F90 index d8f008e9ef..940bcd04b4 100644 --- a/config_src/solo_driver/user_surface_forcing.F90 +++ b/config_src/solo_driver/user_surface_forcing.F90 @@ -11,7 +11,6 @@ module user_surface_forcing use MOM_forcing_type, only : forcing, mech_forcing use MOM_forcing_type, only : allocate_forcing_type, allocate_mech_forcing use MOM_grid, only : ocean_grid_type -use MOM_io, only : file_exists, read_data use MOM_time_manager, only : time_type, operator(+), operator(/) use MOM_tracer_flow_control, only : call_tracer_set_forcing use MOM_tracer_flow_control, only : tracer_flow_control_CS diff --git a/src/core/MOM_open_boundary.F90 b/src/core/MOM_open_boundary.F90 index 9672356bf6..0cb81e9978 100644 --- a/src/core/MOM_open_boundary.F90 +++ b/src/core/MOM_open_boundary.F90 @@ -9,13 +9,12 @@ module MOM_open_boundary use MOM_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end, CLOCK_ROUTINE use MOM_diag_mediator, only : diag_ctrl, time_type use MOM_domains, only : pass_var, pass_vector -use MOM_domains, only : To_All, SCALAR_PAIR, CGRID_NE, CORNER +use MOM_domains, only : To_All, EAST_FACE, NORTH_FACE, SCALAR_PAIR, CGRID_NE, CORNER use MOM_error_handler, only : MOM_mesg, MOM_error, FATAL, WARNING, NOTE, is_root_pe use MOM_file_parser, only : get_param, log_version, param_file_type, log_param use MOM_grid, only : ocean_grid_type, hor_index_type use MOM_dyn_horgrid, only : dyn_horgrid_type -use MOM_io, only : EAST_FACE, NORTH_FACE -use MOM_io, only : slasher, read_data, field_size, SINGLE_FILE +use MOM_io, only : slasher, field_size, SINGLE_FILE use MOM_io, only : vardesc, query_vardesc, var_desc use MOM_restart, only : register_restart_field, register_restart_pair use MOM_restart, only : query_initialized, MOM_restart_CS diff --git a/src/framework/MOM_diag_remap.F90 b/src/framework/MOM_diag_remap.F90 index 462ba7bf5e..4bea1fc5ae 100644 --- a/src/framework/MOM_diag_remap.F90 +++ b/src/framework/MOM_diag_remap.F90 @@ -64,8 +64,6 @@ module MOM_diag_remap use MOM_diag_manager, only : diag_axis_init use MOM_diag_vkernels, only : interpolate_column, reintegrate_column use MOM_file_parser, only : get_param, log_param, param_file_type -use MOM_io, only : slasher, mom_read_data -use MOM_io, only : file_exists, field_size use MOM_string_functions, only : lowercase, extractWord use MOM_grid, only : ocean_grid_type use MOM_unit_scaling, only : unit_scale_type diff --git a/src/initialization/MOM_coord_initialization.F90 b/src/initialization/MOM_coord_initialization.F90 index 23d279b65a..454060414b 100644 --- a/src/initialization/MOM_coord_initialization.F90 +++ b/src/initialization/MOM_coord_initialization.F90 @@ -17,8 +17,6 @@ module MOM_coord_initialization use user_initialization, only : user_set_coord use BFB_initialization, only : BFB_set_coord -use netcdf - implicit none ; private public MOM_initialize_coord diff --git a/src/initialization/MOM_fixed_initialization.F90 b/src/initialization/MOM_fixed_initialization.F90 index b075da4141..069d576b2c 100644 --- a/src/initialization/MOM_fixed_initialization.F90 +++ b/src/initialization/MOM_fixed_initialization.F90 @@ -17,7 +17,6 @@ module MOM_fixed_initialization use MOM_open_boundary, only : open_boundary_config, open_boundary_query use MOM_open_boundary, only : open_boundary_impose_normal_slope use MOM_open_boundary, only : open_boundary_impose_land_mask -! use MOM_shared_initialization, only : MOM_shared_init_init use MOM_shared_initialization, only : MOM_initialize_rotation, MOM_calculate_grad_Coriolis use MOM_shared_initialization, only : initialize_topography_from_file, apply_topography_edits_from_file use MOM_shared_initialization, only : initialize_topography_named, limit_topography, diagnoseMaximumDepth @@ -42,8 +41,6 @@ module MOM_fixed_initialization use Phillips_initialization, only : Phillips_initialize_topography use dense_water_initialization, only : dense_water_initialize_topography -use netcdf - implicit none ; private public MOM_initialize_fixed, MOM_initialize_rotation, MOM_initialize_topography From 9d9a74d10512c4051e4bd6716cd351a1a1e8dabb Mon Sep 17 00:00:00 2001 From: Robert Hallberg Date: Tue, 26 Jan 2021 19:04:33 -0500 Subject: [PATCH 2/4] +Document all MOM_io interfaces Added explicit interfaces to field_size, check_nml_error, open_namelist_file, write_version_number and get_filename_appendix to MOM_io.F90. Added explicit interfaces to write_metadata, get_file_times, get_axis_data and get_file_times as well as the newly named routines check_namelist_error, check_namelist_error, write_version, get_field_size to MOM_io_infra.F90. MOM_read_data was expanded to work with regions of 2D fields. MOM_grid_initialize and MOM_restart were altered to use the new interfaces, and support for non-domain-decomposed 2-d, 3-d and 4-d arrays was dropped from the MOM_restart module. All answers are bitwise identical, but there are some expanded capabilities. --- src/framework/MOM_io.F90 | 73 ++++++- src/framework/MOM_io_infra.F90 | 212 ++++++++++++++++++--- src/framework/MOM_restart.F90 | 27 ++- src/initialization/MOM_grid_initialize.F90 | 6 +- 4 files changed, 269 insertions(+), 49 deletions(-) diff --git a/src/framework/MOM_io.F90 b/src/framework/MOM_io.F90 index 9c0cb3a228..a251c52281 100644 --- a/src/framework/MOM_io.F90 +++ b/src/framework/MOM_io.F90 @@ -7,16 +7,17 @@ module MOM_io use MOM_domains, only : MOM_domain_type, domain1D, get_domain_components use MOM_domains, only : AGRID, BGRID_NE, CGRID_NE use MOM_dyn_horgrid, only : dyn_horgrid_type +use MOM_ensemble_manager, only : get_ensemble_id use MOM_error_handler, only : MOM_error, NOTE, FATAL, WARNING use MOM_file_parser, only : log_version, param_file_type use MOM_grid, only : ocean_grid_type -use MOM_io_infra, only : MOM_read_data, read_data, MOM_read_vector, read_field_chksum +use MOM_io_infra, only : MOM_read_data, read_data=>MOM_read_data, MOM_read_vector, read_field_chksum use MOM_io_infra, only : file_exists, get_file_info, get_file_fields, get_field_atts -use MOM_io_infra, only : open_file, close_file, field_size, fieldtype, field_exists -use MOM_io_infra, only : flush_file, get_filename_appendix, get_ensemble_id +use MOM_io_infra, only : open_file, close_file, get_field_size, fieldtype, field_exists +use MOM_io_infra, only : flush_file, get_filename_suffix use MOM_io_infra, only : get_file_times, axistype, get_axis_data -use MOM_io_infra, only : write_field, write_metadata, write_version_number -use MOM_io_infra, only : open_namelist_file, check_nml_error, io_infra_init, io_infra_end +use MOM_io_infra, only : write_field, write_metadata, write_version +use MOM_io_infra, only : MOM_namelist_file, check_namelist_error, io_infra_init, io_infra_end use MOM_io_infra, only : APPEND_FILE, ASCII_FILE, MULTIPLE, NETCDF_FILE, OVERWRITE_FILE use MOM_io_infra, only : READONLY_FILE, SINGLE_FILE, WRITEONLY_FILE use MOM_io_infra, only : CENTER, CORNER, NORTH_FACE, EAST_FACE @@ -33,13 +34,16 @@ module MOM_io ! These interfaces are actually implemented in this file. public :: create_file, reopen_file, num_timelevels, cmor_long_std, ensembler, MOM_io_init public :: MOM_write_field, var_desc, modify_vardesc, query_vardesc +public :: open_namelist_file, check_namelist_error, check_nml_error ! The following are simple pass throughs of routines from MOM_io_infra or other modules public :: close_file, field_exists, field_size, fieldtype, get_filename_appendix public :: file_exists, flush_file, get_file_info, get_file_fields, get_field_atts public :: get_file_times, open_file, get_axis_data -public :: MOM_read_data, MOM_read_vector, read_data, read_field_chksum +public :: MOM_read_data, MOM_read_vector, read_field_chksum public :: slasher, write_field, write_version_number -public :: open_namelist_file, check_nml_error, io_infra_init, io_infra_end +public :: io_infra_init, io_infra_end +! This API is here just to support non-FMS couplers, and should not persist. +public :: read_data ! These are encoding constants. public :: APPEND_FILE, ASCII_FILE, MULTIPLE, NETCDF_FILE, OVERWRITE_FILE public :: READONLY_FILE, SINGLE_FILE, WRITEONLY_FILE @@ -440,6 +444,12 @@ function num_timelevels(filename, varname, min_dims) result(n_time) n_time = -1 found = .false. + ! To do the same via MOM_io_infra calls, do the following: + ! found = field_exists(filename, varname) + ! call open_file(ncid, filename, action=READONLY_FILE, form=NETCDF_FILE, threading=MULTIPLE) + ! call get_file_info(ncid, ntime=n_time) + ! However, this does not handle the case where the time axis for the variable is not the record axis. + status = NF90_OPEN(filename, NF90_NOWRITE, ncid) if (status /= NF90_NOERR) then call MOM_error(WARNING,"num_timelevels: "//& @@ -788,6 +798,21 @@ subroutine MOM_write_field_0d(io_unit, field_md, field, tstamp, fill_value) call write_field(io_unit, field_md, field, tstamp=tstamp) end subroutine MOM_write_field_0d +!> Given filename and fieldname, this subroutine returns the size of the field in the file +subroutine field_size(filename, fieldname, sizes, field_found, no_domain) + character(len=*), intent(in) :: filename !< The name of the file to read + character(len=*), intent(in) :: fieldname !< The name of the variable whose sizes are returned + integer, dimension(:), intent(inout) :: sizes !< The sizes of the variable in each dimension + logical, optional, intent(out) :: field_found !< This indicates whether the field was found in + !! the input file. Without this argument, there + !! is a fatal error if the field is not found. + logical, optional, intent(in) :: no_domain !< If present and true, do not check for file + !! names with an appended tile number + + call get_field_size(filename, fieldname, sizes, field_found=field_found, no_domain=no_domain) + +end subroutine field_size + !> Copies a string subroutine safe_string_copy(str1, str2, fieldnm, caller) @@ -865,6 +890,40 @@ function ensembler(name, ens_no_in) result(en_nm) end function ensembler +!> Provide a string to append to filenames, to differentiate ensemble members, for example. +subroutine get_filename_appendix(suffix) + character(len=*), intent(out) :: suffix !< A string to append to filenames + + call get_filename_suffix(suffix) +end subroutine get_filename_appendix + +!> Write a file version number to the log file or other output file +subroutine write_version_number(version, tag, unit) + character(len=*), intent(in) :: version !< A string that contains the routine name and version + character(len=*), optional, intent(in) :: tag !< A tag name to add to the message + integer, optional, intent(in) :: unit !< An alternate unit number for output + + call write_version(version, tag, unit) +end subroutine write_version_number + + +!> Open a single namelist file that is potentially readable by all PEs. +function open_namelist_file(file) result(unit) + character(len=*), optional, intent(in) :: file !< The file to open, by default "input.nml" + integer :: unit !< The opened unit number of the namelist file + unit = MOM_namelist_file(file) +end function open_namelist_file + +!> Checks the iostat argument that is returned after reading a namelist variable and writes a +!! message if there is an error. +function check_nml_error(IOstat, nml_name) result(ierr) + integer, intent(in) :: IOstat !< An I/O status field from a namelist read call + character(len=*), intent(in) :: nml_name !< The name of the namelist + integer :: ierr !< A copy of IOstat that is returned to preserve legacy function behavior + call check_namelist_error(IOstat, nml_name) + ierr = IOstat +end function check_nml_error + !> Initialize the MOM_io module subroutine MOM_io_init(param_file) type(param_file_type), intent(in) :: param_file !< structure indicating the open file to diff --git a/src/framework/MOM_io_infra.F90 b/src/framework/MOM_io_infra.F90 index 1a075b63ef..d7d744e740 100644 --- a/src/framework/MOM_io_infra.F90 +++ b/src/framework/MOM_io_infra.F90 @@ -5,20 +5,18 @@ module MOM_io_infra use MOM_domain_infra, only : MOM_domain_type, AGRID, BGRID_NE, CGRID_NE use MOM_domain_infra, only : get_simple_array_i_ind, get_simple_array_j_ind -use MOM_domain_infra, only : domain2d, CENTER, CORNER, NORTH_FACE, EAST_FACE +use MOM_domain_infra, only : domain2d, domain1d, CENTER, CORNER, NORTH_FACE, EAST_FACE use MOM_error_infra, only : MOM_error=>MOM_err, NOTE, FATAL, WARNING -use ensemble_manager_mod, only : get_ensemble_id use fms_mod, only : write_version_number, open_namelist_file, check_nml_error use fms_io_mod, only : file_exist, field_exist, field_size, read_data use fms_io_mod, only : fms_io_exit, get_filename_appendix use mpp_io_mod, only : mpp_open, mpp_close, mpp_flush -use mpp_io_mod, only : write_metadata=>mpp_write_meta, mpp_write +use mpp_io_mod, only : mpp_write_meta, mpp_write use mpp_io_mod, only : mpp_get_atts, mpp_attribute_exist -use mpp_io_mod, only : mpp_get_axes, axistype, get_axis_data=>mpp_get_axis_data +use mpp_io_mod, only : mpp_get_axes, axistype, mpp_get_axis_data use mpp_io_mod, only : mpp_get_fields, fieldtype -use mpp_io_mod, only : mpp_get_info -use mpp_io_mod, only : get_file_times=>mpp_get_times +use mpp_io_mod, only : mpp_get_info, mpp_get_times use mpp_io_mod, only : mpp_io_init ! These are encoding constants. use mpp_io_mod, only : APPEND_FILE=>MPP_APPEND, ASCII_FILE=>MPP_ASCII @@ -29,16 +27,15 @@ module MOM_io_infra implicit none ; private ! These interfaces are actually implemented or have explicit interfaces in this file. -public :: MOM_read_data, MOM_read_vector, write_field, open_file, close_file, flush_file -public :: file_exists, field_exists, read_field_chksum -public :: get_file_info, get_file_fields, get_field_atts, io_infra_init, io_infra_end -! The following are simple pass throughs of routines from other modules. They need -! to have explicit interfaces added to this file. -public :: fieldtype, axistype, field_size, get_filename_appendix -public :: get_file_times, read_data, get_axis_data -public :: write_metadata, write_version_number, get_ensemble_id -public :: open_namelist_file, check_nml_error -! These are encoding constants. +public :: open_file, close_file, flush_file, file_exists, get_filename_suffix +public :: get_file_info, get_file_fields, get_file_times +public :: MOM_read_data, MOM_read_vector, write_metadata, write_field +public :: field_exists, get_field_atts, get_field_size, get_axis_data, read_field_chksum +public :: io_infra_init, io_infra_end, MOM_namelist_file, check_namelist_error, write_version +! These types are inherited from underlying infrastructure code, to act as containers for +! information about fields and axes, respectively, and are opaque to this module. +public :: fieldtype, axistype +! These are encoding constant parmeters. public :: APPEND_FILE, ASCII_FILE, MULTIPLE, NETCDF_FILE, OVERWRITE_FILE public :: READONLY_FILE, SINGLE_FILE, WRITEONLY_FILE public :: CENTER, CORNER, NORTH_FACE, EAST_FACE @@ -53,7 +50,7 @@ module MOM_io_infra interface MOM_read_data module procedure MOM_read_data_4d module procedure MOM_read_data_3d - module procedure MOM_read_data_2d + module procedure MOM_read_data_2d, MOM_read_data_2d_region module procedure MOM_read_data_1d module procedure MOM_read_data_0d end interface @@ -72,7 +69,12 @@ module MOM_io_infra interface MOM_read_vector module procedure MOM_read_vector_3d module procedure MOM_read_vector_2d -end interface +end interface MOM_read_vector + +!> Write metadata about a variable or axis to a file and store it for later reuse +interface write_metadata + module procedure write_metadata_axis, write_metadata_field +end interface write_metadata contains @@ -150,6 +152,30 @@ subroutine io_infra_end() call fms_io_exit() end subroutine io_infra_end +!> Open a single namelist file that is potentially readable by all PEs. +function MOM_namelist_file(file) result(unit) + character(len=*), optional, intent(in) :: file !< The file to open, by default "input.nml". + integer :: unit !< The opened unit number of the namelist file + unit = open_namelist_file(file) +end function MOM_namelist_file + +!> Checks the iostat argument that is returned after reading a namelist variable and writes a +!! message if there is an error. +subroutine check_namelist_error(IOstat, nml_name) + integer, intent(in) :: IOstat !< An I/O status field from a namelist read call + character(len=*), intent(in) :: nml_name !< The name of the namelist + integer :: ierr + ierr = check_nml_error(IOstat, nml_name) +end subroutine check_namelist_error + +!> Write a file version number to the log file or other output file +subroutine write_version(version, tag, unit) + character(len=*), intent(in) :: version !< A string that contains the routine name and version + character(len=*), optional, intent(in) :: tag !< A tag name to add to the message + integer, optional, intent(in) :: unit !< An alternate unit number for output + + call write_version_number(version, tag, unit) +end subroutine write_version !> open_file opens a file for parallel or single-file I/O. subroutine open_file(unit, file, action, form, threading, fileset, nohdrs, domain, MOM_domain) @@ -179,6 +205,14 @@ subroutine open_file(unit, file, action, form, threading, fileset, nohdrs, domai endif end subroutine open_file +!> Provide a string to append to filenames, to differentiate ensemble members, for example. +subroutine get_filename_suffix(suffix) + character(len=*), intent(out) :: suffix !< A string to append to filenames + + call get_filename_appendix(suffix) +end subroutine get_filename_suffix + + !> Get information about the number of dimensions, variables, global attributes and time levels !! in the file associated with an open file unit subroutine get_file_info(unit, ndim, nvar, natt, ntime) @@ -200,6 +234,25 @@ subroutine get_file_info(unit, ndim, nvar, natt, ntime) end subroutine get_file_info + +!> Get the times of records from a file + !### Modify this to also convert to time_type, using information about the dimensions? +subroutine get_file_times(unit, time_values, ntime) + integer, intent(in) :: unit !< The I/O unit for the open file + real, allocatable, dimension(:), intent(inout) :: time_values !< The real times for the records in file. + integer, optional, intent(out) :: ntime !< The number of time levels in the file + + integer :: ntimes + + if (allocated(time_values)) deallocate(time_values) + call get_file_info(unit, ntime=ntimes) + if (present(ntime)) ntime = ntimes + if (ntimes > 0) then + allocate(time_values(ntimes)) + call mpp_get_times(unit, time_values) + endif +end subroutine get_file_times + !> Set up the field information (e.g., names and metadata) for all of the variables in a file. The !! argument fields must be allocated with a size that matches the number of variables in a file. subroutine get_file_fields(unit, fields) @@ -238,7 +291,30 @@ function field_exists(filename, field_name, domain, no_domain, MOM_domain) end function field_exists -!> This function uses the fms_io function read_data to read a scalar +!> Given filename and fieldname, this subroutine returns the size of the field in the file +subroutine get_field_size(filename, fieldname, sizes, field_found, no_domain) + character(len=*), intent(in) :: filename !< The name of the file to read + character(len=*), intent(in) :: fieldname !< The name of the variable whose sizes are returned + integer, dimension(:), intent(inout) :: sizes !< The sizes of the variable in each dimension + logical, optional, intent(out) :: field_found !< This indicates whether the field was found in + !! the input file. Without this argument, there + !! is a fatal error if the field is not found. + logical, optional, intent(in) :: no_domain !< If present and true, do not check for file + !! names with an appended tile number + + call field_size(filename, fieldname, sizes, field_found=field_found, no_domain=no_domain) + +end subroutine get_field_size + +!> Extracts and returns the axis data stored in an axistype. +subroutine get_axis_data( axis, dat ) + type(axistype), intent(in) :: axis !< An axis type + real, dimension(:), intent(out) :: dat !< The data in the axis variable + + call mpp_get_axis_data( axis, dat ) +end subroutine get_axis_data + +!> This routine uses the fms_io subroutine read_data to read a scalar !! data field named "fieldname" from file "filename". subroutine MOM_read_data_0d(filename, fieldname, data, timelevel, scale) character(len=*), intent(in) :: filename !< The name of the file to read @@ -256,7 +332,7 @@ subroutine MOM_read_data_0d(filename, fieldname, data, timelevel, scale) end subroutine MOM_read_data_0d -!> This function uses the fms_io function read_data to read a 1-D +!> This routine uses the fms_io subroutine read_data to read a 1-D !! data field named "fieldname" from file "filename". subroutine MOM_read_data_1d(filename, fieldname, data, timelevel, scale) character(len=*), intent(in) :: filename !< The name of the file to read @@ -274,7 +350,7 @@ subroutine MOM_read_data_1d(filename, fieldname, data, timelevel, scale) end subroutine MOM_read_data_1d -!> This function uses the fms_io function read_data to read a distributed +!> This routine uses the fms_io subroutine read_data to read a distributed !! 2-D data field named "fieldname" from file "filename". Valid values for !! "position" include CORNER, CENTER, EAST_FACE and NORTH_FACE. subroutine MOM_read_data_2d(filename, fieldname, data, MOM_Domain, & @@ -302,7 +378,42 @@ subroutine MOM_read_data_2d(filename, fieldname, data, MOM_Domain, & end subroutine MOM_read_data_2d -!> This function uses the fms_io function read_data to read a distributed +!> This routine uses the fms_io subroutine read_data to read a region from a distributed or +!! global 2-D data field named "fieldname" from file "filename". +subroutine MOM_read_data_2d_region(filename, fieldname, data, start, nread, MOM_domain, & + no_domain, scale) + character(len=*), intent(in) :: filename !< The name of the file to read + character(len=*), intent(in) :: fieldname !< The variable name of the data in the file + real, dimension(:,:), intent(inout) :: data !< The 2-dimensional array into which the data + !! should be read + integer, dimension(:), intent(in) :: start !< The starting index to read in each of 4 + !! dimensions. For this 2-d read, the 3rd + !! and 4th values are always 1. + integer, dimension(:), intent(in) :: nread !< The number of points to read in each of 4 + !! dimensions. For this 2-d read, the 3rd + !! and 4th values are always 1. + type(MOM_domain_type), & + optional, intent(in) :: MOM_Domain !< The MOM_Domain that describes the decomposition + logical, optional, intent(in) :: no_domain !< If present and true, this variable does not + !! use domain decomposion. + real, optional, intent(in) :: scale !< A scaling factor that the field is multiplied + !! by before it is returned. + + if (present(MOM_Domain)) then + call read_data(filename, fieldname, data, start, nread, domain=MOM_Domain%mpp_domain, & + no_domain=no_domain) + else + call read_data(filename, fieldname, data, start, nread, no_domain=no_domain) + endif + + if (present(scale)) then ; if (scale /= 1.0) then + ! Dangerously rescale the whole array + data(:,:) = scale*data(:,:) + endif ; endif + +end subroutine MOM_read_data_2d_region + +!> This routine uses the fms_io subroutine read_data to read a distributed !! 3-D data field named "fieldname" from file "filename". Valid values for !! "position" include CORNER, CENTER, EAST_FACE and NORTH_FACE. subroutine MOM_read_data_3d(filename, fieldname, data, MOM_Domain, & @@ -330,7 +441,7 @@ subroutine MOM_read_data_3d(filename, fieldname, data, MOM_Domain, & end subroutine MOM_read_data_3d -!> This function uses the fms_io function read_data to read a distributed +!> This routine uses the fms_io subroutine read_data to read a distributed !! 4-D data field named "fieldname" from file "filename". Valid values for !! "position" include CORNER, CENTER, EAST_FACE and NORTH_FACE. subroutine MOM_read_data_4d(filename, fieldname, data, MOM_Domain, & @@ -359,7 +470,7 @@ subroutine MOM_read_data_4d(filename, fieldname, data, MOM_Domain, & end subroutine MOM_read_data_4d -!> This function uses the fms_io function read_data to read a pair of distributed +!> This routine uses the fms_io subroutine read_data to read a pair of distributed !! 2-D data fields with names given by "[uv]_fieldname" from file "filename". Valid values for !! "stagger" include CGRID_NE, BGRID_NE, and AGRID. subroutine MOM_read_vector_2d(filename, u_fieldname, v_fieldname, u_data, v_data, MOM_Domain, & @@ -403,7 +514,7 @@ subroutine MOM_read_vector_2d(filename, u_fieldname, v_fieldname, u_data, v_data end subroutine MOM_read_vector_2d -!> This function uses the fms_io function read_data to read a pair of distributed +!> This routine uses the fms_io subroutine read_data to read a pair of distributed !! 3-D data fields with names given by "[uv]_fieldname" from file "filename". Valid values for !! "stagger" include CGRID_NE, BGRID_NE, and AGRID. subroutine MOM_read_vector_3d(filename, u_fieldname, v_fieldname, u_data, v_data, MOM_Domain, & @@ -511,6 +622,7 @@ subroutine write_field_0d(io_unit, field_md, field, tstamp) call mpp_write(io_unit, field_md, field, tstamp=tstamp) end subroutine write_field_0d +!> Write the data for an axis subroutine MOM_write_axis(io_unit, axis) integer, intent(in) :: io_unit !< File I/O unit handle type(axistype), intent(in) :: axis !< An axis type variable with information to write @@ -519,4 +631,54 @@ subroutine MOM_write_axis(io_unit, axis) end subroutine MOM_write_axis +!> Store information about an axis in a previously defined axistype and write this +!! information to the file indicated by unit. +subroutine write_metadata_axis( unit, axis, name, units, longname, cartesian, sense, domain, data, calendar) + integer, intent(in) :: unit !< The I/O unit for the file to write to + type(axistype), intent(inout) :: axis !< The axistype where this information is stored. + character(len=*), intent(in) :: name !< The name in the file of this axis + character(len=*), intent(in) :: units !< The units of this axis + character(len=*), intent(in) :: longname !< The long description of this axis + character(len=*), optional, intent(in) :: cartesian !< A variable indicating which direction + !! this axis corresponds with. Valid values + !! include 'X', 'Y', 'Z', 'T', and 'N' for none. + integer, optional, intent(in) :: sense !< This is 1 for axes whose values increase upward, or + !! -1 if they increase downward. + type(domain1D), optional, intent(in) :: domain !< The domain decomposion for this axis + real, dimension(:), optional, intent(in) :: data !< The coordinate values of the points on this axis + character(len=*), optional, intent(in) :: calendar !< The name of the calendar used with a time axis + + call mpp_write_meta(unit, axis, name, units, longname, cartesian=cartesian, sense=sense, & + domain=domain, data=data, calendar=calendar) +end subroutine write_metadata_axis + +!> Store information about an output variable in a previously defined fieldtype and write this +!! information to the file indicated by unit. +subroutine write_metadata_field(unit, field, axes, name, units, longname, & + min, max, fill, scale, add, pack, standard_name, checksum) + integer, intent(in) :: unit !< The I/O unit for the file to write to + type(fieldtype), intent(inout) :: field !< The fieldtype where this information is stored + type(axistype), dimension(:), intent(in) :: axes !< Handles for the axis used for this variable + character(len=*), intent(in) :: name !< The name in the file of this variable + character(len=*), intent(in) :: units !< The units of this variable + character(len=*), intent(in) :: longname !< The long description of this variable + real, optional, intent(in) :: min !< The minimum valid value for this variable + real, optional, intent(in) :: max !< The maximum valid value for this variable + real, optional, intent(in) :: fill !< Missing data fill value + real, optional, intent(in) :: scale !< An multiplicative factor by which to scale + !! the variable before output + real, optional, intent(in) :: add !< An offset to add to the variable before output + integer, optional, intent(in) :: pack !< A precision reduction factor with which the + !! variable. The default, 1, has no reduction, + !! but 2 is not uncommon. + character(len=*), optional, intent(in) :: standard_name !< The standard (e.g., CMOR) name for this variable + integer(kind=8), dimension(:), & + optional, intent(in) :: checksum !< Checksum values that can be used to verify reads. + + + call mpp_write_meta( unit, field, axes, name, units, longname, & + min=min, max=max, fill=fill, scale=scale, add=add, pack=pack, standard_name=standard_name, checksum=checksum) + +end subroutine write_metadata_field + end module MOM_io_infra diff --git a/src/framework/MOM_restart.F90 b/src/framework/MOM_restart.F90 index 6780eff644..d0b3b24aef 100644 --- a/src/framework/MOM_restart.F90 +++ b/src/framework/MOM_restart.F90 @@ -1084,7 +1084,7 @@ subroutine restore_state(filename, directory, day, G, CS) integer :: i, n, m, missing_fields integer :: isL, ieL, jsL, jeL, is0, js0 integer :: sizes(7) - integer :: ndim, nvar, natt, ntime, pos + integer :: nvar, ntime, pos integer :: unit(CS%max_fields) ! The I/O units of all open files. character(len=200) :: unit_path(CS%max_fields) ! The file names. @@ -1119,11 +1119,9 @@ subroutine restore_state(filename, directory, day, G, CS) ! Get the time from the first file in the list that has one. do n=1,num_file - call get_file_info(unit(n), ndim, nvar, natt, ntime) + call get_file_times(unit(n), time_vals, ntime) if (ntime < 1) cycle - allocate(time_vals(ntime)) - call get_file_times(unit(n), time_vals) t1 = time_vals(1) deallocate(time_vals) @@ -1138,11 +1136,9 @@ subroutine restore_state(filename, directory, day, G, CS) ! if they differ from the first time. if (is_root_pe()) then do m = n+1,num_file - call get_file_info(unit(n), ndim, nvar, natt, ntime) + call get_file_times(unit(n), time_vals, ntime) if (ntime < 1) cycle - allocate(time_vals(ntime)) - call get_file_times(unit(n), time_vals) t2 = time_vals(1) deallocate(time_vals) @@ -1157,7 +1153,7 @@ subroutine restore_state(filename, directory, day, G, CS) ! Read each variable from the first file in which it is found. do n=1,num_file - call get_file_info(unit(n), ndim, nvar, natt, ntime) + call get_file_info(unit(n), nvar=nvar) allocate(fields(nvar)) call get_file_fields(unit(n), fields(1:nvar)) @@ -1216,8 +1212,9 @@ subroutine restore_state(filename, directory, day, G, CS) call MOM_read_data(unit_path(n), varname, CS%var_ptr2d(m)%p, & G%Domain, timelevel=1, position=pos) else ! This array is not domain-decomposed. This variant may be under-tested. - call read_data(unit_path(n), varname, CS%var_ptr2d(m)%p, & - no_domain=.true., timelevel=1) + call MOM_error(FATAL, & + "MOM_restart does not support 2-d arrays without domain decomposition.") + ! call read_data(unit_path(n), varname, CS%var_ptr2d(m)%p,no_domain=.true., timelevel=1) endif if (is_there_a_checksum) checksum_data = chksum(CS%var_ptr2d(m)%p(isL:ieL,jsL:jeL)) elseif (associated(CS%var_ptr3d(m)%p)) then ! Read a 3d array. @@ -1225,8 +1222,9 @@ subroutine restore_state(filename, directory, day, G, CS) call MOM_read_data(unit_path(n), varname, CS%var_ptr3d(m)%p, & G%Domain, timelevel=1, position=pos) else ! This array is not domain-decomposed. This variant may be under-tested. - call read_data(unit_path(n), varname, CS%var_ptr3d(m)%p, & - no_domain=.true., timelevel=1) + call MOM_error(FATAL, & + "MOM_restart does not support 3-d arrays without domain decomposition.") + ! call read_data(unit_path(n), varname, CS%var_ptr3d(m)%p, no_domain=.true., timelevel=1) endif if (is_there_a_checksum) checksum_data = chksum(CS%var_ptr3d(m)%p(isL:ieL,jsL:jeL,:)) elseif (associated(CS%var_ptr4d(m)%p)) then ! Read a 4d array. @@ -1234,8 +1232,9 @@ subroutine restore_state(filename, directory, day, G, CS) call MOM_read_data(unit_path(n), varname, CS%var_ptr4d(m)%p, & G%Domain, timelevel=1, position=pos) else ! This array is not domain-decomposed. This variant may be under-tested. - call read_data(unit_path(n), varname, CS%var_ptr4d(m)%p, & - no_domain=.true., timelevel=1) + call MOM_error(FATAL, & + "MOM_restart does not support 4-d arrays without domain decomposition.") + ! call read_data(unit_path(n), varname, CS%var_ptr4d(m)%p, no_domain=.true., timelevel=1) endif if (is_there_a_checksum) checksum_data = chksum(CS%var_ptr4d(m)%p(isL:ieL,jsL:jeL,:,:)) else diff --git a/src/initialization/MOM_grid_initialize.F90 b/src/initialization/MOM_grid_initialize.F90 index b5685745ac..0fac3e15b4 100644 --- a/src/initialization/MOM_grid_initialize.F90 +++ b/src/initialization/MOM_grid_initialize.F90 @@ -12,7 +12,7 @@ module MOM_grid_initialize use MOM_error_handler, only : MOM_error, MOM_mesg, FATAL, is_root_pe use MOM_error_handler, only : callTree_enter, callTree_leave use MOM_file_parser, only : get_param, log_param, log_version, param_file_type -use MOM_io, only : MOM_read_data, read_data, slasher, file_exists, stdout +use MOM_io, only : MOM_read_data, slasher, file_exists, stdout use MOM_io, only : CORNER, NORTH_FACE, EAST_FACE use MOM_unit_scaling, only : unit_scale_type @@ -333,7 +333,7 @@ subroutine set_grid_metrics_from_mosaic(G, param_file, US) start(2) = 2 ; nread(1) = ni+1 ; nread(2) = 2 allocate( tmpGlbl(ni+1,2) ) if (is_root_PE()) & - call read_data(filename, "x", tmpGlbl, start, nread, no_domain=.TRUE.) + call MOM_read_data(filename, "x", tmpGlbl, start, nread, no_domain=.TRUE.) call broadcast(tmpGlbl, 2*(ni+1), root_PE()) ! I don't know why the second axis is 1 or 2 here. -RWH @@ -351,7 +351,7 @@ subroutine set_grid_metrics_from_mosaic(G, param_file, US) start(:) = 1 ; nread(:) = 1 start(1) = int(ni/4)+1 ; nread(2) = nj+1 if (is_root_PE()) & - call read_data(filename, "y", tmpGlbl, start, nread, no_domain=.TRUE.) + call MOM_read_data(filename, "y", tmpGlbl, start, nread, no_domain=.TRUE.) call broadcast(tmpGlbl, nj+1, root_PE()) do j=G%jsg,G%jeg From 291505cd17f6313d0911c99e1da9d1bcae82ae52 Mon Sep 17 00:00:00 2001 From: Robert Hallberg Date: Wed, 27 Jan 2021 08:58:01 -0500 Subject: [PATCH 3/4] Change netcdf use statements to use, only Modified the module use statements for netcdf to explicitly list the routines and constants that are used. Also added comments documenting the purpose of the encoding constants that MOM_io makes available. Also added a missing NF90_close call to Surface_Bands_by_data_override. All answers are bitwise identical. --- src/ALE/MOM_regridding.F90 | 3 +- src/diagnostics/MOM_sum_output.F90 | 7 ++- src/framework/MOM_io.F90 | 53 ++++++++++--------- .../MOM_shared_initialization.F90 | 5 +- src/tracer/MOM_tracer_Z_init.F90 | 6 ++- src/user/MOM_wave_interface.F90 | 9 +++- 6 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/ALE/MOM_regridding.F90 b/src/ALE/MOM_regridding.F90 index e827b3ff3a..dc85fab7d3 100644 --- a/src/ALE/MOM_regridding.F90 +++ b/src/ALE/MOM_regridding.F90 @@ -30,7 +30,8 @@ module MOM_regridding use coord_slight, only : init_coord_slight, slight_CS, set_slight_params, build_slight_column, end_coord_slight use coord_adapt, only : init_coord_adapt, adapt_CS, set_adapt_params, build_adapt_column, end_coord_adapt -use netcdf ! Used by check_grid_def() +! Direct netcdf calls are used by check_grid_def() +use netcdf, only : NF90_open, NF90_inq_varid, NF90_get_att, NF90_NOERR, NF90_NOWRITE implicit none ; private diff --git a/src/diagnostics/MOM_sum_output.F90 b/src/diagnostics/MOM_sum_output.F90 index 0746a120f2..ca57926ab1 100644 --- a/src/diagnostics/MOM_sum_output.F90 +++ b/src/diagnostics/MOM_sum_output.F90 @@ -26,7 +26,10 @@ module MOM_sum_output use MOM_variables, only : surface, thermo_var_ptrs use MOM_verticalGrid, only : verticalGrid_type -use netcdf +use netcdf, only : NF90_create, NF90_def_dim, NF90_def_var, NF90_put_att, NF90_enddef +use netcdf, only : NF90_put_var, NF90_open, NF90_close, NF90_inquire_variable, NF90_strerror +use netcdf, only : NF90_inq_varid, NF90_inquire_dimension, NF90_get_var, NF90_get_att +use netcdf, only : NF90_DOUBLE, NF90_NOERR, NF90_NOWRITE, NF90_GLOBAL, NF90_ENOTATT implicit none ; private @@ -1351,7 +1354,7 @@ subroutine read_depth_list(G, US, CS, filename) character(len=240) :: var_name, var_msg real, allocatable :: tmp(:) integer :: ncid, status, varid, list_size, k - integer :: ndim, len, var_dim_ids(NF90_MAX_VAR_DIMS) + integer :: ndim, len, var_dim_ids(8) character(len=16) :: depth_file_chksum, depth_grid_chksum character(len=16) :: area_file_chksum, area_grid_chksum integer :: depth_attr_status, area_attr_status diff --git a/src/framework/MOM_io.F90 b/src/framework/MOM_io.F90 index a251c52281..d990f2eea6 100644 --- a/src/framework/MOM_io.F90 +++ b/src/framework/MOM_io.F90 @@ -11,7 +11,8 @@ module MOM_io use MOM_error_handler, only : MOM_error, NOTE, FATAL, WARNING use MOM_file_parser, only : log_version, param_file_type use MOM_grid, only : ocean_grid_type -use MOM_io_infra, only : MOM_read_data, read_data=>MOM_read_data, MOM_read_vector, read_field_chksum +use MOM_io_infra, only : MOM_read_data, MOM_read_vector, read_field_chksum +use MOM_io_infra, only : read_data=>MOM_read_data ! read_data will be removed soon. use MOM_io_infra, only : file_exists, get_file_info, get_file_fields, get_field_atts use MOM_io_infra, only : open_file, close_file, get_field_size, fieldtype, field_exists use MOM_io_infra, only : flush_file, get_filename_suffix @@ -26,8 +27,7 @@ module MOM_io use iso_fortran_env, only : stdout_iso=>output_unit, stderr_iso=>error_unit use netcdf, only : NF90_open, NF90_inquire, NF90_inq_varids, NF90_inquire_variable -use netcdf, only : NF90_Inquire_Dimension, NF90_max_name, NF90_max_var_dims -use netcdf, only : NF90_STRERROR, NF90_NOWRITE, NF90_NOERR +use netcdf, only : NF90_Inquire_Dimension, NF90_STRERROR, NF90_NOWRITE, NF90_NOERR implicit none ; private @@ -35,18 +35,23 @@ module MOM_io public :: create_file, reopen_file, num_timelevels, cmor_long_std, ensembler, MOM_io_init public :: MOM_write_field, var_desc, modify_vardesc, query_vardesc public :: open_namelist_file, check_namelist_error, check_nml_error -! The following are simple pass throughs of routines from MOM_io_infra or other modules -public :: close_file, field_exists, field_size, fieldtype, get_filename_appendix -public :: file_exists, flush_file, get_file_info, get_file_fields, get_field_atts -public :: get_file_times, open_file, get_axis_data +! The following are simple pass throughs of routines from MOM_io_infra or other modules. +public :: file_exists, open_file, close_file, flush_file, get_filename_appendix +public :: get_file_info, field_exists, get_file_fields, get_file_times +public :: fieldtype, field_size, get_field_atts +public :: axistype, get_axis_data public :: MOM_read_data, MOM_read_vector, read_field_chksum public :: slasher, write_field, write_version_number public :: io_infra_init, io_infra_end -! This API is here just to support non-FMS couplers, and should not persist. +! This API is here just to support potential use by non-FMS drivers, and should not persist. public :: read_data -! These are encoding constants. -public :: APPEND_FILE, ASCII_FILE, MULTIPLE, NETCDF_FILE, OVERWRITE_FILE -public :: READONLY_FILE, SINGLE_FILE, WRITEONLY_FILE +!> These encoding constants are used to indicate the file format +public :: ASCII_FILE, NETCDF_FILE +!> These encoding constants are used to indicate whether the file is domain decomposed +public :: MULTIPLE, SINGLE_FILE +!> These encoding constants are used to indicate the access mode for a file +public :: APPEND_FILE, OVERWRITE_FILE, READONLY_FILE, WRITEONLY_FILE +!> These encoding constants are used to indicate the discretization position of a variable public :: CENTER, CORNER, NORTH_FACE, EAST_FACE !> Write a registered field to an output file, potentially with rotation @@ -435,16 +440,14 @@ function num_timelevels(filename, varname, min_dims) result(n_time) integer :: n_time !< number of time levels varname has in filename logical :: found - character(len=200) :: msg - character(len=nf90_max_name) :: name + character(len=256) :: msg, name integer :: ncid, nvars, status, varid, ndims, n - integer, allocatable :: varids(:) - integer, dimension(nf90_max_var_dims) :: dimids + integer, allocatable :: varids(:), dimids(:) n_time = -1 found = .false. - ! To do the same via MOM_io_infra calls, do the following: + ! To do almost the same via MOM_io_infra calls, do the following: ! found = field_exists(filename, varname) ! call open_file(ncid, filename, action=READONLY_FILE, form=NETCDF_FILE, threading=MULTIPLE) ! call get_file_info(ncid, ntime=n_time) @@ -491,9 +494,8 @@ function num_timelevels(filename, varname, min_dims) result(n_time) if (trim(lowercase(name)) == trim(lowercase(varname))) then if (found) then - call MOM_error(WARNING,"num_timelevels: "//& - " Two variables match the case-insensitive name "//trim(varname)//& - " in file "//trim(filename)//" - "//trim(NF90_STRERROR(status))) + call MOM_error(WARNING, "num_timelevels: Two variables match the case-insensitive name "//& + trim(varname)//" in file "//trim(filename)) else varid = varids(n) ; found = .true. endif @@ -518,19 +520,19 @@ function num_timelevels(filename, varname, min_dims) result(n_time) if (present(min_dims)) then if (ndims < min_dims-1) then write(msg, '(I3)') min_dims - call MOM_error(WARNING, "num_timelevels: variable "//trim(varname)//& - " in file "//trim(filename)//" has fewer than min_dims = "//trim(msg)//& - " dimensions.") + call MOM_error(WARNING, "num_timelevels: variable "//trim(varname)//" in file "//& + trim(filename)//" has fewer than min_dims = "//trim(msg)//" dimensions.") elseif (ndims == min_dims - 1) then n_time = 0 ; return endif endif - status = nf90_inquire_variable(ncid, varid, dimids = dimids(1:ndims)) + allocate(dimids(ndims)) + status = nf90_inquire_variable(ncid, varid, dimids=dimids(1:ndims)) if (status /= NF90_NOERR) then call MOM_error(WARNING,"num_timelevels: "//trim(NF90_STRERROR(status))//& " Getting last dimension ID for "//trim(varname)//" in "//trim(filename)) - return + deallocate(dimids) ; return endif status = nf90_Inquire_Dimension(ncid, dimids(ndims), len=n_time) @@ -538,8 +540,9 @@ function num_timelevels(filename, varname, min_dims) result(n_time) trim(NF90_STRERROR(status))//" Getting number of time levels of "//& trim(varname)//" in "//trim(filename)) -end function num_timelevels + deallocate(dimids) +end function num_timelevels !> Returns a vardesc type whose elements have been filled with the provided !! fields. The argument name is required, while the others are optional and diff --git a/src/initialization/MOM_shared_initialization.F90 b/src/initialization/MOM_shared_initialization.F90 index 24318954a1..22e8227637 100644 --- a/src/initialization/MOM_shared_initialization.F90 +++ b/src/initialization/MOM_shared_initialization.F90 @@ -17,7 +17,8 @@ module MOM_shared_initialization use MOM_string_functions, only : uppercase use MOM_unit_scaling, only : unit_scale_type -use netcdf +use netcdf, only : NF90_open, NF90_inq_varid, NF90_get_var, NF90_close +use netcdf, only : NF90_inq_dimid, NF90_inquire_dimension, NF90_NOWRITE, NF90_NOERR implicit none ; private @@ -189,7 +190,7 @@ subroutine apply_topography_edits_from_file(D, G, param_file, US) type(param_file_type), intent(in) :: param_file !< Parameter file structure type(unit_scale_type), optional, intent(in) :: US !< A dimensional unit scaling type - ! Local variables + ! Local variablesNF real :: m_to_Z ! A dimensional rescaling factor. character(len=200) :: topo_edits_file, inputdir ! Strings for file/path character(len=40) :: mdl = "apply_topography_edits_from_file" ! This subroutine's name. diff --git a/src/tracer/MOM_tracer_Z_init.F90 b/src/tracer/MOM_tracer_Z_init.F90 index 1e79061dcd..8381c85538 100644 --- a/src/tracer/MOM_tracer_Z_init.F90 +++ b/src/tracer/MOM_tracer_Z_init.F90 @@ -11,7 +11,9 @@ module MOM_tracer_Z_init use MOM_unit_scaling, only : unit_scale_type use MOM_verticalGrid, only : verticalGrid_type -use netcdf +use netcdf, only : NF90_open, NF90_inq_varid, NF90_inquire_variable, NF90_get_var +use netcdf, only : NF90_get_att, NF90_inquire_dimension, NF90_close, NF90_strerror +use netcdf, only : NF90_NOWRITE, NF90_NOERR implicit none ; private @@ -402,7 +404,7 @@ subroutine read_Z_edges(filename, tr_name, z_edges, nz_out, has_edges, & character(len=120) :: dim_name, edge_name, tr_msg, dim_msg logical :: monotonic integer :: ncid, status, intid, tr_id, layid, k - integer :: nz_edge, ndim, tr_dim_ids(NF90_MAX_VAR_DIMS) + integer :: nz_edge, ndim, tr_dim_ids(8) mdl = "MOM_tracer_Z_init read_Z_edges: " tr_msg = trim(tr_name)//" in "//trim(filename) diff --git a/src/user/MOM_wave_interface.F90 b/src/user/MOM_wave_interface.F90 index df4b2a30fd..4531c63b99 100644 --- a/src/user/MOM_wave_interface.F90 +++ b/src/user/MOM_wave_interface.F90 @@ -18,6 +18,9 @@ module MOM_wave_interface use MOM_verticalgrid, only : verticalGrid_type use data_override_mod, only : data_override_init, data_override +use netcdf, only : NF90_open, NF90_inq_varid, NF90_inquire_variable, NF90_get_var +use netcdf, only : NF90_inquire_dimension, NF90_close, NF90_NOWRITE, NF90_NOERR + implicit none ; private #include @@ -773,12 +776,12 @@ end subroutine Update_Stokes_Drift !> A subroutine to fill the Stokes drift from a NetCDF file !! using the data_override procedures. subroutine Surface_Bands_by_data_override(day_center, G, GV, US, CS) - use NETCDF type(time_type), intent(in) :: day_center !< Center of timestep type(wave_parameters_CS), pointer :: CS !< Wave structure type(ocean_grid_type), intent(inout) :: G !< Grid structure type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type + ! Local variables real :: temp_x(SZI_(G),SZJ_(G)) ! Pseudo-zonal Stokes drift of band at h-points [m s-1] real :: temp_y(SZI_(G),SZJ_(G)) ! Psuedo-meridional Stokes drift of band at h-points [m s-1] @@ -895,6 +898,10 @@ subroutine Surface_Bands_by_data_override(day_center, G, GV, US, CS) enddo endif + rcode_wn = NF90_close(ncid) + if (rcode_wn /= 0) call MOM_error(WARNING, & + "Error closing file "//trim(SurfBandFileName)//" in MOM_wave_interface.") + endif do b = 1,CS%NumBands From 0977e13ab5b8063105ef6566c95bdf70fe414b16 Mon Sep 17 00:00:00 2001 From: Alistair Adcroft Date: Wed, 27 Jan 2021 09:47:25 -0500 Subject: [PATCH 4/4] Undid typo --- src/initialization/MOM_shared_initialization.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/initialization/MOM_shared_initialization.F90 b/src/initialization/MOM_shared_initialization.F90 index 22e8227637..d32f972258 100644 --- a/src/initialization/MOM_shared_initialization.F90 +++ b/src/initialization/MOM_shared_initialization.F90 @@ -190,7 +190,7 @@ subroutine apply_topography_edits_from_file(D, G, param_file, US) type(param_file_type), intent(in) :: param_file !< Parameter file structure type(unit_scale_type), optional, intent(in) :: US !< A dimensional unit scaling type - ! Local variablesNF + ! Local variables real :: m_to_Z ! A dimensional rescaling factor. character(len=200) :: topo_edits_file, inputdir ! Strings for file/path character(len=40) :: mdl = "apply_topography_edits_from_file" ! This subroutine's name.