Skip to content

Commit

Permalink
Merge pull request mom-ocean#1488 from marshallward/rotate_read_data
Browse files Browse the repository at this point in the history
Testing: Rotation support for MOM_read_data
  • Loading branch information
Hallberg-NOAA authored Sep 9, 2021
2 parents b560b2c + e5a522b commit a316416
Show file tree
Hide file tree
Showing 7 changed files with 430 additions and 107 deletions.
17 changes: 14 additions & 3 deletions config_src/infra/FMS1/MOM_domain_infra.F90
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ module MOM_domain_infra
!! would be contain only land points and are not
!! assigned to actual processors. This need not be
!! assigned if all logical processors are used.
integer :: turns !< Number of quarter-turns from input to this grid.
type(MOM_domain_type), pointer :: domain_in => NULL()
!< Reference to unrotated domain (if turned)
end type MOM_domain_type

integer, parameter :: To_All = To_East + To_West + To_North + To_South !< A flag for passing in all directions
Expand Down Expand Up @@ -1396,6 +1399,9 @@ subroutine create_MOM_domain(MOM_dom, n_global, n_halo, reentrant, tripolar_N, l
mask_table_exists = .false.
endif

! Initialize as an unrotated domain
MOM_dom%turns = 0

call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain)

!For downsampled domain, recommend a halo of 1 (or 0?) since we're not doing wide-stencil computations.
Expand Down Expand Up @@ -1487,8 +1493,9 @@ end subroutine get_domain_components_d2D
!! some properties of the new type to differ from the original one.
subroutine clone_MD_to_MD(MD_in, MOM_dom, min_halo, halo_size, symmetric, domain_name, &
turns, refine, extra_halo)
type(MOM_domain_type), intent(in) :: MD_in !< An existing MOM_domain
type(MOM_domain_type), pointer :: MOM_dom !< A pointer to a MOM_domain that will be
type(MOM_domain_type), target, intent(in) :: MD_in !< An existing MOM_domain
type(MOM_domain_type), pointer :: MOM_dom
!< A pointer to a MOM_domain that will be
!! allocated if it is unassociated, and will have data
!! copied from MD_in
integer, dimension(2), &
Expand Down Expand Up @@ -1619,8 +1626,12 @@ subroutine clone_MD_to_MD(MD_in, MOM_dom, min_halo, halo_size, symmetric, domain
MOM_dom%name = MD_in%name
endif

call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain, xextent=exni, yextent=exnj)
MOM_dom%turns = qturns
if (qturns /= 0) then
MOM_dom%domain_in => MD_in
endif

call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain, xextent=exni, yextent=exnj)
call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain_d2, domain_name=MOM_dom%name, coarsen=2)

end subroutine clone_MD_to_MD
Expand Down
74 changes: 33 additions & 41 deletions config_src/infra/FMS1/MOM_io_infra.F90
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ module MOM_io_infra
! These interfaces are actually implemented or have explicit interfaces in this file.
public :: open_file, open_ASCII_file, file_is_open, close_file, flush_file, file_exists
public :: get_file_info, get_file_fields, get_file_times, get_filename_suffix
public :: MOM_read_data, MOM_read_vector, write_metadata, write_field
public :: read_field, 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
public :: stdout_if_root
Expand All @@ -55,13 +55,13 @@ module MOM_io_infra
end interface open_file

!> Read a data field from a file
interface MOM_read_data
module procedure MOM_read_data_4d
module procedure MOM_read_data_3d
module procedure MOM_read_data_2d, MOM_read_data_2d_region
module procedure MOM_read_data_1d, MOM_read_data_1d_int
module procedure MOM_read_data_0d, MOM_read_data_0d_int
end interface
interface read_field
module procedure read_field_4d
module procedure read_field_3d
module procedure read_field_2d, read_field_2d_region
module procedure read_field_1d, read_field_1d_int
module procedure read_field_0d, read_field_0d_int
end interface read_field

!> Write a registered field to an output file
interface write_field
Expand All @@ -74,10 +74,10 @@ module MOM_io_infra
end interface write_field

!> Read a pair of data fields representing the two components of a vector from a file
interface MOM_read_vector
interface read_vector
module procedure MOM_read_vector_3d
module procedure MOM_read_vector_2d
end interface MOM_read_vector
end interface read_vector

!> Write metadata about a variable or axis to a file and store it for later reuse
interface write_metadata
Expand Down Expand Up @@ -416,8 +416,8 @@ end subroutine get_axis_data

!> This routine uses the fms_io subroutine read_data to read a scalar named
!! "fieldname" from a single or domain-decomposed file "filename".
subroutine MOM_read_data_0d(filename, fieldname, data, timelevel, scale, MOM_Domain, &
global_file, file_may_be_4d)
subroutine read_field_0d(filename, fieldname, data, timelevel, scale, MOM_Domain, &
global_file, file_may_be_4d)
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, intent(inout) :: data !< The 1-dimensional array into which the data
Expand Down Expand Up @@ -471,12 +471,11 @@ subroutine MOM_read_data_0d(filename, fieldname, data, timelevel, scale, MOM_Dom
if (present(scale)) then ; if (scale /= 1.0) then
data = scale*data
endif ; endif

end subroutine MOM_read_data_0d
end subroutine read_field_0d

!> This routine uses the fms_io subroutine read_data to read a 1-D data field named
!! "fieldname" from a single or domain-decomposed file "filename".
subroutine MOM_read_data_1d(filename, fieldname, data, timelevel, scale, MOM_Domain, &
subroutine read_field_1d(filename, fieldname, data, timelevel, scale, MOM_Domain, &
global_file, file_may_be_4d)
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
Expand Down Expand Up @@ -521,7 +520,7 @@ subroutine MOM_read_data_1d(filename, fieldname, data, timelevel, scale, MOM_Dom
endif
enddo
if ((n == nvar+1) .or. (nvar < 1)) call MOM_error(WARNING, &
"MOM_read_data apparently did not find 1-d variable "//trim(fieldname)//" in file "//trim(filename))
"read_field apparently did not find 1-d variable "//trim(fieldname)//" in file "//trim(filename))

deallocate(fields)
call mpp_close(unit)
Expand All @@ -534,14 +533,13 @@ subroutine MOM_read_data_1d(filename, fieldname, data, timelevel, scale, MOM_Dom
if (present(scale)) then ; if (scale /= 1.0) then
data(:) = scale*data(:)
endif ; endif

end subroutine MOM_read_data_1d
end subroutine read_field_1d

!> 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, &
timelevel, position, scale, global_file, file_may_be_4d)
subroutine read_field_2d(filename, fieldname, data, MOM_Domain, &
timelevel, position, scale, global_file, file_may_be_4d)
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
Expand Down Expand Up @@ -589,7 +587,7 @@ subroutine MOM_read_data_2d(filename, fieldname, data, MOM_Domain, &
endif
enddo
if ((n == nvar+1) .or. (nvar < 1)) call MOM_error(WARNING, &
"MOM_read_data apparently did not find 2-d variable "//trim(fieldname)//" in file "//trim(filename))
"read_field apparently did not find 2-d variable "//trim(fieldname)//" in file "//trim(filename))

deallocate(fields)
call mpp_close(unit)
Expand All @@ -598,13 +596,12 @@ subroutine MOM_read_data_2d(filename, fieldname, data, MOM_Domain, &
if (present(scale)) then ; if (scale /= 1.0) then
call rescale_comp_data(MOM_Domain, data, scale)
endif ; endif

end subroutine MOM_read_data_2d
end subroutine read_field_2d

!> 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)
subroutine read_field_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
Expand Down Expand Up @@ -637,13 +634,12 @@ subroutine MOM_read_data_2d_region(filename, fieldname, data, start, nread, MOM_
data(:,:) = scale*data(:,:)
endif
endif ; endif

end subroutine MOM_read_data_2d_region
end subroutine read_field_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, &
subroutine read_field_3d(filename, fieldname, data, MOM_Domain, &
timelevel, position, scale, global_file, file_may_be_4d)
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
Expand Down Expand Up @@ -692,7 +688,7 @@ subroutine MOM_read_data_3d(filename, fieldname, data, MOM_Domain, &
endif
enddo
if ((n == nvar+1) .or. (nvar < 1)) call MOM_error(WARNING, &
"MOM_read_data apparently did not find 3-d variable "//trim(fieldname)//" in file "//trim(filename))
"read_field apparently did not find 3-d variable "//trim(fieldname)//" in file "//trim(filename))

deallocate(fields)
call mpp_close(unit)
Expand All @@ -701,13 +697,12 @@ subroutine MOM_read_data_3d(filename, fieldname, data, MOM_Domain, &
if (present(scale)) then ; if (scale /= 1.0) then
call rescale_comp_data(MOM_Domain, data, scale)
endif ; endif

end subroutine MOM_read_data_3d
end subroutine read_field_3d

!> 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, &
subroutine read_field_4d(filename, fieldname, data, MOM_Domain, &
timelevel, position, scale, global_file)
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
Expand Down Expand Up @@ -754,40 +749,37 @@ subroutine MOM_read_data_4d(filename, fieldname, data, MOM_Domain, &
endif
enddo
if ((n == nvar+1) .or. (nvar < 1)) call MOM_error(WARNING, &
"MOM_read_data apparently did not find 4-d variable "//trim(fieldname)//" in file "//trim(filename))
"read_field apparently did not find 4-d variable "//trim(fieldname)//" in file "//trim(filename))

deallocate(fields)
call mpp_close(unit)

if (present(scale)) then ; if (scale /= 1.0) then
call rescale_comp_data(MOM_Domain, data, scale)
endif ; endif

end subroutine MOM_read_data_4d
end subroutine read_field_4d

!> This routine uses the fms_io subroutine read_data to read a scalar integer
!! data field named "fieldname" from file "filename".
subroutine MOM_read_data_0d_int(filename, fieldname, data, timelevel)
subroutine read_field_0d_int(filename, fieldname, data, timelevel)
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
integer, intent(inout) :: data !< The 1-dimensional array into which the data
integer, optional, intent(in) :: timelevel !< The time level in the file to read

call read_data(filename, fieldname, data, timelevel=timelevel, no_domain=.true.)

end subroutine MOM_read_data_0d_int
end subroutine read_field_0d_int

!> This routine uses the fms_io subroutine read_data to read a 1-D integer
!! data field named "fieldname" from file "filename".
subroutine MOM_read_data_1d_int(filename, fieldname, data, timelevel)
subroutine read_field_1d_int(filename, fieldname, data, timelevel)
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
integer, dimension(:), intent(inout) :: data !< The 1-dimensional array into which the data
integer, optional, intent(in) :: timelevel !< The time level in the file to read

call read_data(filename, fieldname, data, timelevel=timelevel, no_domain=.true.)

end subroutine MOM_read_data_1d_int
end subroutine read_field_1d_int


!> This routine uses the fms_io subroutine read_data to read a pair of distributed
Expand Down
18 changes: 14 additions & 4 deletions config_src/infra/FMS2/MOM_domain_infra.F90
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ module MOM_domain_infra
!! would be contain only land points and are not
!! assigned to actual processors. This need not be
!! assigned if all logical processors are used.
integer :: turns !< Number of quarter-turns from input to this grid.
type(MOM_domain_type), pointer :: domain_in => NULL()
!< Reference to unrotated domain (if turned)
end type MOM_domain_type

integer, parameter :: To_All = To_East + To_West + To_North + To_South !< A flag for passing in all directions
Expand Down Expand Up @@ -1396,14 +1399,16 @@ subroutine create_MOM_domain(MOM_dom, n_global, n_halo, reentrant, tripolar_N, l
mask_table_exists = .false.
endif

! Initialize as an unrotated domain
MOM_dom%turns = 0

call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain)

!For downsampled domain, recommend a halo of 1 (or 0?) since we're not doing wide-stencil computations.
!But that does not work because the downsampled field would not have the correct size to pass the checks, e.g., we get
!error: downsample_diag_indices_get: peculiar size 28 in i-direction\ndoes not match one of 24 25 26 27
! call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain_d2, halo_size=(MOM_dom%nihalo/2), coarsen=2)
call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain_d2, coarsen=2)

end subroutine create_MOM_domain

!> dealloc_MOM_domain deallocates memory associated with a pointer to a MOM_domain_type
Expand Down Expand Up @@ -1487,8 +1492,9 @@ end subroutine get_domain_components_d2D
!! some properties of the new type to differ from the original one.
subroutine clone_MD_to_MD(MD_in, MOM_dom, min_halo, halo_size, symmetric, domain_name, &
turns, refine, extra_halo)
type(MOM_domain_type), intent(in) :: MD_in !< An existing MOM_domain
type(MOM_domain_type), pointer :: MOM_dom !< A pointer to a MOM_domain that will be
type(MOM_domain_type), target, intent(in) :: MD_in !< An existing MOM_domain
type(MOM_domain_type), pointer :: MOM_dom
!< A pointer to a MOM_domain that will be
!! allocated if it is unassociated, and will have data
!! copied from MD_in
integer, dimension(2), &
Expand Down Expand Up @@ -1619,8 +1625,12 @@ subroutine clone_MD_to_MD(MD_in, MOM_dom, min_halo, halo_size, symmetric, domain
MOM_dom%name = MD_in%name
endif

call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain, xextent=exni, yextent=exnj)
MOM_dom%turns = qturns
if (qturns /= 0) then
MOM_dom%domain_in => MD_in
endif

call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain, xextent=exni, yextent=exnj)
call clone_MD_to_d2D(MOM_dom, MOM_dom%mpp_domain_d2, domain_name=MOM_dom%name, coarsen=2)

end subroutine clone_MD_to_MD
Expand Down
Loading

0 comments on commit a316416

Please sign in to comment.