@@ -128,6 +128,8 @@ module MOM_io_file
128128type :: 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]
131133end 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
10131017function 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
10501057end 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
10761092end 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+
11021128end 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
11281163end 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
11461189end 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)
11641209end 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
14051450function 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
14411489end 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
14831539end 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
15101574end 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
15371609end 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
15571637end 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)
15771659end subroutine write_field_0d_nc
15781660
15791661
0 commit comments