Skip to content

Commit c3da676

Browse files
committed
+Add optional conversion argument to register_field
Added the option to rescale variables as they are written out via MOM_io_file. These involved adding optional conversion arguments to register_field_infra and register_field_nc, which are then stored in a new element in the MOM_field type, and use the conversion factors to unscale variables before they are written in the ten write_field routines in MOM_io_file. The new optional arguments to register_field are used in MOM_create_file, taking their values from the vardesc types sent to this routine. This commit also alters modify_vardesc to store the value of the conversion optional argument in the conversion element of the vardesc type. Also modified query_vardesc so that the conversion factor is returned via the conversion optional argument. These steps had been intended when these optional arguments were first added, but for some reason they had not actually been used. The conversion values stored in a vardesc type are also now used in the register_diag_field call in ocean_register_diag. However, it does not appear that ocean_register_diag is actually used anymore, so it might be a candidate for deletion. All answers are bitwise identical, but there are new optional arguments to publicly visible routines.
1 parent e6e0870 commit c3da676

File tree

3 files changed

+113
-23
lines changed

3 files changed

+113
-23
lines changed

src/framework/MOM_diag_mediator.F90

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,7 @@ subroutine register_cell_measure(G, diag, Time)
972972
! Local variables
973973
integer :: id
974974
id = register_diag_field('ocean_model', 'volcello', diag%axesTL, &
975-
Time, 'Ocean grid-cell volume', 'm3', &
975+
Time, 'Ocean grid-cell volume', units='m3', conversion=1.0, &
976976
standard_name='ocean_volume', v_extensive=.true., &
977977
x_cell_method='sum', y_cell_method='sum')
978978
call diag_associate_volume_cell_measure(diag, id)
@@ -3153,10 +3153,13 @@ function ocean_register_diag(var_desc, G, diag_CS, day)
31533153
character(len=48) :: units ! A variable's units.
31543154
character(len=240) :: longname ! A variable's longname.
31553155
character(len=8) :: hor_grid, z_grid ! Variable grid info.
3156+
real :: conversion ! A multiplicative factor for unit conversions for output,
3157+
! as might be needed to convert from intensive to extensive
3158+
! or for dimensional consistency testing [various] or [a A-1 ~> 1]
31563159
type(axes_grp), pointer :: axes => NULL()
31573160

31583161
call query_vardesc(var_desc, units=units, longname=longname, hor_grid=hor_grid, &
3159-
z_grid=z_grid, caller="ocean_register_diag")
3162+
z_grid=z_grid, conversion=conversion, caller="ocean_register_diag")
31603163

31613164
! Use the hor_grid and z_grid components of vardesc to determine the
31623165
! desired axes to register the diagnostic field for.
@@ -3211,8 +3214,8 @@ function ocean_register_diag(var_desc, G, diag_CS, day)
32113214
"ocean_register_diag: unknown z_grid component "//trim(z_grid))
32123215
end select
32133216

3214-
ocean_register_diag = register_diag_field("ocean_model", trim(var_name), &
3215-
axes, day, trim(longname), trim(units), missing_value=-1.0e+34)
3217+
ocean_register_diag = register_diag_field("ocean_model", trim(var_name), axes, day, &
3218+
trim(longname), units=trim(units), conversion=conversion, missing_value=-1.0e+34)
32163219

32173220
end function ocean_register_diag
32183221

src/framework/MOM_io.F90

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,10 +555,10 @@ subroutine create_MOM_file(IO_handle, filename, vars, novars, fields, &
555555
pack = 1
556556
if (present(checksums)) then
557557
fields(k) = IO_handle%register_field(axes(1:numaxes), vars(k)%name, vars(k)%units, &
558-
vars(k)%longname, pack=pack, checksum=checksums(k,:))
558+
vars(k)%longname, pack=pack, checksum=checksums(k,:), conversion=vars(k)%conversion)
559559
else
560560
fields(k) = IO_handle%register_field(axes(1:numaxes), vars(k)%name, vars(k)%units, &
561-
vars(k)%longname, pack=pack)
561+
vars(k)%longname, pack=pack, conversion=vars(k)%conversion)
562562
endif
563563
enddo
564564

@@ -1880,6 +1880,8 @@ subroutine modify_vardesc(vd, name, units, longname, hor_grid, z_grid, t_grid, &
18801880
if (present(cmor_longname)) call safe_string_copy(cmor_longname, vd%cmor_longname, &
18811881
"vd%cmor_longname of "//trim(vd%name), cllr)
18821882

1883+
if (present(conversion)) vd%conversion = conversion
1884+
18831885
if (present(dim_names)) then
18841886
do n=1,min(5,size(dim_names)) ; if (len_trim(dim_names(n)) > 0) then
18851887
call safe_string_copy(dim_names(n), vd%dim_names(n), "vd%dim_names of "//trim(vd%name), cllr)
@@ -2084,6 +2086,9 @@ subroutine query_vardesc(vd, name, units, longname, hor_grid, z_grid, t_grid, &
20842086
"vd%cmor_units of "//trim(vd%name), cllr)
20852087
if (present(cmor_longname)) call safe_string_copy(vd%cmor_longname, cmor_longname, &
20862088
"vd%cmor_longname of "//trim(vd%name), cllr)
2089+
2090+
if (present(conversion)) conversion = vd%conversion
2091+
20872092
if (present(position)) then
20882093
position = vd%position
20892094
if (position == -1) position = position_from_horgrid(vd%hor_grid)

src/framework/MOM_io_file.F90

Lines changed: 99 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ module MOM_io_file
128128
type :: MOM_field
129129
character(len=:), allocatable :: label
130130
!< Identifier for the field in the handle's list
131+
real :: conversion
132+
!< A factor to use to rescale the field before output [a A-1 ~> 1]
131133
end type MOM_field
132134

133135

@@ -454,7 +456,7 @@ end function i_register_axis
454456

455457
!> Interface to register a field to a netCDF file
456458
function i_register_field(handle, axes, label, units, longname, &
457-
pack, standard_name, checksum) result(field)
459+
pack, standard_name, checksum, conversion) result(field)
458460
import :: MOM_file, MOM_axis, MOM_field, int64
459461
class(MOM_file), intent(inout) :: handle
460462
!< Handle for a file that is open for writing
@@ -473,6 +475,8 @@ function i_register_field(handle, axes, label, units, longname, &
473475
!< The standard (e.g., CMOR) name for this variable
474476
integer(kind=int64), dimension(:), optional, intent(in) :: checksum
475477
!< Checksum values that can be used to verify reads.
478+
real, optional, intent(in) :: conversion
479+
!< A factor to use to rescale the field before output [a A-1 ~> 1]
476480
type(MOM_field) :: field
477481
!< IO handle for field in MOM_file
478482
end function i_register_field
@@ -1011,7 +1015,7 @@ end function register_axis_infra
10111015

10121016
!> Register a field to the MOM framework file
10131017
function register_field_infra(handle, axes, label, units, longname, pack, &
1014-
standard_name, checksum) result(field)
1018+
standard_name, checksum, conversion) result(field)
10151019
class(MOM_infra_file), intent(inout) :: handle
10161020
!< Handle for a file that is open for writing
10171021
type(MOM_axis), dimension(:), intent(in) :: axes
@@ -1029,6 +1033,8 @@ function register_field_infra(handle, axes, label, units, longname, pack, &
10291033
!< The standard (e.g., CMOR) name for this variable
10301034
integer(kind=int64), dimension(:), optional, intent(in) :: checksum
10311035
!< Checksum values that can be used to verify reads.
1036+
real, optional, intent(in) :: conversion
1037+
!< A factor to use to rescale the field before output [a A-1 ~> 1]
10321038
type(MOM_field) :: field
10331039
!< The field type where this information is stored
10341040

@@ -1047,6 +1053,7 @@ function register_field_infra(handle, axes, label, units, longname, pack, &
10471053

10481054
call handle%fields%append(field_infra, label)
10491055
field%label = label
1056+
field%conversion = 1.0 ; if (present(conversion)) field%conversion = conversion
10501057
end function register_field_infra
10511058

10521059

@@ -1069,10 +1076,19 @@ subroutine write_field_4d_infra(handle, field_md, MOM_domain, field, tstamp, &
10691076
!< Missing data fill value
10701077

10711078
type(fieldtype) :: field_infra
1079+
real, allocatable :: unscaled_field(:,:,:,:) ! An unscaled version of field for output [a]
10721080

10731081
field_infra = handle%fields%get(field_md%label)
1074-
call write_field(handle%handle_infra, field_infra, MOM_domain, field, &
1075-
tstamp=tstamp, tile_count=tile_count, fill_value=fill_value)
1082+
if (field_md%conversion == 1.0) then
1083+
call write_field(handle%handle_infra, field_infra, MOM_domain, field, &
1084+
tstamp=tstamp, tile_count=tile_count, fill_value=fill_value)
1085+
else
1086+
allocate(unscaled_field, source=field)
1087+
unscaled_field(:,:,:,:) = field_md%conversion * field(:,:,:,:)
1088+
call write_field(handle%handle_infra, field_infra, MOM_domain, unscaled_field, &
1089+
tstamp=tstamp, tile_count=tile_count, fill_value=fill_value)
1090+
deallocate(unscaled_field)
1091+
endif
10761092
end subroutine write_field_4d_infra
10771093

10781094

@@ -1086,7 +1102,7 @@ subroutine write_field_3d_infra(handle, field_md, MOM_domain, field, tstamp, &
10861102
type(MOM_domain_type), intent(in) :: MOM_domain
10871103
!< The MOM_Domain that describes the decomposition
10881104
real, intent(inout) :: field(:,:,:)
1089-
!< Field to write
1105+
!< Field to write, perhaps in arbitrary rescaled units [A ~> a]
10901106
real, optional, intent(in) :: tstamp
10911107
!< Model time of this field
10921108
integer, optional, intent(in) :: tile_count
@@ -1095,10 +1111,20 @@ subroutine write_field_3d_infra(handle, field_md, MOM_domain, field, tstamp, &
10951111
!< Missing data fill value
10961112

10971113
type(fieldtype) :: field_infra
1114+
real, allocatable :: unscaled_field(:,:,:) ! An unscaled version of field for output [a]
10981115

10991116
field_infra = handle%fields%get(field_md%label)
1100-
call write_field(handle%handle_infra, field_infra, MOM_domain, field, &
1101-
tstamp=tstamp, tile_count=tile_count, fill_value=fill_value)
1117+
if (field_md%conversion == 1.0) then
1118+
call write_field(handle%handle_infra, field_infra, MOM_domain, field, &
1119+
tstamp=tstamp, tile_count=tile_count, fill_value=fill_value)
1120+
else
1121+
allocate(unscaled_field, source=field)
1122+
unscaled_field(:,:,:) = field_md%conversion * field(:,:,:)
1123+
call write_field(handle%handle_infra, field_infra, MOM_domain, unscaled_field, &
1124+
tstamp=tstamp, tile_count=tile_count, fill_value=fill_value)
1125+
deallocate(unscaled_field)
1126+
endif
1127+
11021128
end subroutine write_field_3d_infra
11031129

11041130

@@ -1121,10 +1147,19 @@ subroutine write_field_2d_infra(handle, field_md, MOM_domain, field, tstamp, &
11211147
!< Missing data fill value
11221148

11231149
type(fieldtype) :: field_infra
1150+
real, allocatable :: unscaled_field(:,:) ! An unscaled version of field for output [a]
11241151

11251152
field_infra = handle%fields%get(field_md%label)
1126-
call write_field(handle%handle_infra, field_infra, MOM_domain, field, &
1127-
tstamp=tstamp, tile_count=tile_count, fill_value=fill_value)
1153+
if (field_md%conversion == 1.0) then
1154+
call write_field(handle%handle_infra, field_infra, MOM_domain, field, &
1155+
tstamp=tstamp, tile_count=tile_count, fill_value=fill_value)
1156+
else
1157+
allocate(unscaled_field, source=field)
1158+
unscaled_field(:,:) = field_md%conversion * field(:,:)
1159+
call write_field(handle%handle_infra, field_infra, MOM_domain, unscaled_field, &
1160+
tstamp=tstamp, tile_count=tile_count, fill_value=fill_value)
1161+
deallocate(unscaled_field)
1162+
endif
11281163
end subroutine write_field_2d_infra
11291164

11301165

@@ -1140,9 +1175,17 @@ subroutine write_field_1d_infra(handle, field_md, field, tstamp)
11401175
!< Model time of this field
11411176

11421177
type(fieldtype) :: field_infra
1178+
real, allocatable :: unscaled_field(:) ! An unscaled version of field for output [a]
11431179

11441180
field_infra = handle%fields%get(field_md%label)
1145-
call write_field(handle%handle_infra, field_infra, field, tstamp=tstamp)
1181+
if (field_md%conversion == 1.0) then
1182+
call write_field(handle%handle_infra, field_infra, field, tstamp=tstamp)
1183+
else
1184+
allocate(unscaled_field, source=field)
1185+
unscaled_field(:) = field_md%conversion * field(:)
1186+
call write_field(handle%handle_infra, field_infra, unscaled_field, tstamp=tstamp)
1187+
deallocate(unscaled_field)
1188+
endif
11461189
end subroutine write_field_1d_infra
11471190

11481191

@@ -1158,9 +1201,11 @@ subroutine write_field_0d_infra(handle, field_md, field, tstamp)
11581201
!< Model time of this field
11591202

11601203
type(fieldtype) :: field_infra
1204+
real :: unscaled_field ! An unscaled version of field for output [a]
11611205

11621206
field_infra = handle%fields%get(field_md%label)
1163-
call write_field(handle%handle_infra, field_infra, field, tstamp=tstamp)
1207+
unscaled_field = field_md%conversion*field
1208+
call write_field(handle%handle_infra, field_infra, unscaled_field, tstamp=tstamp)
11641209
end subroutine write_field_0d_infra
11651210

11661211

@@ -1403,7 +1448,7 @@ end function register_axis_nc
14031448

14041449
!> Register a field to the MOM netcdf file
14051450
function register_field_nc(handle, axes, label, units, longname, pack, &
1406-
standard_name, checksum) result(field)
1451+
standard_name, checksum, conversion) result(field)
14071452
class(MOM_netcdf_file), intent(inout) :: handle
14081453
!< Handle for a file that is open for writing
14091454
type(MOM_axis), intent(in) :: axes(:)
@@ -1421,6 +1466,8 @@ function register_field_nc(handle, axes, label, units, longname, pack, &
14211466
!< The standard (e.g., CMOR) name for this variable
14221467
integer(kind=int64), dimension(:), optional, intent(in) :: checksum
14231468
!< Checksum values that can be used to verify reads.
1469+
real, optional, intent(in) :: conversion
1470+
!< A factor to use to rescale the field before output [a A-1 ~> 1]
14241471
type(MOM_field) :: field
14251472

14261473
type(netcdf_field) :: field_nc
@@ -1438,6 +1485,7 @@ function register_field_nc(handle, axes, label, units, longname, pack, &
14381485
call handle%fields%append(field_nc, label)
14391486
endif
14401487
field%label = label
1488+
field%conversion = 1.0 ; if (present(conversion)) field%conversion = conversion
14411489
end function register_field_nc
14421490

14431491

@@ -1475,11 +1523,19 @@ subroutine write_field_4d_nc(handle, field_md, MOM_domain, field, tstamp, &
14751523
!< Missing data fill value
14761524

14771525
type(netcdf_field) :: field_nc
1526+
real, allocatable :: unscaled_field(:,:,:,:) ! An unscaled version of field for output [a]
14781527

14791528
if (.not. is_root_PE()) return
14801529

14811530
field_nc = handle%fields%get(field_md%label)
1482-
call write_netcdf_field(handle%handle_nc, field_nc, field, time=tstamp)
1531+
if (field_md%conversion == 1.0) then
1532+
call write_netcdf_field(handle%handle_nc, field_nc, field, time=tstamp)
1533+
else
1534+
allocate(unscaled_field, source=field)
1535+
unscaled_field(:,:,:,:) = field_md%conversion * field(:,:,:,:)
1536+
call write_netcdf_field(handle%handle_nc, field_nc, unscaled_field, time=tstamp)
1537+
deallocate(unscaled_field)
1538+
endif
14831539
end subroutine write_field_4d_nc
14841540

14851541

@@ -1502,11 +1558,19 @@ subroutine write_field_3d_nc(handle, field_md, MOM_domain, field, tstamp, &
15021558
!< Missing data fill value
15031559

15041560
type(netcdf_field) :: field_nc
1561+
real, allocatable :: unscaled_field(:,:,:) ! An unscaled version of field for output [a]
15051562

15061563
if (.not. is_root_PE()) return
15071564

15081565
field_nc = handle%fields%get(field_md%label)
1509-
call write_netcdf_field(handle%handle_nc, field_nc, field, time=tstamp)
1566+
if (field_md%conversion == 1.0) then
1567+
call write_netcdf_field(handle%handle_nc, field_nc, field, time=tstamp)
1568+
else
1569+
allocate(unscaled_field, source=field)
1570+
unscaled_field(:,:,:) = field_md%conversion * field(:,:,:)
1571+
call write_netcdf_field(handle%handle_nc, field_nc, unscaled_field, time=tstamp)
1572+
deallocate(unscaled_field)
1573+
endif
15101574
end subroutine write_field_3d_nc
15111575

15121576

@@ -1529,11 +1593,19 @@ subroutine write_field_2d_nc(handle, field_md, MOM_domain, field, tstamp, &
15291593
!< Missing data fill value
15301594

15311595
type(netcdf_field) :: field_nc
1596+
real, allocatable :: unscaled_field(:,:) ! An unscaled version of field for output [a]
15321597

15331598
if (.not. is_root_PE()) return
15341599

15351600
field_nc = handle%fields%get(field_md%label)
1536-
call write_netcdf_field(handle%handle_nc, field_nc, field, time=tstamp)
1601+
if (field_md%conversion == 1.0) then
1602+
call write_netcdf_field(handle%handle_nc, field_nc, field, time=tstamp)
1603+
else
1604+
allocate(unscaled_field, source=field)
1605+
unscaled_field(:,:) = field_md%conversion * field(:,:)
1606+
call write_netcdf_field(handle%handle_nc, field_nc, unscaled_field, time=tstamp)
1607+
deallocate(unscaled_field)
1608+
endif
15371609
end subroutine write_field_2d_nc
15381610

15391611

@@ -1549,11 +1621,19 @@ subroutine write_field_1d_nc(handle, field_md, field, tstamp)
15491621
!< Model time of this field
15501622

15511623
type(netcdf_field) :: field_nc
1624+
real, allocatable :: unscaled_field(:) ! An unscaled version of field for output [a]
15521625

15531626
if (.not. is_root_PE()) return
15541627

15551628
field_nc = handle%fields%get(field_md%label)
1556-
call write_netcdf_field(handle%handle_nc, field_nc, field, time=tstamp)
1629+
if (field_md%conversion == 1.0) then
1630+
call write_netcdf_field(handle%handle_nc, field_nc, field, time=tstamp)
1631+
else
1632+
allocate(unscaled_field, source=field)
1633+
unscaled_field(:) = field_md%conversion * field(:)
1634+
call write_netcdf_field(handle%handle_nc, field_nc, unscaled_field, time=tstamp)
1635+
deallocate(unscaled_field)
1636+
endif
15571637
end subroutine write_field_1d_nc
15581638

15591639

@@ -1569,11 +1649,13 @@ subroutine write_field_0d_nc(handle, field_md, field, tstamp)
15691649
!< Model time of this field
15701650

15711651
type(netcdf_field) :: field_nc
1652+
real :: unscaled_field ! An unscaled version of field for output [a]
15721653

15731654
if (.not. is_root_PE()) return
15741655

15751656
field_nc = handle%fields%get(field_md%label)
1576-
call write_netcdf_field(handle%handle_nc, field_nc, field, time=tstamp)
1657+
unscaled_field = field_md%conversion * field
1658+
call write_netcdf_field(handle%handle_nc, field_nc, unscaled_field, time=tstamp)
15771659
end subroutine write_field_0d_nc
15781660

15791661

0 commit comments

Comments
 (0)