Skip to content

Commit 3179a41

Browse files
committed
Merge branch 'zhan391/precfactor' (PR #7361)
Dynamical adjustment on freshwater fluxes balance for E3SM runs This pull request introduces a new module and function in the MPAS-Ocean (MPAS-O) model to compute and apply a scaling factor on precipitation fluxes. The goal of this feature is to help maintain freshwater balance in ocean-only simulations by mitigating the spurious linear trend observed in sea surface height (SSH) over time. The updates specifically target uncoupled ocean configurations, including: * G-case: ocean + sea ice with data atmosphere * GP- or J-case: land + river + ocean + sea ice with data atmosphere These configurations do not include a dynamically coupled atmosphere, and thus lack the feedback mechanisms necessary for naturally maintaining freshwater balance. This PR provides a workaround by dynamically adjusting the precipitation flux. [NML] [BFB] - stealth feature, off by default
2 parents 9c886dd + 3bac82f commit 3179a41

File tree

16 files changed

+862
-35
lines changed

16 files changed

+862
-35
lines changed

cime_config/tests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@
315315
"SMS_P480_Ld5.TL319_IcoswISC30E3r5.GMPAS-JRA1p5-DIB-PISMF-TMIX.mpaso-jra_1958",
316316
"PET_P480_Ld2.TL319_IcoswISC30E3r5.GMPAS-JRA1p5-DIB-PISMF-DSGR.mpaso-jra_1958",
317317
"PET_P480_Ld2.TL319_IcoswISC30E3r5.GMPAS-JRA1p5-DIB-PISMF-DSGR.mpaso-freshwater_tracers_jra_1958",
318+
"SMS_P480_Ld5.TL319_IcoswISC30E3r5.GMPAS-JRA1p5.mpaso-precip_scaling_jra_1958",
318319
)
319320
},
320321

components/mpas-ocean/bld/build-namelist

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,17 @@ add_default($nl, 'config_use_sgr_opt_salt_prescribed');
728728
add_default($nl, 'config_sgr_temperature_prescribed');
729729
add_default($nl, 'config_sgr_salinity_prescribed');
730730

731+
##################################
732+
# Namelist group: precip_scaling #
733+
##################################
734+
735+
add_default($nl, 'config_use_precip_scaling');
736+
add_default($nl, 'config_precip_scaling_mode');
737+
add_default($nl, 'config_precip_scaling_initial_factor');
738+
add_default($nl, 'config_precip_scaling_constant_factor');
739+
add_default($nl, 'config_precip_scaling_history_years');
740+
add_default($nl, 'config_precip_scaling_write_to_logfile');
741+
731742
############################
732743
# Namelist group: coupling #
733744
############################
@@ -1892,6 +1903,7 @@ my @groups = qw(run_modes
18921903
wave_coupling
18931904
gotm
18941905
forcing
1906+
precip_scaling
18951907
coupling
18961908
shortwaveradiation
18971909
self_attraction_loading

components/mpas-ocean/bld/build-namelist-group-list

100644100755
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ my @groups = qw(run_modes
1515
wave_coupling
1616
gotm
1717
forcing
18+
precip_scaling
1819
coupling
1920
shortwaveradiation
2021
self_attraction_loading

components/mpas-ocean/bld/build-namelist-section

100644100755
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,17 @@ add_default($nl, 'config_use_sgr_opt_salt_prescribed');
234234
add_default($nl, 'config_sgr_temperature_prescribed');
235235
add_default($nl, 'config_sgr_salinity_prescribed');
236236

237+
##################################
238+
# Namelist group: precip_scaling #
239+
##################################
240+
241+
add_default($nl, 'config_use_precip_scaling');
242+
add_default($nl, 'config_precip_scaling_mode');
243+
add_default($nl, 'config_precip_scaling_initial_factor');
244+
add_default($nl, 'config_precip_scaling_constant_factor');
245+
add_default($nl, 'config_precip_scaling_history_years');
246+
add_default($nl, 'config_precip_scaling_write_to_logfile');
247+
237248
############################
238249
# Namelist group: coupling #
239250
############################

components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,14 @@
372372
<config_sgr_temperature_prescribed>0.0</config_sgr_temperature_prescribed>
373373
<config_sgr_salinity_prescribed>0.0</config_sgr_salinity_prescribed>
374374

375+
<!-- precip_scaling -->
376+
<config_use_precip_scaling>.false.</config_use_precip_scaling>
377+
<config_precip_scaling_mode>'off'</config_precip_scaling_mode>
378+
<config_precip_scaling_initial_factor>1.0</config_precip_scaling_initial_factor>
379+
<config_precip_scaling_constant_factor>1.0</config_precip_scaling_constant_factor>
380+
<config_precip_scaling_history_years>1</config_precip_scaling_history_years>
381+
<config_precip_scaling_write_to_logfile>.false.</config_precip_scaling_write_to_logfile>
382+
375383
<!-- coupling -->
376384
<config_remove_ais_river_runoff>.false.</config_remove_ais_river_runoff>
377385
<config_remove_ais_ice_runoff>.false.</config_remove_ais_ice_runoff>

components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,57 @@ Default: Defined in namelist_defaults.xml
12611261
</entry>
12621262

12631263

1264+
<!-- precip_scaling -->
1265+
1266+
<entry id="config_use_precip_scaling" type="logical"
1267+
category="precip_scaling" group="precip_scaling">
1268+
If true, precipitation fluxes will be scalled to ensure freshwater balance in FOSI runs referring to forced ocean-sea ice simulation where ocean model is driven by a data atmosphere with prescribed precipitation (rain + snow) fluxes.
1269+
1270+
Valid values: .true. or .false.
1271+
Default: Defined in namelist_defaults.xml
1272+
</entry>
1273+
1274+
<entry id="config_precip_scaling_mode" type="char*1024"
1275+
category="precip_scaling" group="precip_scaling">
1276+
Option for scaling precipitation fluxes to ensure freshwater balance in FOSI runs. config_precip_scaling_mode='constant' uses a prescribed constant factor applied to precipitation fluxes. config_precip_scaling_mode='time-dependent' enables the dynamical caclulation of scaling factors using annual and global mean precipitation (rain + snow) and sea surface height changes over one-year or multi-year period.
1277+
1278+
Valid values: 'off', 'constant' or 'time-dependent'
1279+
Default: Defined in namelist_defaults.xml
1280+
</entry>
1281+
1282+
<entry id="config_precip_scaling_initial_factor" type="real"
1283+
category="precip_scaling" group="precip_scaling">
1284+
Initial guess scaling factor on precipitation fluxes in FOSI runs when config_precip_scaling_mode = 'time-dependent'.
1285+
1286+
Valid values: Non-negative number between 0 and 1.0. Default value of 1.0 means no scaling.
1287+
Default: Defined in namelist_defaults.xml
1288+
</entry>
1289+
1290+
<entry id="config_precip_scaling_constant_factor" type="real"
1291+
category="precip_scaling" group="precip_scaling">
1292+
Prescribed constant scaling factor on precipitation fluxes in FOSI runs when config_precip_scaling_mode = 'constant'.
1293+
1294+
Valid values: Non-negative number between 0 and 1.0. Default value of 1.0 means no scaling.
1295+
Default: Defined in namelist_defaults.xml
1296+
</entry>
1297+
1298+
<entry id="config_precip_scaling_history_years" type="integer"
1299+
category="precip_scaling" group="precip_scaling">
1300+
The number of years over which scaling factor on precipitation fluxes is computed in FOSI runs. Default value is 1 year.
1301+
1302+
Valid values: Positive integer greater than or equal to 1.
1303+
Default: Defined in namelist_defaults.xml
1304+
</entry>
1305+
1306+
<entry id="config_precip_scaling_write_to_logfile" type="logical"
1307+
category="precip_scaling" group="precip_scaling">
1308+
Logical flag indicating whether information for precipitation flux scaling in FOSI runs will be written to the log file.
1309+
1310+
Valid values: .true. or .false.
1311+
Default: Defined in namelist_defaults.xml
1312+
</entry>
1313+
1314+
12641315
<!-- coupling -->
12651316

12661317
<entry id="config_remove_ais_river_runoff" type="logical"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
This testdef is used to test a stealth feature in mpaso introduced by
2+
PR #7361. It simplies changes one mpaso namelist variable,
3+
config_use_precip_scaling
4+
from its default value of .false. to .true.. It also sets associated
5+
variables,
6+
config_precip_scaling_mode
7+
config_precip_scaling_constant_factor
8+
for testing. This particular testdef also limmits the required JRA
9+
forcing data to a single year to reduce the number of files needed for
10+
testing.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
./xmlchange DATM_CLMNCEP_YR_START=1958
2+
./xmlchange DATM_CLMNCEP_YR_END=1958
3+
./xmlchange DROF_STRM_YR_START=1958
4+
./xmlchange DROF_STRM_YR_END=1958
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
config_use_precip_scaling = .true.
2+
config_precip_scaling_mode = 'constant'
3+
config_precip_scaling_constant_factor = 0.95

components/mpas-ocean/driver/ocn_comp_mct.F

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ module ocn_comp_mct
7070
use ocn_submesoscale_eddies
7171
use ocn_eddy_parameterization_helpers
7272
use ocn_scaled_dismf
73+
use ocn_scaled_sfwf
7374
!
7475
! !PUBLIC MEMBER FUNCTIONS:
7576
implicit none
@@ -121,6 +122,8 @@ module ocn_comp_mct
121122
integer :: itimestep, & ! time step number for MPAS
122123
ocn_cpl_dt ! length of coupling interval in seconds - set by coupler/ESMF
123124

125+
real (kind=RKIND) :: precFactor
126+
124127
!=======================================================================
125128

126129
contains
@@ -235,6 +238,12 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename )!{{{
235238
real (kind=RKIND), pointer :: &
236239
runningMeanRemovedIceRunoff ! the area integrated, running mean of removed ice runoff from the ocean
237240

241+
! freshwater balance adjustment
242+
logical, pointer :: config_use_precip_scaling
243+
character (len=StrKIND), pointer :: config_precip_scaling_mode
244+
real (kind=RKIND), pointer :: SFWFScalingFactor ! scaling factor on freshwater fluxes
245+
real(kind=RKIND), pointer :: scalingFactor
246+
238247
#ifdef HAVE_MOAB
239248
character*100 outfile, wopts
240249
integer :: ierrmb, numco, tagtype, tagindex, ent_type
@@ -833,6 +842,25 @@ end subroutine xml_stream_get_attributes
833842

834843
! initialize scaled data ice-shelf melt fluxes based on remove ice runoff
835844
call ocn_init_scaled_dismf(domain)
845+
846+
! Initialize the precipitation scaling scheme
847+
call ocn_scaled_sfwf_init(domain)
848+
! Ensure a valid first guess at the initial time
849+
call mpas_pool_get_config(domain % configs, 'config_use_precip_scaling', config_use_precip_scaling)
850+
if (config_use_precip_scaling) then
851+
call mpas_pool_get_config(domain % configs, 'config_precip_scaling_mode', config_precip_scaling_mode)
852+
! independent of space so should be no need to loop over blocks
853+
block_ptr => domain % blocklist
854+
call mpas_pool_get_subpool(block_ptr % structs, 'forcing', forcingPool)
855+
call mpas_pool_get_array(forcingPool, "SFWFScalingFactor", SFWFScalingFactor)
856+
if (trim(config_precip_scaling_mode) == 'time-dependent') then
857+
call mpas_pool_get_config(domain % configs, 'config_precip_scaling_initial_factor', scalingFactor)
858+
else if (trim(config_precip_scaling_mode) == 'constant') then
859+
call mpas_pool_get_config(domain % configs, 'config_precip_scaling_constant_factor', scalingFactor)
860+
end if
861+
! Broadcast the scalar to the field
862+
SFWFScalingFactor = scalingFactor
863+
end if
836864
end if
837865

838866
!-----------------------------------------------------------------------
@@ -881,6 +909,10 @@ end subroutine xml_stream_get_attributes
881909

882910
! initialize scaled data ice-shelf melt fluxes based on remove ice runoff
883911
call ocn_init_scaled_dismf(domain)
912+
913+
! initialize scaled data freshwater fluxes based on water balance relationship
914+
call ocn_scaled_sfwf_init(domain)
915+
884916
end if
885917

886918
call t_stopf ('mpaso_mct_init')
@@ -915,6 +947,16 @@ end subroutine xml_stream_get_attributes
915947
call init_glc_z_levels(domain, ierr_local)
916948
ierr = ior(ierr, ierr_local)
917949

950+
!configuration for freshwater conservation
951+
call mpas_pool_get_config(domain % configs, 'config_use_precip_scaling', config_use_precip_scaling)
952+
if (config_use_precip_scaling) then
953+
! independent of space so should be no need to loop over blocks
954+
block_ptr => domain % blocklist
955+
call mpas_pool_get_subpool(block_ptr % structs, 'forcing', forcingPool)
956+
call mpas_pool_get_array(forcingPool, "SFWFScalingFactor", SFWFScalingFactor)
957+
call seq_infodata_PutData(infodata, precip_fact=SFWFScalingFactor)
958+
end if
959+
918960
!-----------------------------------------------------------------------
919961
!
920962
! get initial state from driver
@@ -1038,6 +1080,10 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o)!{{{
10381080
real (kind=RKIND), pointer :: &
10391081
runningMeanRemovedIceRunoff ! the area integrated, running mean of removed ice runoff from the ocean
10401082
1083+
! freshwater balance adjustment
1084+
logical, pointer :: config_use_precip_scaling
1085+
real (kind=RKIND), pointer :: SFWFScalingFactor ! scaling factor on freshwater fluxes
1086+
10411087
#ifdef HAVE_MOAB
10421088
#ifdef MOABCOMP
10431089
real(r8) :: difference
@@ -1286,6 +1332,9 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o)!{{{
12861332
call mpas_log_write(' Validating ocean state')
12871333
endif
12881334

1335+
! update scalling factors for freshwater fluxes
1336+
call ocn_update_scaling_factor(domain, timeLevel=1)
1337+
12891338
call ocn_validate_state(domain, timeLevel=1)
12901339
if (debugOn) call mpas_log_write(' Completed validating ocean state')
12911340

@@ -1356,6 +1405,16 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o)!{{{
13561405
call seq_infodata_PutData(infodata, rmean_rmv_ice_runoff=runningMeanRemovedIceRunoff)
13571406
end if
13581407

1408+
!configuration for freshwater conservation
1409+
call mpas_pool_get_config(domain % configs, 'config_use_precip_scaling', config_use_precip_scaling)
1410+
if (config_use_precip_scaling) then
1411+
! independent of space so should be no need to loop over blocks
1412+
block_ptr => domain % blocklist
1413+
call mpas_pool_get_subpool(block_ptr % structs, 'forcing', forcingPool)
1414+
call mpas_pool_get_array(forcingPool, "SFWFScalingFactor", SFWFScalingFactor)
1415+
call seq_infodata_PutData(infodata, precip_fact=SFWFScalingFactor)
1416+
end if
1417+
13591418
! Reset I/O logs
13601419
call shr_file_setLogUnit (shrlogunit)
13611420
call shr_file_setLogLevel(shrloglev)
@@ -1980,7 +2039,11 @@ subroutine ocn_import_mct(x2o_o, errorCode)!{{{
19802039
ecosysSeaIceCoupling, &
19812040
DMSSeaIceCoupling, &
19822041
MacroMoleculesSeaIceCoupling, &
1983-
CFCAuxiliary
2042+
CFCAuxiliary, &
2043+
conservationCheckEnergyAMPool, &
2044+
conservationCheckMassAMPool, &
2045+
conservationCheckSaltAMPool, &
2046+
conservationCheckCarbonAMPool
19842047

19852048
integer, pointer :: nCellsSolve
19862049

@@ -2092,6 +2155,9 @@ subroutine ocn_import_mct(x2o_o, errorCode)!{{{
20922155

20932156
real (kind=RKIND) :: riverFactor
20942157

2158+
! freshwater balance adjustment
2159+
logical, pointer :: config_use_precip_scaling
2160+
20952161
!-----------------------------------------------------------------------
20962162
!
20972163
! zero out padded cells
@@ -2123,6 +2189,14 @@ subroutine ocn_import_mct(x2o_o, errorCode)!{{{
21232189
call mpas_pool_get_config(domain % configs, 'config_remove_ais_ice_runoff', config_remove_ais_ice_runoff)
21242190
call mpas_pool_get_config(domain % configs, 'config_cvmix_kpp_use_theory_wave', config_cvmix_kpp_use_theory_wave)
21252191

2192+
precFactor = 1.0_RKIND ! Default to no scaling
2193+
!configuration for freshwater balance constrains
2194+
call mpas_pool_get_config(domain % configs, 'config_use_precip_scaling', config_use_precip_scaling)
2195+
if (config_use_precip_scaling) then
2196+
!extract scaling factors
2197+
call seq_infodata_GetData(infodata, precip_fact=precFactor)
2198+
end if
2199+
21262200
n = 0
21272201
removedRiverRunoffFluxThisProc = 0.0_RKIND
21282202
removedIceRunoffFluxThisProc = 0.0_RKIND
@@ -2379,7 +2453,7 @@ subroutine ocn_import_mct(x2o_o, errorCode)!{{{
23792453
end if
23802454

23812455
if ( rainFluxField % isActive ) then
2382-
rainFlux(i) = x2o_o % rAttr(index_x2o_Faxa_rain, n)
2456+
rainFlux(i) = x2o_o % rAttr(index_x2o_Faxa_rain, n) * precFactor
23832457
end if
23842458
if ( atmosphericPressureField % isActive ) then
23852459
atmosphericPressure(i) = x2o_o % rAttr(index_x2o_Sa_pslv, n)
@@ -3955,7 +4029,7 @@ subroutine ocn_import_moab(Eclock, errorCode)!{{{
39554029
icebergHeatFlux(i) = x2o_om(n, index_x2o_Fioi_bergh)
39564030
end if
39574031
if ( snowFluxField % isActive ) then
3958-
snowFlux(i) = x2o_om(n, index_x2o_Faxa_snow)
4032+
snowFlux(i) = x2o_om(n, index_x2o_Faxa_snow) * precFactor
39594033
end if
39604034
if ( seaIceFreshWaterFluxField % isActive ) then
39614035
seaIceFreshWaterFlux(i) = x2o_om(n, index_x2o_Fioi_meltw)

0 commit comments

Comments
 (0)