diff --git a/cime_config/tests.py b/cime_config/tests.py index 47096ada4b83..6e3b4aa35d7d 100644 --- a/cime_config/tests.py +++ b/cime_config/tests.py @@ -269,6 +269,7 @@ "SMS_D_Ld1.T62_oQU240.GMPAS-IAF.mpaso-harmonic_mean_drag", "SMS_D_Ld1.T62_oQU240.GMPAS-IAF.mpaso-upwind_advection", "ERS_Ld5_D.T62_oQU240.GMPAS-IAF.mpaso-conservation_check", + "ERS_Ld5_PS.ne30pg2_r05_IcoswISC30E3r5.CRYO1850-DISMF.mpaso-scaled_dib_dismf", ) }, diff --git a/components/mpas-ocean/bld/build-namelist b/components/mpas-ocean/bld/build-namelist index e38ba0772288..43a57037902c 100755 --- a/components/mpas-ocean/bld/build-namelist +++ b/components/mpas-ocean/bld/build-namelist @@ -740,6 +740,8 @@ if (($OCN_ISMF ne 'none') && ($OCN_FORCING ne 'active_atm')) { } else { add_default($nl, 'config_remove_ais_river_runoff', 'val'=>".false."); } +add_default($nl, 'config_scale_dismf_by_removed_ice_runoff'); +add_default($nl, 'config_ais_ice_runoff_history_days'); ###################################### # Namelist group: shortwaveRadiation # @@ -789,7 +791,6 @@ add_default($nl, 'config_self_attraction_and_loading_beta'); add_default($nl, 'config_use_frazil_ice_formation'); add_default($nl, 'config_frazil_in_open_ocean'); -add_default($nl, 'config_frazil_under_land_ice'); add_default($nl, 'config_frazil_heat_of_fusion'); add_default($nl, 'config_frazil_ice_density'); add_default($nl, 'config_frazil_fractional_thickness_limit'); @@ -799,18 +800,32 @@ add_default($nl, 'config_frazil_sea_ice_reference_salinity'); add_default($nl, 'config_frazil_maximum_freezing_temperature'); add_default($nl, 'config_frazil_use_surface_pressure'); +if ($OCN_ISMF eq 'coupled') { + add_default($nl, 'config_frazil_under_land_ice', 'val'=>".true."); +} elsif ($OCN_ISMF eq 'internal') { + add_default($nl, 'config_frazil_under_land_ice', 'val'=>".true."); +} elsif ($OCN_ISMF eq 'data') { + add_default($nl, 'config_frazil_under_land_ice', 'val'=>".false."); +} else { + add_default($nl, 'config_frazil_under_land_ice'); +} + ################################### # Namelist group: land_ice_fluxes # ################################### if ($OCN_ISMF eq 'coupled') { add_default($nl, 'config_land_ice_flux_mode', 'val'=>"coupled"); + add_default($nl, 'config_frazil_under_land_ice', 'val'=>".true."); } elsif ($OCN_ISMF eq 'internal') { add_default($nl, 'config_land_ice_flux_mode', 'val'=>"standalone"); + add_default($nl, 'config_frazil_under_land_ice', 'val'=>".true."); } elsif ($OCN_ISMF eq 'data') { add_default($nl, 'config_land_ice_flux_mode', 'val'=>"data"); + add_default($nl, 'config_frazil_under_land_ice', 'val'=>".false."); } else { add_default($nl, 'config_land_ice_flux_mode'); + add_default($nl, 'config_frazil_under_land_ice'); } if ($OCN_TIDAL_MIXING eq 'true') { add_default($nl, 'config_land_ice_flux_tidal_Jourdain_alpha', 'val'=>"0.777"); diff --git a/components/mpas-ocean/bld/build-namelist-section b/components/mpas-ocean/bld/build-namelist-section index c5dad5d935a9..2c904e825d06 100644 --- a/components/mpas-ocean/bld/build-namelist-section +++ b/components/mpas-ocean/bld/build-namelist-section @@ -239,6 +239,8 @@ add_default($nl, 'config_sgr_salinity_prescribed'); add_default($nl, 'config_remove_ais_river_runoff'); add_default($nl, 'config_remove_ais_ice_runoff'); +add_default($nl, 'config_scale_dismf_by_removed_ice_runoff'); +add_default($nl, 'config_ais_ice_runoff_history_days'); ###################################### # Namelist group: shortwaveRadiation # diff --git a/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml b/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml index f1ab05d22075..277278772274 100644 --- a/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml +++ b/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml @@ -364,6 +364,8 @@ .false. .false. +.false. +731 'jerlov' @@ -401,7 +403,7 @@ .true. .true. -.true. +.false. 3.337e5 1000.0 0.1 diff --git a/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml b/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml index bea1e98d9de8..46bbfde1f873 100644 --- a/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml +++ b/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml @@ -1271,6 +1271,22 @@ Valid values: .true. or .false. Default: Defined in namelist_defaults.xml + +Whether to scale data ice-shelf melt fluxes by the running mean of removed ice runoff. + +Valid values: .true. or .false. +Default: Defined in namelist_defaults.xml + + + +The number of days over for which the history of removed AIS runoff is stored. The default is 731 days (2 years + 1 day). + +Valid values: Any positive integer +Default: Defined in namelist_defaults.xml + + diff --git a/components/mpas-ocean/cime_config/buildnml b/components/mpas-ocean/cime_config/buildnml index d45d94344fe7..778d268d5700 100755 --- a/components/mpas-ocean/cime_config/buildnml +++ b/components/mpas-ocean/cime_config/buildnml @@ -376,7 +376,7 @@ def buildnml(case, caseroot, compname): ic_prefix = 'mpaso.IcoswISC30E3r5.20231120+MARBL_ICfromOMIP_64levels' eco_forcing_file = 'ecoForcingSurfaceMonthly.IcoswISC30E3r5.20231215.nc' if ocn_ismf == 'data': - data_ismf_file = 'prescribed_ismf_paolo2023.IcoswISC30E3r5.20240227.nc' + data_ismf_file = 'prescribed_ismf_paolo2023.IcoswISC30E3r5.20240805.nc' if ocn_tidal_mixing == 'true': u_tidal_rms_file = 'velocityTidalRMS_CATS2008.IcoswISC30E3r5.20231120.nc' if ocn_sgr == 'data': @@ -417,7 +417,7 @@ def buildnml(case, caseroot, compname): ic_date = '20240829' ic_prefix = 'mpaso.SOwISC12to30E3r3.rstFromG-chrysalis' if ocn_ismf == 'data': - data_ismf_file = 'prescribed_ismf_paolo2023.SOwISC12to30E3r3.20240829.nc' + data_ismf_file = 'prescribed_ismf_paolo2023.SOwISC12to30E3r3.20241017.nc' #-------------------------------------------------------------------- @@ -1818,6 +1818,7 @@ def buildnml(case, caseroot, compname): lines.append(' packages="dataLandIceFluxesPKG">') lines.append(' ') lines.append(' ') + lines.append(' ') lines.append('') lines.append('') diff --git a/components/mpas-ocean/cime_config/config_component.xml b/components/mpas-ocean/cime_config/config_component.xml index 83b4501ee5e5..ee55bf415d92 100644 --- a/components/mpas-ocean/cime_config/config_component.xml +++ b/components/mpas-ocean/cime_config/config_component.xml @@ -107,6 +107,8 @@ constant none + none + none constant constant diagnostic diff --git a/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/scaled_dib_dismf/README b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/scaled_dib_dismf/README new file mode 100644 index 000000000000..f9f97d27de15 --- /dev/null +++ b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/scaled_dib_dismf/README @@ -0,0 +1,8 @@ +This testdef is used to test a stealth feature in mpaso and mpassi introduced +by PR #6696. It simply changes sets the following namelist option in mpaso +to true + config_scale_dismf_by_removed_ice_runoff +and the following namelist option in mpassi to true + config_scale_dib_by_removed_ice_runoff +These flags only makes sense to use in a B-case runs with data icebergs (DIB) +and data ice-shelf melt fluxes (DISMF). diff --git a/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/scaled_dib_dismf/user_nl_mpaso b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/scaled_dib_dismf/user_nl_mpaso new file mode 100644 index 000000000000..902d4418f5a0 --- /dev/null +++ b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/scaled_dib_dismf/user_nl_mpaso @@ -0,0 +1 @@ + config_scale_dismf_by_removed_ice_runoff = .true. diff --git a/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/scaled_dib_dismf/user_nl_mpassi b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/scaled_dib_dismf/user_nl_mpassi new file mode 100644 index 000000000000..8512001af932 --- /dev/null +++ b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/scaled_dib_dismf/user_nl_mpassi @@ -0,0 +1 @@ + config_scale_dib_by_removed_ice_runoff = .true. diff --git a/components/mpas-ocean/driver/ocn_comp_mct.F b/components/mpas-ocean/driver/ocn_comp_mct.F index d1b140563bb7..e4e9a4a68fc4 100644 --- a/components/mpas-ocean/driver/ocn_comp_mct.F +++ b/components/mpas-ocean/driver/ocn_comp_mct.F @@ -69,6 +69,7 @@ module ocn_comp_mct use ocn_config use ocn_submesoscale_eddies use ocn_eddy_parameterization_helpers + use ocn_scaled_dismf ! ! !PUBLIC MEMBER FUNCTIONS: implicit none @@ -214,6 +215,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename )!{{{ character(len=StrKIND) :: iotype logical :: streamsExists integer :: mesh_iotype + logical :: ocn_c2_glcshelf logical, pointer :: tempLogicalConfig character(len=StrKIND), pointer :: tempCharConfig @@ -222,11 +224,14 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename )!{{{ logical, pointer :: config_use_CFCTracers logical, pointer :: config_use_activeTracers_surface_restoring logical, pointer :: config_use_surface_salinity_monthly_restoring + logical, pointer :: config_scale_dismf_by_removed_ice_runoff character (len=StrKIND), pointer :: config_land_ice_flux_mode ! ssh coupling interval initialization integer, pointer :: index_avgZonalSSHGradient, index_avgMeridionalSSHGradient real (kind=RKIND), dimension(:,:), pointer :: avgSSHGradient + real (kind=RKIND), pointer :: & + runningMeanRemovedIceRunoff ! the area integrated, running mean of removed ice runoff from the ocean #ifdef HAVE_MOAB character*100 outfile, wopts @@ -815,6 +820,9 @@ end subroutine xml_stream_get_attributes call ocn_time_average_coupled_accumulate(statePool, forcingPool, 1) block_ptr => block_ptr % next end do + + ! initialize scaled data ice-shelf melt fluxes based on remove ice runoff + call ocn_init_scaled_dismf(domain) end if !----------------------------------------------------------------------- @@ -860,6 +868,9 @@ end subroutine xml_stream_get_attributes call ocn_time_average_coupled_accumulate(statePool, forcingPool, 1) block_ptr => block_ptr % next end do + + ! initialize scaled data ice-shelf melt fluxes based on remove ice runoff + call ocn_init_scaled_dismf(domain) end if call t_stopf ('mpaso_mct_init') @@ -869,14 +880,25 @@ end subroutine xml_stream_get_attributes trim(config_land_ice_flux_mode) == 'pressure_only' .or. & trim(config_land_ice_flux_mode) == 'data' .or. & trim(config_land_ice_flux_mode) == 'standalone' ) then - call seq_infodata_PutData( infodata, ocn_prognostic=.true., ocnrof_prognostic=.true., & - ocn_c2_glcshelf=.false.) + ocn_c2_glcshelf = .false. else if ( trim(config_land_ice_flux_mode) .eq. 'coupled' ) then - call seq_infodata_PutData( infodata, ocn_prognostic=.true., ocnrof_prognostic=.true., & - ocn_c2_glcshelf=.true.) + ocn_c2_glcshelf = .true. else call mpas_log_write('ERROR: unknown land_ice_flux_mode: ' // trim(config_land_ice_flux_mode), MPAS_LOG_CRIT) end if + call seq_infodata_PutData(infodata, ocn_prognostic=.true., ocnrof_prognostic=.true., & + ocn_c2_glcshelf=ocn_c2_glcshelf) + + call mpas_pool_get_config(domain % configs, 'config_scale_dismf_by_removed_ice_runoff', & + config_scale_dismf_by_removed_ice_runoff) + if (config_scale_dismf_by_removed_ice_runoff) then + ! independent of space so should be no need to loop over blocks + block_ptr => domain % blocklist + call mpas_pool_get_subpool(block_ptr % structs, 'forcing', forcingPool) + call MPAS_pool_get_array(forcingPool, "runningMeanRemovedIceRunoff", & + runningMeanRemovedIceRunoff) + call seq_infodata_PutData(infodata, rmean_rmv_ice_runoff=runningMeanRemovedIceRunoff) + end if !----------------------------------------------------------------------- ! @@ -987,12 +1009,15 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o)!{{{ logical, pointer :: config_use_CFCTracers logical, pointer :: config_use_activeTracers_surface_restoring logical, pointer :: config_use_surface_salinity_monthly_restoring + logical, pointer :: config_scale_dismf_by_removed_ice_runoff character (len=StrKIND), pointer :: config_restart_timestamp_name character (len=StrKIND), pointer :: config_sw_absorption_type ! Added for coupling interval initialization integer, pointer :: index_avgZonalSSHGradient, index_avgMeridionalSSHGradient real (kind=RKIND), dimension(:,:), pointer :: avgSSHGradient + real (kind=RKIND), pointer :: & + runningMeanRemovedIceRunoff ! the area integrated, running mean of removed ice runoff from the ocean #ifdef HAVE_MOAB #ifdef MOABCOMP @@ -1193,6 +1218,9 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o)!{{{ block_ptr => block_ptr % next end do + ! update scaled data ice-shelf melt fluxes based on remove ice runoff + call ocn_update_scaled_dismf(domain) + if (debugOn) call mpas_log_write(' Computing analysis members') call ocn_analysis_compute(domain_ptr, ierr) if (iam==0.and.debugOn) then @@ -1290,6 +1318,17 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o)!{{{ #endif call check_clocks_sync(domain % clock, Eclock, ierr) + call mpas_pool_get_config(domain % configs, 'config_scale_dismf_by_removed_ice_runoff', & + config_scale_dismf_by_removed_ice_runoff) + if (config_scale_dismf_by_removed_ice_runoff) then + ! independent of space so should be no need to loop over blocks + block_ptr => domain % blocklist + call mpas_pool_get_subpool(block_ptr % structs, 'forcing', forcingPool) + call MPAS_pool_get_array(forcingPool, "runningMeanRemovedIceRunoff", & + runningMeanRemovedIceRunoff) + call seq_infodata_PutData(infodata, rmean_rmv_ice_runoff=runningMeanRemovedIceRunoff) + end if + ! Reset I/O logs call shr_file_setLogUnit (shrlogunit) call shr_file_setLogLevel(shrloglev) diff --git a/components/mpas-ocean/src/Registry.xml b/components/mpas-ocean/src/Registry.xml index 2a21e22f40d2..f230276dca81 100644 --- a/components/mpas-ocean/src/Registry.xml +++ b/components/mpas-ocean/src/Registry.xml @@ -113,6 +113,9 @@ + @@ -807,6 +810,14 @@ description="If true, solid runoff from the Antarctic Ice Sheet (below 60S latitude) coming from the coupled is zeroed in the coupler import routines. To be used with data iceberg fluxes coming from the sea ice model." possible_values=".true. or .false." /> + + - @@ -1717,6 +1728,7 @@ + @@ -2043,6 +2055,11 @@ + + + + + + + + + + + @@ -4019,6 +4060,10 @@ description="Flux of heat into the ocean at land ice-ocean interface, as read in from a forcing file. Positive into ocean." packages="dataLandIceFluxesPKG" /> + + domain % blocklist + call mpas_pool_get_subpool(block % structs, 'forcing', forcingPool) + call mpas_pool_get_array(globalStatsAMPool, 'gsRunningMeanRemovedIceRunoff', gsRunningMeanRemovedIceRunoff) + call mpas_pool_get_array(forcingPool, 'runningMeanRemovedIceRunoff', runningMeanRemovedIceRunoff) + gsRunningMeanRemovedIceRunoff = runningMeanRemovedIceRunoff + end if + ! calculate fresh water conservation check quantities absoluteFreshWaterConservation = totalVolumeChange - netFreshwaterInput if (abs(totalVolumeChange) < 1e-12_RKIND) then diff --git a/components/mpas-ocean/src/driver/mpas_ocn_core_interface.F b/components/mpas-ocean/src/driver/mpas_ocn_core_interface.F index 6d542fb0c3f3..66c2349e1515 100644 --- a/components/mpas-ocean/src/driver/mpas_ocn_core_interface.F +++ b/components/mpas-ocean/src/driver/mpas_ocn_core_interface.F @@ -140,6 +140,7 @@ function ocn_setup_packages(configPool, packagePool, iocontext) result(ierr)!{{{ logical, pointer :: verticalRemapPKGActive logical, pointer :: activeWavePKGActive logical, pointer :: subgridWetDryPKGActive + logical, pointer :: scaledDISMFPKGActive type (mpas_pool_iterator_type) :: pkgItr logical, pointer :: packageActive @@ -175,6 +176,7 @@ function ocn_setup_packages(configPool, packagePool, iocontext) result(ierr)!{{{ logical, pointer :: config_use_gotm logical, pointer :: config_use_active_wave logical, pointer :: config_use_subgrid_wetting_drying + logical, pointer :: config_scale_dismf_by_removed_ice_runoff character (len=StrKIND), pointer :: config_time_integrator character (len=StrKIND), pointer :: config_ocean_run_mode @@ -449,6 +451,17 @@ function ocn_setup_packages(configPool, packagePool, iocontext) result(ierr)!{{{ subgridWetDryPKGActive = .true. end if + ! + ! test for scaling data ice-shelf melt fluxes by the running mean of removed ice runoff + ! + call mpas_pool_get_package(packagePool, 'scaledDISMFPKGActive', scaledDISMFPKGActive) + call mpas_pool_get_config(configPool, & + 'config_scale_dismf_by_removed_ice_runoff', & + config_scale_dismf_by_removed_ice_runoff) + if (config_scale_dismf_by_removed_ice_runoff) then + scaledDISMFPKGActive = .true. + end if + ! ! call into analysis member driver to set analysis member packages ! diff --git a/components/mpas-ocean/src/ocean.cmake b/components/mpas-ocean/src/ocean.cmake index 8866a8cea3d6..f2d5303fdd7b 100644 --- a/components/mpas-ocean/src/ocean.cmake +++ b/components/mpas-ocean/src/ocean.cmake @@ -114,6 +114,7 @@ list(APPEND RAW_SOURCES core_ocean/shared/mpas_ocn_stokes_drift.F core_ocean/shared/mpas_ocn_manufactured_solution.F core_ocean/shared/mpas_ocn_subgrid.F + core_ocean/shared/mpas_ocn_scaled_dismf.F ) set(OCEAN_DRIVER diff --git a/components/mpas-ocean/src/shared/mpas_ocn_scaled_dismf.F b/components/mpas-ocean/src/shared/mpas_ocn_scaled_dismf.F new file mode 100644 index 000000000000..bfdb39e49ad6 --- /dev/null +++ b/components/mpas-ocean/src/shared/mpas_ocn_scaled_dismf.F @@ -0,0 +1,309 @@ +! Copyright (c) 2013, Los Alamos National Security, LLC (LANS) +! and the University Corporation for Atmospheric Research (UCAR). +! +! Unless noted otherwise source code is licensed under the BSD license. +! Additional copyright and license information can be found in the LICENSE file +! distributed with this code, or at http://mpas-dev.github.io/license.html +! +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! ocn_scaled_dismf +!> \brief MPAS ocean scale data ice-shelf melt fluxes +!> \author Xylar Asay-Davis +!> \date July 2024 +!> \details +!> This module contains routines for scaling data ice-shelf melt fluxes by +!> the running mean of the removed ice runoff +!> Design document located at: +!> https://acme-climate.atlassian.net/wiki/spaces/PSC/pages/4210098268/Design+Document+Data+iceberg+and+ice-shelf+melt+flux+patterns+for+E3SM+runs +! +!----------------------------------------------------------------------- + +module ocn_scaled_dismf + + use mpas_kind_types + use mpas_derived_types + use mpas_global_sum_mod + use mpas_timekeeping + use mpas_timer + + use ocn_config + use ocn_mesh + + use shr_const_mod + + implicit none + private + save + + !-------------------------------------------------------------------- + ! + ! Public parameters + ! + !-------------------------------------------------------------------- + + !-------------------------------------------------------------------- + ! + ! Public member functions + ! + !-------------------------------------------------------------------- + + public :: ocn_init_scaled_dismf, & + ocn_update_scaled_dismf + + !-------------------------------------------------------------------- + ! + ! Private module variables + ! + !-------------------------------------------------------------------- + + logical :: scaledDISMFOn + character (len=*), parameter :: alarmID = 'scaledDISMFUpdateAlarm' + +!*********************************************************************** + +contains + + +!*********************************************************************** +! +! routine ocn_init_scaled_dismf +! +!> \brief Initialize scaling of data ice-shelf melt fluxes +!> \author Xylar Asay-Davis +!> \date July 2024 +!> \details +!> Set alarms needed to compute daily and running means of removed ice runoff +! +!----------------------------------------------------------------------- + + subroutine ocn_init_scaled_dismf(domain)!{{{ + + type (domain_type), intent(inout) :: domain + + ! Alarm variables + type (MPAS_Time_Type) :: alarmTime + type (MPAS_TimeInterval_type) :: alarmTimeStep + + integer :: err_tmp + + if (config_scale_dismf_by_removed_ice_runoff) then + scaledDISMFOn = .true. + else + scaledDISMFOn = .false. + return + endif + + if (.not. config_remove_ais_ice_runoff) then + call mpas_log_write('config_scale_dismf_by_removed_ice_runoff = .true. requires config_remove_ais_ice_runoff = .true.', & + MPAS_LOG_CRIT) + endif + + if (trim(config_land_ice_flux_mode) /= 'data') then + call mpas_log_write('config_scale_dismf_by_removed_ice_runoff = .true. requires config_land_ice_flux_mode = "data"', & + MPAS_LOG_CRIT) + endif + + ! Setup Alarm for updating of scaled DISMF + alarmTime = mpas_get_clock_time(domain % clock, & + MPAS_START_TIME, & + ierr=err_tmp) + call mpas_set_timeInterval(alarmTimeStep, & + timeString='0000-00-01_00:00:00', & + ierr=err_tmp) + call mpas_add_clock_alarm(domain % clock, alarmID, alarmTime + alarmTimeStep, & + alarmTimeInterval=alarmTimeStep, ierr=err_tmp) + + end subroutine ocn_init_scaled_dismf!}}} + + +!*********************************************************************** +! +! routine ocn_update_scaled_dismf +! +!> \brief Update scaled data ice-shelf melt fluxes +!> \author Xylar Asay-Davis +!> \date August 2024 +!> \details +!> Accumulate daily mean of removed runoff. If we are at the end of a day, +!> update the running mean of removed ice runoff, and use it to scale +!> the ice shelf melt flux based on the pattern from a data file +! +!----------------------------------------------------------------------- + + subroutine ocn_update_scaled_dismf(domain)!{{{ + + type (domain_type), intent(inout) :: domain + + integer :: err_tmp + + if (.not. scaledDISMFOn) then + return + end if + + ! since the current clock time is for the end of the accumulation + ! intereval, first, accumulate the daily mean + call accumulate_mean_removed_ice_runoff(domain) + + ! then, compute update the history and running mean if we are at the + ! end of a day + if(mpas_is_alarm_ringing(domain % clock, alarmID, ierr=err_tmp)) then +#ifdef MPAS_DEBUG + call mpas_log_write(' Computing Scaled DISMF') +#endif + call update_scaled_dismf(domain) + call mpas_reset_clock_alarm(domain % clock, alarmID, ierr=err_tmp) + endif + + end subroutine ocn_update_scaled_dismf!}}} + + +!*********************************************************************** +! +! routine accumulate_mean_removed_ice_runoff +! +!> \brief Accumulate mean removed ice runoff +!> \author Xylar Asay-Davis +!> \date August 2024 +!> \details +!> Accumulate current removed ice runoff into the daily mean value +! +!----------------------------------------------------------------------- + + subroutine accumulate_mean_removed_ice_runoff(domain)!{{{ + + type (domain_type), intent(inout) :: domain + + type (block_type), pointer :: block_ptr + type (mpas_pool_type), pointer :: forcingPool + + real (kind=RKIND), dimension(:), pointer :: removedIceRunoffFlux + real (kind=RKIND), pointer :: avgRemovedIceRunoff + integer, pointer :: nCellsSolve, nAccumulated + + real (kind=RKIND) :: totalFlux + real (kind=RKIND), dimension(:), allocatable :: localArrayForReproSum + + integer :: iCell + + block_ptr => domain % blocklist + + call mpas_pool_get_subpool(block_ptr % structs, 'forcing', forcingPool) + + ! independent of blocks + call mpas_pool_get_array(forcingPool, 'avgRemovedIceRunoff', avgRemovedIceRunoff) + call mpas_pool_get_dimension(forcingPool, 'nCellsSolve', nCellsSolve) + call mpas_pool_get_array(forcingPool, 'nAccumulatedRemovedIceRunoff', nAccumulated) + + do while(associated(block_ptr)) + call mpas_pool_get_subpool(block_ptr % structs, 'forcing', forcingPool) + + call mpas_pool_get_array(forcingPool, 'removedIceRunoffFlux', removedIceRunoffFlux) + call mpas_pool_get_array(forcingPool, 'avgRemovedIceRunoff', avgRemovedIceRunoff) + + call mpas_pool_get_dimension(forcingPool, 'nCellsSolve', nCellsSolve) + + call mpas_pool_get_array(forcingPool, 'nAccumulatedRemovedIceRunoff', nAccumulated) + + + allocate(localArrayForReproSum(nCellsSolve)) + localArrayForReproSum(:) = 0.0_RKIND + + !$omp parallel + !$omp do schedule(runtime) + do iCell=1,nCellsSolve + localArrayForReproSum(iCell) = removedIceRunoffFlux(iCell) * areaCell(iCell) + enddo + !$omp end do + !$omp end parallel + + block_ptr => block_ptr % next + end do ! block_ptr + + totalFlux = mpas_global_sum(localArrayForReproSum, domain % dminfo % comm) + + deallocate (localArrayForReproSum) + + avgRemovedIceRunoff = (avgRemovedIceRunoff * nAccumulated + totalFlux) & + / ( nAccumulated + 1 ) + + nAccumulated = nAccumulated + 1 + + end subroutine accumulate_mean_removed_ice_runoff!}}} + + + +!*********************************************************************** +! +! routine update_scaled_dismf +! +!> \brief Update scaled data ice-shelf melt fluxes +!> \author Xylar Asay-Davis +!> \date August 2024 +!> \details +!> Update the running mean of removed ice runoff, and use it to scale +!> the ice shelf melt flux based on the pattern from a data file +! +!----------------------------------------------------------------------- + + subroutine update_scaled_dismf(domain)!{{{ + + type (domain_type), intent(inout) :: domain + + type (block_type), pointer :: block_ptr + type (mpas_pool_type), pointer :: forcingPool + + real (kind=RKIND), pointer :: avgRemovedIceRunoff, runningMeanRemovedIceRunoff + real (kind=RKIND), dimension(:), pointer :: totalRemovedIceRunoffHistory + integer, pointer :: nValidHistory, nAccumulated + + real (kind=RKIND), dimension(:), allocatable :: tmpHistory + + real (kind=RKIND) :: previousTotal, timeInterval + integer :: nHistory + + block_ptr => domain % blocklist + call mpas_pool_get_subpool(block_ptr % structs, 'forcing', forcingPool) + + call mpas_pool_get_array(forcingPool, 'nAccumulatedRemovedIceRunoff', nAccumulated) + call mpas_pool_get_array(forcingPool, 'nValidTotalRemovedIceRunoffHistory', nValidHistory) + call mpas_pool_get_array(forcingPool, 'avgRemovedIceRunoff', avgRemovedIceRunoff) + call mpas_pool_get_array(forcingPool, 'totalRemovedIceRunoffHistory', totalRemovedIceRunoffHistory) + call mpas_pool_get_array(forcingPool, 'runningMeanRemovedIceRunoff', runningMeanRemovedIceRunoff) + + nHistory = config_ais_ice_runoff_history_days + + previousTotal = totalRemovedIceRunoffHistory(nValidHistory) + + if (nValidHistory == 0) then + ! we keep zero as the first entry in totalRemovedIceRunoffHistory + nValidHistory = 1 + end if + + if (nValidHistory == nHistory) then + ! we need to shift the history, since it's full + allocate(tmpHistory(nHistory)) + tmpHistory(:) = totalRemovedIceRunoffHistory(:) + totalRemovedIceRunoffHistory(1:nHistory - 1) = tmpHistory(2:nHistory) + else + ! the history isn't full yet, so we just add to the end + nValidHistory = nValidHistory + 1 + end if + + ! add the new total, the previous total plus the new daily average + totalRemovedIceRunoffHistory(nValidHistory) = previousTotal + SHR_CONST_CDAY * avgRemovedIceRunoff + + timeInterval = SHR_CONST_CDAY * (nValidHistory - 1) + ! the running mean is the difference between the newest and oldest + ! totals divided by the time between them + runningMeanRemovedIceRunoff = & + (totalRemovedIceRunoffHistory(nValidHistory) - totalRemovedIceRunoffHistory(1)) & + / timeInterval + + ! reset daily averaging of the removed runoff + nAccumulated = 0 + avgRemovedIceRunoff = 0.0_RKIND + + end subroutine update_scaled_dismf!}}} + +end module ocn_scaled_dismf \ No newline at end of file diff --git a/components/mpas-ocean/src/shared/mpas_ocn_surface_land_ice_fluxes.F b/components/mpas-ocean/src/shared/mpas_ocn_surface_land_ice_fluxes.F index fe489029a139..db5df3dfbe00 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_surface_land_ice_fluxes.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_surface_land_ice_fluxes.F @@ -278,6 +278,12 @@ subroutine ocn_surface_land_ice_fluxes_thick(forcingPool, surfaceThicknessFlux, real (kind=RKIND), dimension(:), pointer :: landIceFreshwaterFlux, & dataLandIceFreshwaterFlux + real (kind=RKIND), pointer :: runningMeanRemovedIceRunoff, & + areaIntegAnnMeanDataIcebergIceShelfFreshwaterFlux + + + real (kind=RKIND) :: scaling + err = 0 if (.not.landIceFluxesOn) return @@ -287,6 +293,16 @@ subroutine ocn_surface_land_ice_fluxes_thick(forcingPool, surfaceThicknessFlux, call mpas_pool_get_array(forcingPool, 'landIceFreshwaterFlux', landIceFreshwaterFlux) if ( landIceDataOn ) then + + if (config_scale_dismf_by_removed_ice_runoff) then + call mpas_pool_get_array(forcingPool, 'runningMeanRemovedIceRunoff', runningMeanRemovedIceRunoff) + call mpas_pool_get_array(forcingPool, 'areaIntegAnnMeanDataIcebergIceShelfFreshwaterFlux', & + areaIntegAnnMeanDataIcebergIceShelfFreshwaterFlux) + scaling = runningMeanRemovedIceRunoff / areaIntegAnnMeanDataIcebergIceShelfFreshwaterFlux + else + scaling = 1.0_RKIND + end if + call mpas_pool_get_array(forcingPool, 'dataLandIceFreshwaterFlux', dataLandIceFreshwaterFlux) #ifdef MPAS_OPENACC !$acc enter data copyin(landIceFreshwaterFlux) @@ -297,7 +313,7 @@ subroutine ocn_surface_land_ice_fluxes_thick(forcingPool, surfaceThicknessFlux, !$omp do schedule(runtime) #endif do iCell = 1, nCellsAll - landIceFreshwaterFlux(iCell) = dataLandIceFreshwaterFlux(iCell) + landIceFreshwaterFlux(iCell) = scaling * dataLandIceFreshwaterFlux(iCell) end do #ifndef MPAS_OPENACC !$omp end do @@ -378,6 +394,12 @@ subroutine ocn_surface_land_ice_fluxes_active_tracers(meshPool, forcingPool, tra real (kind=RKIND), dimension(:), pointer :: landIceHeatFlux, & dataLandIceHeatFlux + real (kind=RKIND), pointer :: runningMeanRemovedIceRunoff, & + areaIntegAnnMeanDataIcebergIceShelfFreshwaterFlux + + + real (kind=RKIND) :: scaling + err = 0 if (.not.landIceFluxesOn) return @@ -387,11 +409,21 @@ subroutine ocn_surface_land_ice_fluxes_active_tracers(meshPool, forcingPool, tra call mpas_pool_get_array(forcingPool, 'landIceHeatFlux', landIceHeatFlux) if ( landIceDataOn ) then + + if (config_scale_dismf_by_removed_ice_runoff) then + call mpas_pool_get_array(forcingPool, 'runningMeanRemovedIceRunoff', runningMeanRemovedIceRunoff) + call mpas_pool_get_array(forcingPool, 'areaIntegAnnMeanDataIcebergIceShelfFreshwaterFlux', & + areaIntegAnnMeanDataIcebergIceShelfFreshwaterFlux) + scaling = runningMeanRemovedIceRunoff / areaIntegAnnMeanDataIcebergIceShelfFreshwaterFlux + else + scaling = 1.0_RKIND + end if + call mpas_pool_get_array(forcingPool, 'dataLandIceHeatFlux', dataLandIceHeatFlux) !$omp parallel !$omp do schedule(runtime) do iCell = 1, nCells - landIceHeatFlux(iCell) = dataLandIceHeatFlux(iCell) + landIceHeatFlux(iCell) = scaling * dataLandIceHeatFlux(iCell) end do !$omp end do !$omp end parallel diff --git a/components/mpas-seaice/bld/build-namelist b/components/mpas-seaice/bld/build-namelist index 3d7ce2c619f8..87831cc94b03 100755 --- a/components/mpas-seaice/bld/build-namelist +++ b/components/mpas-seaice/bld/build-namelist @@ -946,6 +946,7 @@ if ($iceberg_mode eq 'data') { } else { add_default($nl, 'config_use_data_icebergs', 'val'=>"false"); } +add_default($nl, 'config_scale_dib_by_removed_ice_runoff'); add_default($nl, 'config_salt_flux_coupling_type'); add_default($nl, 'config_ice_ocean_drag_coefficient'); diff --git a/components/mpas-seaice/bld/build-namelist-section b/components/mpas-seaice/bld/build-namelist-section index d2866ee4c813..90dd6ce39f21 100644 --- a/components/mpas-seaice/bld/build-namelist-section +++ b/components/mpas-seaice/bld/build-namelist-section @@ -451,6 +451,7 @@ add_default($nl, 'config_ocean_heat_transfer_type'); add_default($nl, 'config_sea_freezing_temperature_type'); add_default($nl, 'config_ocean_surface_type'); add_default($nl, 'config_use_data_icebergs'); +add_default($nl, 'config_scale_dib_by_removed_ice_runoff'); add_default($nl, 'config_salt_flux_coupling_type'); add_default($nl, 'config_ice_ocean_drag_coefficient'); diff --git a/components/mpas-seaice/bld/namelist_files/namelist_defaults_mpassi.xml b/components/mpas-seaice/bld/namelist_files/namelist_defaults_mpassi.xml index 69294640ff67..8128c268c6e0 100644 --- a/components/mpas-seaice/bld/namelist_files/namelist_defaults_mpassi.xml +++ b/components/mpas-seaice/bld/namelist_files/namelist_defaults_mpassi.xml @@ -456,6 +456,7 @@ 'mushy' 'free' false +false 'constant' 0.00536 diff --git a/components/mpas-seaice/bld/namelist_files/namelist_definition_mpassi.xml b/components/mpas-seaice/bld/namelist_files/namelist_definition_mpassi.xml index ba6ae4be4bb1..d19f3f4eaad5 100644 --- a/components/mpas-seaice/bld/namelist_files/namelist_definition_mpassi.xml +++ b/components/mpas-seaice/bld/namelist_files/namelist_definition_mpassi.xml @@ -2686,6 +2686,14 @@ Valid values: true or false Default: Defined in namelist_defaults.xml + +Whether to scale data iceberg fluxes by the running mean of removed ice runoff + +Valid values: true or false +Default: Defined in namelist_defaults.xml + + Type of salt flux to ocean method diff --git a/components/mpas-seaice/cime_config/buildnml b/components/mpas-seaice/cime_config/buildnml index 29b017f6d8ba..5df71d69b1a8 100755 --- a/components/mpas-seaice/cime_config/buildnml +++ b/components/mpas-seaice/cime_config/buildnml @@ -300,7 +300,7 @@ def buildnml(case, caseroot, compname): grid_prefix = 'mpassi.IcoswISC30E3r5' decomp_date = '20231120' decomp_prefix = 'partitions/mpas-seaice.graph.info.' - data_iceberg_file = 'Iceberg_Climatology_Merino.IcoswISC30E3r5.20231120.nc' + data_iceberg_file = 'Iceberg_Climatology_Merino.IcoswISC30E3r5.20240805.nc' dust_iron_file = 'ecoForcingSurfaceMonthly+WetDryDustSolFrac.IcoswISC30E3r5.20240511.nc' if ice_ic_mode == 'spunup': if iceberg_mode == 'data': @@ -335,7 +335,7 @@ def buildnml(case, caseroot, compname): grid_prefix = 'mpassi.SOwISC12to30E3r3' decomp_date = '20240829' decomp_prefix = 'partitions/mpas-seaice.graph.info.' - data_iceberg_file = 'Iceberg_Climatology_Merino.SOwISC12to30E3r3.20240829.nc' + data_iceberg_file = 'Iceberg_Climatology_Merino.SOwISC12to30E3r3.20241017.nc' if ice_ic_mode == 'spunup': grid_date = '20240829' grid_prefix = 'mpassi.SOwISC12to30E3r3.rstFromG-chrysalis' @@ -668,6 +668,7 @@ def buildnml(case, caseroot, compname): lines.append(' input_interval="none" >') lines.append('') lines.append(' ') + lines.append(' ') lines.append(' ') lines.append('') lines.append('') diff --git a/components/mpas-seaice/driver/ice_comp_mct.F b/components/mpas-seaice/driver/ice_comp_mct.F index 3c579aee77af..f9d79bab96f2 100644 --- a/components/mpas-seaice/driver/ice_comp_mct.F +++ b/components/mpas-seaice/driver/ice_comp_mct.F @@ -194,7 +194,9 @@ subroutine ice_init_mct( EClock, cdata_i, x2i_i, i2x_i, NLFilename )!{{{ type (MPAS_TimeInterval_Type) :: alarmTimeStep type (block_type), pointer :: block - type (MPAS_Pool_Type), pointer :: shortwave + type (MPAS_Pool_Type), pointer :: & + shortwave, & + berg_forcing logical :: exists logical :: verbose_taskmap_output ! true then use verbose task-to-node mapping format @@ -241,15 +243,18 @@ subroutine ice_init_mct( EClock, cdata_i, x2i_i, i2x_i, NLFilename )!{{{ integer :: size_list, index_list type(mct_string) :: mctOStr ! character(CXX) :: mct_field, modelStr -#endif +#endif #endif - logical, pointer :: tempLogicalConfig + logical, pointer :: & + tempLogicalConfig, & + config_scale_dib_by_removed_ice_runoff character(len=StrKIND), pointer :: tempCharConfig real (kind=RKIND), pointer :: tempRealConfig real(kind=RKIND), pointer :: & - dayOfNextShortwaveCalculation ! needed for CESM like coupled simulations + dayOfNextShortwaveCalculation, & ! needed for CESM like coupled simulations + runningMeanRemovedIceRunoff ! the area integrated, running mean of removed ice runoff from the ocean interface subroutine xml_stream_parser(xmlname, mgr_p, comm, ierr) bind(c) @@ -505,6 +510,9 @@ end subroutine xml_stream_get_attributes end if + call MPAS_pool_get_config(domain % configs, "config_scale_dib_by_removed_ice_runoff", & + config_scale_dib_by_removed_ice_runoff) + ! Setup MPASSI simulation clock ierr = domain % core % setup_clock(domain % clock, domain % configs) if ( ierr /= 0 ) then @@ -636,6 +644,15 @@ end subroutine xml_stream_get_attributes ! Determine coupling type call seq_infodata_GetData(infodata, cpl_seq_option=cpl_seq_option) + if (config_scale_dib_by_removed_ice_runoff) then + ! independent of space so should be no need to loop over blocks + block => domain % blocklist + call MPAS_pool_get_subpool(block % structs, "berg_forcing", berg_forcing) + call MPAS_pool_get_array(berg_forcing, "runningMeanRemovedIceRunoff", & + runningMeanRemovedIceRunoff) + call seq_infodata_GetData(infodata, rmean_rmv_ice_runoff=runningMeanRemovedIceRunoff ) + end if + ! Determine time of next atmospheric shortwave calculation block => domain % blocklist do while (associated(block)) @@ -730,7 +747,7 @@ end subroutine xml_stream_get_attributes allocate (x2i_im(lsize, nrecv) ) i2x_im = 0._r8 x2i_im = 0._r8 - ! define tags according to the seq_flds_i2x_fields + ! define tags according to the seq_flds_i2x_fields ! also zero them out tagtype = 1 ! dense, double numco = 1 ! one value per cell / entity @@ -763,7 +780,7 @@ end subroutine xml_stream_get_attributes endif #endif - + !----------------------------------------------------------------------- ! @@ -827,10 +844,10 @@ end subroutine xml_stream_get_attributes else if (trim(tempCharConfig) == "column_package") then call seaice_column_coupling_prep(domain) endif ! config_column_physics_type - + call MPAS_pool_get_config(domain % configs, "config_use_floe_size_distribution", tempLogicalConfig) if (tempLogicalConfig) then - call mpas_log_write('FloeSizeDistribution coming online soon. Turn FSD off for now.', MPAS_LOG_CRIT) + call mpas_log_write('FloeSizeDistribution coming online soon. Turn FSD off for now.', MPAS_LOG_CRIT) endif !----------------------------------------------------------------------- ! @@ -854,7 +871,7 @@ end subroutine xml_stream_get_attributes ! ! get intial state from driver ! - call ice_import_mct(x2i_i, errorCode) + call ice_import_mct(x2i_i, errorCode) if (errorCode /= 0) then call mpas_log_write('Error in ice_import_mct', MPAS_LOG_CRIT) endif @@ -862,7 +879,7 @@ end subroutine xml_stream_get_attributes #ifdef HAVE_MOAB #ifdef MOABCOMP - mpicom_moab = mpicom_i ! save it for run method + mpicom_moab = mpicom_i ! save it for run method ! loop over all fields in seq_flds_x2i_fields call mct_list_init(temp_list ,seq_flds_x2i_fields) size_list=mct_list_nitem (temp_list) @@ -879,8 +896,8 @@ end subroutine xml_stream_get_attributes #endif call ice_import_moab(Eclock) -#endif - +#endif + currTime = mpas_get_clock_time(domain % clock, MPAS_NOW, ierr) call mpas_get_time(curr_time=currTime, dateTimeString=timeStamp, ierr=ierr) @@ -1151,7 +1168,8 @@ subroutine ice_run_mct( EClock, cdata_i, x2i_i, i2x_i)!{{{ ! Variable related to MPASSI type (block_type), pointer :: block type (MPAS_Pool_type), pointer :: & - shortwave + shortwave, & + berg_forcing real (kind=RKIND) :: current_wallclock_time type (MPAS_Time_Type) :: currTime @@ -1159,13 +1177,16 @@ subroutine ice_run_mct( EClock, cdata_i, x2i_i, i2x_i)!{{{ type (MPAS_timeInterval_type) :: timeStep integer :: ierr, streamDirection, iam logical :: streamActive, debugOn - logical, pointer :: config_write_output_on_startup + logical, pointer :: & + config_write_output_on_startup, & + config_scale_dib_by_removed_ice_runoff logical, save :: first=.true. character (len=StrKIND), pointer :: & config_restart_timestamp_name, & config_column_physics_type real(kind=RKIND), pointer :: & - dayOfNextShortwaveCalculation ! needed for CESM like coupled simulations + dayOfNextShortwaveCalculation, & ! needed for CESM like coupled simulations + runningMeanRemovedIceRunoff ! the area integrated, running mean of removed ice runoff from the ocean #ifdef MOABCOMP real(r8) :: difference @@ -1173,7 +1194,7 @@ subroutine ice_run_mct( EClock, cdata_i, x2i_i, i2x_i)!{{{ integer :: size_list, index_list, ent_type type(mct_string) :: mctOStr ! character(CXX) :: mct_field, modelStr, tagname -#endif +#endif iam = domain % dminfo % my_proc_id @@ -1187,8 +1208,10 @@ subroutine ice_run_mct( EClock, cdata_i, x2i_i, i2x_i)!{{{ mpas_log_info => domain % logInfo if (debugOn) call mpas_log_write("=== Beginning ice_run_mct ===") - call mpas_pool_get_config(domain % configs, 'config_restart_timestamp_name', config_restart_timestamp_name) + call MPAS_pool_get_config(domain % configs, 'config_restart_timestamp_name', config_restart_timestamp_name) call MPAS_pool_get_config(domain % configs, "config_column_physics_type", config_column_physics_type) + call MPAS_pool_get_config(domain % configs, "config_scale_dib_by_removed_ice_runoff", & + config_scale_dib_by_removed_ice_runoff) ! Setup log information. call shr_file_getLogUnit (shrlogunit) @@ -1225,6 +1248,15 @@ subroutine ice_run_mct( EClock, cdata_i, x2i_i, i2x_i)!{{{ ! Post coupling calls block => domain % blocklist + + if (config_scale_dib_by_removed_ice_runoff) then + ! independent of space so should be no need to loop over blocks + call MPAS_pool_get_subpool(block % structs, "berg_forcing", berg_forcing) + call MPAS_pool_get_array(berg_forcing, "runningMeanRemovedIceRunoff", & + runningMeanRemovedIceRunoff) + call seq_infodata_GetData(infodata, rmean_rmv_ice_runoff=runningMeanRemovedIceRunoff ) + end if + do while (associated(block)) ! Determine time of next atmospheric shortwave calculation @@ -2998,8 +3030,8 @@ subroutine frazil_mass(freezingPotential, frazilMassFlux, seaSurfaceSalinity) qi0new, & vi0new - call MPAS_pool_get_config(domain % configs, "config_thermodynamics_type", config_thermodynamics_type) - call MPAS_pool_get_config(domain % configs, "config_column_physics_type", config_column_physics_type) + call MPAS_pool_get_config(domain % configs, "config_thermodynamics_type", config_thermodynamics_type) + call MPAS_pool_get_config(domain % configs, "config_column_physics_type", config_column_physics_type) if (freezingPotential > 0.0_RKIND) then @@ -3479,15 +3511,15 @@ subroutine ice_import_moab(Eclock)!{{{ ! o dhdx -- ocn surface slope, zonal ! o dhdy -- ocn surface slope, meridional ! o lwdn -- downward lw heat flux -! o rain -- prec: liquid -! o snow -- prec: frozen +! o rain -- prec: liquid +! o snow -- prec: frozen ! o swndr -- sw: nir direct downward ! o swvdr -- sw: vis direct downward ! o swndf -- sw: nir diffuse downward ! o swvdf -- sw: vis diffuse downward ! o swnet -- sw: net ! o q -- ocn frazil heat flux(+) / melt potential(-) -! o frazil -- ocn frazil mass flux +! o frazil -- ocn frazil mass flux ! o bcphidry -- Black Carbon hydrophilic dry deposition flux ! o bcphodry -- Black Carbon hydrophobic dry deposition flux ! o bcphiwet -- Black Carbon hydrophilic wet deposition flux @@ -3502,10 +3534,10 @@ subroutine ice_import_moab(Eclock)!{{{ ! o dstdry2 -- Size 2 dust -- dry deposition flux ! o dstdry3 -- Size 3 dust -- dry deposition flux ! o dstdry4 -- Size 4 dust -- dry deposition flux -! +! ! The following fields are sometimes received from the coupler, ! depending on model options: -! +! ! o algae1 -- ! o algae2 -- ! o algae3 -- @@ -3530,7 +3562,7 @@ subroutine ice_import_moab(Eclock)!{{{ ! o zaer4 -- ! o zaer5 -- ! o zaer6 -- -! +! !----------------------------------------------------------------------- ! ! !REVISION HISTORY: @@ -3550,7 +3582,7 @@ subroutine ice_import_moab(Eclock)!{{{ character (len=StrKIND) :: & label, & message - + integer :: & i,n @@ -3687,10 +3719,10 @@ subroutine ice_import_moab(Eclock)!{{{ if (ierr > 0 ) then write(iceLogUnit,*) 'Fail to write ice state ' endif -#endif -!----------------------------------------------------------------------- +#endif +!----------------------------------------------------------------------- ! -! zero out padded cells +! zero out padded cells ! !----------------------------------------------------------------------- diff --git a/components/mpas-seaice/src/Registry.xml b/components/mpas-seaice/src/Registry.xml index 78830161c62d..d7b198b75745 100644 --- a/components/mpas-seaice/src/Registry.xml +++ b/components/mpas-seaice/src/Registry.xml @@ -1879,6 +1879,10 @@ description="Use data iceberg meltwater forcing" possible_values="true or false" /> + + + @@ -4956,11 +4962,26 @@ - + + + diff --git a/components/mpas-seaice/src/model_forward/mpas_seaice_core_interface.F b/components/mpas-seaice/src/model_forward/mpas_seaice_core_interface.F index 4b128d0c534d..6240ea9f7057 100644 --- a/components/mpas-seaice/src/model_forward/mpas_seaice_core_interface.F +++ b/components/mpas-seaice/src/model_forward/mpas_seaice_core_interface.F @@ -8,6 +8,7 @@ module seaice_core_interface use seaice_analysis_driver use mpas_log, only: mpas_log_write + implicit none public contains @@ -546,10 +547,10 @@ end subroutine setup_packages_column_physics!}}} ! routine setup_packages_bergs ! !> \brief Setup icebergs package - !> \author Darin Comeau - !> \date 19 May 2017 - !> \details This routine is intended to set the icebergs package PkgBergs - !> as active/deactive based on the namelist option config_use_bergs. + !> \author Darin Comeau, Xylar Asay-Davis + !> \date August 2024 + !> \details This routine is intended to set the icebergs packages PkgBergs + !> and pkgScaledDIB as active/deactive based on the namelist options. ! !----------------------------------------------------------------------- @@ -561,10 +562,13 @@ subroutine setup_packages_bergs(configPool, packagePool, ierr)!{{{ ! icebergs package logical, pointer :: & - config_use_data_icebergs + config_use_data_icebergs, & + config_scale_dib_by_removed_ice_runoff + logical, pointer :: & - pkgBergsActive + pkgBergsActive, & + pkgScaledDIBActive ierr = 0 @@ -576,6 +580,10 @@ subroutine setup_packages_bergs(configPool, packagePool, ierr)!{{{ call MPAS_pool_get_package(packagePool, "pkgBergsActive", pkgBergsActive) pkgBergsActive = config_use_data_icebergs + call MPAS_pool_get_config(configPool, "config_scale_dib_by_removed_ice_runoff", config_scale_dib_by_removed_ice_runoff) + call MPAS_pool_get_package(packagePool, "pkgScaledDIBActive", pkgScaledDIBActive) + pkgScaledDIBActive = config_scale_dib_by_removed_ice_runoff + end subroutine setup_packages_bergs!}}} !*********************************************************************** diff --git a/components/mpas-seaice/src/shared/mpas_seaice_forcing.F b/components/mpas-seaice/src/shared/mpas_seaice_forcing.F index ca0c4c5a962f..868189757005 100644 --- a/components/mpas-seaice/src/shared/mpas_seaice_forcing.F +++ b/components/mpas-seaice/src/shared/mpas_seaice_forcing.F @@ -3318,6 +3318,9 @@ subroutine get_data_iceberg_fluxes(domain) berg_forcing, & berg_fluxes + logical, pointer :: & + config_scale_dib_by_removed_ice_runoff + integer, pointer :: & nCellsSolve @@ -3326,14 +3329,36 @@ subroutine get_data_iceberg_fluxes(domain) bergFreshwaterFlux, & ! iceberg freshwater flux for ocean (kg/m^2/s) bergLatentHeatFlux ! iceberg latent heat flux for ocean (J/m^2/s) + real(kind=RKIND), pointer :: & + areaIntegAnnMeanDataIcebergIceShelfFreshwaterFlux, & ! area integrated, annual mean freshwater flux from icebegs and ice shelves (kg/s) + runningMeanRemovedIceRunoff ! the area integrated, running mean of removed ice runoff (kg/s) + integer :: & iCell + real(kind=RKIND) :: & + scaling + ! dc including as parameters here so as not to create new namelist options real(kind=RKIND), parameter :: & specificHeatFreshIce = 2106.0_RKIND, & ! specific heat of fresh ice J * kg^-1 * K^-1 bergTemperature = -4.0_RKIND ! iceberg temperature, assumed constant + + call MPAS_pool_get_config(domain % configs, "config_scale_dib_by_removed_ice_runoff", & + config_scale_dib_by_removed_ice_runoff) + + if (config_scale_dib_by_removed_ice_runoff) then + block => domain % blocklist + call MPAS_pool_get_subpool(block % structs, "berg_forcing", berg_forcing) + call mpas_pool_get_array(berg_forcing, 'runningMeanRemovedIceRunoff', runningMeanRemovedIceRunoff) + call mpas_pool_get_array(berg_forcing, 'areaIntegAnnMeanDataIcebergIceShelfFreshwaterFlux', & + areaIntegAnnMeanDataIcebergIceShelfFreshwaterFlux) + scaling = runningMeanRemovedIceRunoff / areaIntegAnnMeanDataIcebergIceShelfFreshwaterFlux + else + scaling = 1.0_RKIND + end if + block => domain % blocklist do while (associated(block)) @@ -3349,8 +3374,8 @@ subroutine get_data_iceberg_fluxes(domain) do iCell = 1, nCellsSolve - bergFreshwaterFlux(iCell) = bergFreshwaterFluxData(iCell) - bergLatentHeatFlux(iCell) = -bergFreshwaterFluxData(iCell) * & + bergFreshwaterFlux(iCell) = scaling * bergFreshwaterFluxData(iCell) + bergLatentHeatFlux(iCell) = -scaling * bergFreshwaterFluxData(iCell) * & (seaiceLatentHeatMelting - specificHeatFreshIce*bergTemperature) enddo diff --git a/driver-mct/main/seq_rest_mod.F90 b/driver-mct/main/seq_rest_mod.F90 index 0ad62de966f4..536602783313 100644 --- a/driver-mct/main/seq_rest_mod.F90 +++ b/driver-mct/main/seq_rest_mod.F90 @@ -519,6 +519,8 @@ subroutine seq_rest_write(EClock_d, seq_SyncClock, infodata, & call seq_io_write(rest_file,rvar,'seq_infodata_precip_fact',whead=whead,wdata=wdata) call seq_infodata_GetData(infodata,case_name=cvar) call seq_io_write(rest_file,trim(cvar),'seq_infodata_case_name',whead=whead,wdata=wdata) + call seq_infodata_GetData(infodata,rmean_rmv_ice_runoff=rvar) + call seq_io_write(rest_file,rvar,'seq_infodata_rmean_rmv_ice_runoff',whead=whead,wdata=wdata) call seq_timemgr_EClockGetData( EClock_d, start_ymd=ivar) call seq_io_write(rest_file,ivar,'seq_timemgr_start_ymd',whead=whead,wdata=wdata) diff --git a/driver-mct/shr/seq_infodata_mod.F90 b/driver-mct/shr/seq_infodata_mod.F90 index fcc6a21eef1f..ccb58e9cf857 100644 --- a/driver-mct/shr/seq_infodata_mod.F90 +++ b/driver-mct/shr/seq_infodata_mod.F90 @@ -250,7 +250,8 @@ MODULE seq_infodata_mod integer(SHR_KIND_IN) :: iac_phase ! iac phase logical :: atm_aero ! atmosphere aerosols logical :: glc_g2lupdate ! update glc2lnd fields in lnd model - real(shr_kind_r8) :: max_cplstep_time ! abort if cplstep time exceeds this value + real(SHR_KIND_R8) :: max_cplstep_time ! abort if cplstep time exceeds this value + real(SHR_KIND_R8) :: rmean_rmv_ice_runoff ! running mean of removed Antarctic ice runoff !--- set from restart file --- character(SHR_KIND_CL) :: rest_case_name ! Short case identification !--- set by driver and may be time varying @@ -761,7 +762,7 @@ SUBROUTINE seq_infodata_Init( infodata, nmlfile, ID, pioid, cpl_tag) infodata%atm_prognostic = .false. infodata%lnd_prognostic = .false. infodata%rof_prognostic = .false. - infodata%rofocn_prognostic = .false. + infodata%rofocn_prognostic = .false. infodata%ocn_prognostic = .false. infodata%ocnrof_prognostic = .false. infodata%ocn_c2_glcshelf = .false. @@ -808,6 +809,7 @@ SUBROUTINE seq_infodata_Init( infodata, nmlfile, ID, pioid, cpl_tag) infodata%atm_aero = .false. infodata%glc_g2lupdate = .false. infodata%glc_valid_input = .true. + infodata%rmean_rmv_ice_runoff = -1.0_SHR_KIND_R8 infodata%max_cplstep_time = max_cplstep_time infodata%model_doi_url = model_doi_url @@ -907,11 +909,13 @@ SUBROUTINE seq_infodata_Init( infodata, nmlfile, ID, pioid, cpl_tag) call seq_io_read(infodata%restart_file,pioid,infodata%nextsw_cday ,'seq_infodata_nextsw_cday') call seq_io_read(infodata%restart_file,pioid,infodata%precip_fact ,'seq_infodata_precip_fact') call seq_io_read(infodata%restart_file,pioid,infodata%rest_case_name,'seq_infodata_case_name') + call seq_io_read(infodata%restart_file,pioid,infodata%rmean_rmv_ice_runoff,'seq_infodata_rmean_rmv_ice_runoff') endif !--- Send from CPLID ROOT to GLOBALID ROOT, use bcast as surrogate call shr_mpi_bcast(infodata%nextsw_cday,mpicom,pebcast=seq_comm_gloroot(CPLID)) call shr_mpi_bcast(infodata%precip_fact,mpicom,pebcast=seq_comm_gloroot(CPLID)) call shr_mpi_bcast(infodata%rest_case_name,mpicom,pebcast=seq_comm_gloroot(CPLID)) + call shr_mpi_bcast(infodata%rmean_rmv_ice_runoff,mpicom,pebcast=seq_comm_gloroot(CPLID)) endif if (seq_comm_iamroot(ID)) then @@ -1041,7 +1045,8 @@ SUBROUTINE seq_infodata_GetData_explicit( infodata, cime_model, case_name, case_ reprosum_use_ddpdd, reprosum_allow_infnan, & reprosum_diffmax, reprosum_recompute, & mct_usealltoall, mct_usevector, max_cplstep_time, model_doi_url, & - glc_valid_input, nlmaps_verbosity, nlmaps_exclude_fields) + glc_valid_input, nlmaps_verbosity, nlmaps_exclude_fields, & + rmean_rmv_ice_runoff) implicit none @@ -1228,6 +1233,7 @@ SUBROUTINE seq_infodata_GetData_explicit( infodata, cime_model, case_name, case_ real(shr_kind_r8), optional, intent(out) :: max_cplstep_time character(SHR_KIND_CL), optional, intent(OUT) :: model_doi_url logical, optional, intent(OUT) :: glc_valid_input + real(SHR_KIND_R8), optional, intent(out) :: rmean_rmv_ice_runoff !----- local ----- character(len=*), parameter :: subname = '(seq_infodata_GetData_explicit) ' @@ -1427,6 +1433,7 @@ SUBROUTINE seq_infodata_GetData_explicit( infodata, cime_model, case_name, case_ if ( present(model_doi_url) ) model_doi_url = infodata%model_doi_url if ( present(glc_valid_input)) glc_valid_input = infodata%glc_valid_input + if ( present(rmean_rmv_ice_runoff) ) rmean_rmv_ice_runoff = infodata%rmean_rmv_ice_runoff END SUBROUTINE seq_infodata_GetData_explicit @@ -1595,7 +1602,7 @@ SUBROUTINE seq_infodata_PutData_explicit( infodata, cime_model, case_name, case_ reprosum_use_ddpdd, reprosum_allow_infnan, & reprosum_diffmax, reprosum_recompute, & mct_usealltoall, mct_usevector, glc_valid_input, & - nlmaps_verbosity, nlmaps_exclude_fields) + nlmaps_verbosity, nlmaps_exclude_fields, rmean_rmv_ice_runoff) implicit none @@ -1778,6 +1785,7 @@ SUBROUTINE seq_infodata_PutData_explicit( infodata, cime_model, case_name, case_ logical, optional, intent(IN) :: atm_aero ! atm aerosols logical, optional, intent(IN) :: glc_g2lupdate ! update glc2lnd fields in lnd model logical, optional, intent(IN) :: glc_valid_input + real(SHR_KIND_R8), optional, intent(IN) :: rmean_rmv_ice_runoff ! running mean of removed Antarctic ice runoff !EOP @@ -1963,6 +1971,7 @@ SUBROUTINE seq_infodata_PutData_explicit( infodata, cime_model, case_name, case_ if ( present(atm_aero) ) infodata%atm_aero = atm_aero if ( present(glc_g2lupdate) ) infodata%glc_g2lupdate = glc_g2lupdate if ( present(glc_valid_input) ) infodata%glc_valid_input = glc_valid_input + if ( present(rmean_rmv_ice_runoff) ) infodata%rmean_rmv_ice_runoff = rmean_rmv_ice_runoff END SUBROUTINE seq_infodata_PutData_explicit @@ -2277,6 +2286,7 @@ subroutine seq_infodata_bcast(infodata,mpicom) call shr_mpi_bcast(infodata%glc_valid_input, mpicom) call shr_mpi_bcast(infodata%model_doi_url, mpicom) call shr_mpi_bcast(infodata%constant_zenith_deg, mpicom) + call shr_mpi_bcast(infodata%rmean_rmv_ice_runoff, mpicom) end subroutine seq_infodata_bcast @@ -2617,6 +2627,7 @@ subroutine seq_infodata_Exchange(infodata,ID,type) if (ocn2cplr) then call shr_mpi_bcast(infodata%precip_fact, mpicom, pebcast=cmppe) + call shr_mpi_bcast(infodata%rmean_rmv_ice_runoff, mpicom, pebcast=cmppe) endif if (cpl2r) then @@ -2624,6 +2635,7 @@ subroutine seq_infodata_Exchange(infodata,ID,type) call shr_mpi_bcast(infodata%precip_fact, mpicom, pebcast=cplpe) call shr_mpi_bcast(infodata%glc_g2lupdate, mpicom, pebcast=cplpe) call shr_mpi_bcast(infodata%glc_valid_input, mpicom, pebcast=cplpe) + call shr_mpi_bcast(infodata%rmean_rmv_ice_runoff, mpicom, pebcast=cplpe) endif end subroutine seq_infodata_Exchange @@ -2995,6 +3007,7 @@ SUBROUTINE seq_infodata_print( infodata ) write(logunit,F0S) subname,'iac_phase = ', infodata%iac_phase write(logunit,F0L) subname,'glc_g2lupdate = ', infodata%glc_g2lupdate + write(logunit,F0R) subname,'rmean_rmv_ice_runoff = ', infodata%rmean_rmv_ice_runoff ! endif END SUBROUTINE seq_infodata_print diff --git a/driver-moab/main/seq_rest_mod.F90 b/driver-moab/main/seq_rest_mod.F90 index ab40eab408a5..dafd4d056686 100644 --- a/driver-moab/main/seq_rest_mod.F90 +++ b/driver-moab/main/seq_rest_mod.F90 @@ -97,7 +97,7 @@ module seq_rest_mod public :: seq_rest_mb_write ! read cpl7_moab restart data #ifdef MOABDEBUG - public :: write_moab_state ! debug, write files + public :: write_moab_state ! debug, write files #endif ! !PUBLIC DATA MEMBERS: @@ -367,7 +367,7 @@ subroutine seq_rest_mb_read(rest_file, infodata, samegrid_al) use seq_comm_mct, only: mbaxid, mbixid, mboxid, mblxid, mbrxid, mbofxid ! coupler side instances use iMOAB, only: iMOAB_GetGlobalInfo use seq_comm_mct , only: num_moab_exports ! it is used only as a counter for moab h5m files - + implicit none character(*) , intent(in) :: rest_file ! restart file path/name @@ -379,7 +379,7 @@ subroutine seq_rest_mb_read(rest_file, infodata, samegrid_al) real(r8),allocatable :: ns(:) ! for reshaping diag data for restart file character(CXX) :: moab_rest_file - character(CXX) :: tagname + character(CXX) :: tagname integer (in), pointer :: o2racc_om_cnt ! replacement, moab version for o2racc_ox_cnt integer (in), pointer :: x2oacc_om_cnt ! replacement, moab version for x2oacc_ox_cnt @@ -392,7 +392,7 @@ subroutine seq_rest_mb_read(rest_file, infodata, samegrid_al) real(r8), dimension(:,:), pointer :: p_l2racc_lm character(len=*), parameter :: subname = "(seq_rest_mb_read) " - + !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- @@ -517,7 +517,7 @@ subroutine seq_rest_mb_read(rest_file, infodata, samegrid_al) call seq_io_read(moab_rest_file, mboxid, 'fractions_ox', & 'afrac:ifrac:ofrac:ifrad:ofrad') ! fraclist_o = 'afrac:ifrac:ofrac:ifrad:ofrad' call seq_io_read(moab_rest_file, mboxid, 'o2x_ox', & - trim(seq_flds_o2x_fields)) + trim(seq_flds_o2x_fields)) tagname = trim(seq_flds_x2o_fields) x2oacc_om_cnt => prep_ocn_get_x2oacc_om_cnt() p_x2oacc_om => prep_ocn_get_x2oacc_om() @@ -525,7 +525,7 @@ subroutine seq_rest_mb_read(rest_file, infodata, samegrid_al) call seq_io_read (moab_rest_file, mboxid, 'x2oacc_ox', & trim(tagname), & matrix=p_x2oacc_om) - call seq_io_read(moab_rest_file, x2oacc_om_cnt, 'x2oacc_ox_cnt') + call seq_io_read(moab_rest_file, x2oacc_om_cnt, 'x2oacc_ox_cnt') ! tagname = trim(seq_flds_xao_fields)//C_NULL_CHAR ! arrsize = nxflds * lsize ! allocate (xao_om (lsize, nxflds)) ! ierr = iMOAB_GetDoubleTagStorage ( mbofxid, tagname, arrsize , ent_type, xao_om) @@ -548,7 +548,7 @@ subroutine seq_rest_mb_read(rest_file, infodata, samegrid_al) call seq_io_read(moab_rest_file, mbixid, 'fractions_ix', & 'afrac:ifrac:ofrac') ! fraclist_i = 'afrac:ifrac:ofrac' call seq_io_read(moab_rest_file, mbixid, 'i2x_ix', & - trim(seq_flds_i2x_fields) ) + trim(seq_flds_i2x_fields) ) ! gsmap => component_get_gsmap_cx(ice(1)) ! call seq_io_read(rest_file, gsmap, fractions_ix, 'fractions_ix') ! call seq_io_read(rest_file, ice, 'c2x', 'i2x_ix') @@ -557,7 +557,7 @@ subroutine seq_rest_mb_read(rest_file, infodata, samegrid_al) call seq_io_read(moab_rest_file, mbrxid, 'fractions_rx', & 'lfrac:lfrin:rfrac') ! fraclist_r = 'lfrac:lfrin:rfrac' call seq_io_read(moab_rest_file, mbrxid, 'r2x_rx', & - trim(seq_flds_r2x_fields) ) + trim(seq_flds_r2x_fields) ) ! gsmap => component_get_gsmap_cx(rof(1)) ! call seq_io_read(rest_file, gsmap, fractions_rx, 'fractions_rx') ! call seq_io_read(rest_file, rof, 'c2x', 'r2x_rx') @@ -799,6 +799,8 @@ subroutine seq_rest_write(EClock_d, seq_SyncClock, infodata, & call seq_io_write(rest_file,rvar,'seq_infodata_precip_fact',whead=whead,wdata=wdata) call seq_infodata_GetData(infodata,case_name=cvar) call seq_io_write(rest_file,trim(cvar),'seq_infodata_case_name',whead=whead,wdata=wdata) + call seq_infodata_GetData(infodata,rmean_rmv_ice_runoff=rvar) + call seq_io_write(rest_file,rvar,'seq_infodata_rmean_rmv_ice_runoff',whead=whead,wdata=wdata) call seq_timemgr_EClockGetData( EClock_d, start_ymd=ivar) call seq_io_write(rest_file,ivar,'seq_timemgr_start_ymd',whead=whead,wdata=wdata) @@ -1120,6 +1122,8 @@ subroutine seq_rest_mb_write(EClock_d, seq_SyncClock, infodata, & call seq_io_write(rest_file,rvar,'seq_infodata_precip_fact',whead=whead,wdata=wdata) call seq_infodata_GetData(infodata,case_name=cvar) call seq_io_write(rest_file,trim(cvar),'seq_infodata_case_name',whead=whead,wdata=wdata) + call seq_infodata_GetData(infodata,rmean_rmv_ice_runoff=rvar) + call seq_io_write(rest_file,rvar,'seq_infodata_rmean_rmv_ice_runoff',whead=whead,wdata=wdata) call seq_timemgr_EClockGetData( EClock_d, start_ymd=ivar) call seq_io_write(rest_file,ivar,'seq_timemgr_start_ymd',whead=whead,wdata=wdata) @@ -1169,15 +1173,15 @@ subroutine seq_rest_mb_write(EClock_d, seq_SyncClock, infodata, & ! nx for land will be from global nb atmosphere ierr = iMOAB_GetGlobalInfo(mbaxid, dummy, nx_lnd) ! max id for land will come from atm call seq_io_write(rest_file, mblxid, 'fractions_lx', & - 'afrac:lfrac:lfrin', & ! seq_frac_mod: character(*),parameter :: fraclist_l = 'afrac:lfrac:lfrin' - whead=whead, wdata=wdata, nx=nx_lnd) + 'afrac:lfrac:lfrin', & ! seq_frac_mod: character(*),parameter :: fraclist_l = 'afrac:lfrac:lfrin' + whead=whead, wdata=wdata, nx=nx_lnd) else call seq_io_write(rest_file, mblxid, 'fractions_lx', & - 'afrac:lfrac:lfrin', & ! seq_frac_mod: character(*),parameter :: fraclist_l = 'afrac:lfrac:lfrin' + 'afrac:lfrac:lfrin', & ! seq_frac_mod: character(*),parameter :: fraclist_l = 'afrac:lfrac:lfrin' whead=whead, wdata=wdata) endif ! call seq_io_write(rest_file, mblxid, 'fractions_lx', & - ! 'afrac:lfrac:lfrin', & ! seq_frac_mod: character(*),parameter :: fraclist_l = 'afrac:lfrac:lfrin' + ! 'afrac:lfrac:lfrin', & ! seq_frac_mod: character(*),parameter :: fraclist_l = 'afrac:lfrac:lfrin' ! whead=whead, wdata=wdata) ! gsmap => component_get_gsmap_cx(lnd(1)) ! call seq_io_write(rest_file, gsmap, fractions_lx, 'fractions_lx', & @@ -1192,7 +1196,7 @@ subroutine seq_rest_mb_write(EClock_d, seq_SyncClock, infodata, & ierr = iMOAB_GetGlobalInfo(mbaxid, dummy, nx_lnd) ! max id for land will come from atm call seq_io_write(rest_file, mblxid, 'l2racc_lx', & trim(tagname), & - whead=whead, wdata=wdata, matrix = p_l2racc_lm, nx=nx_lnd) + whead=whead, wdata=wdata, matrix = p_l2racc_lm, nx=nx_lnd) else call seq_io_write(rest_file, mblxid, 'l2racc_lx', & trim(tagname), & @@ -1247,11 +1251,11 @@ subroutine seq_rest_mb_write(EClock_d, seq_SyncClock, infodata, & if (ocn_present) then ! gsmap => component_get_gsmap_cx(ocn(1)) ! x2oacc_ox => prep_ocn_get_x2oacc_ox() - + call seq_io_write(rest_file, mboxid, 'fractions_ox', & 'afrac:ifrac:ofrac:ifrad:ofrad', & ! fraclist_o = 'afrac:ifrac:ofrac:ifrad:ofrad' whead=whead, wdata=wdata) - + call seq_io_write(rest_file, mboxid, 'o2x_ox', & trim(seq_flds_o2x_fields), & whead=whead, wdata=wdata) @@ -1293,7 +1297,7 @@ subroutine seq_rest_mb_write(EClock_d, seq_SyncClock, infodata, & whead=whead, wdata=wdata) call seq_io_write(rest_file, mbixid, 'i2x_ix', & trim(seq_flds_i2x_fields), & - whead=whead, wdata=wdata) + whead=whead, wdata=wdata) ! gsmap => component_get_gsmap_cx(ice(1)) ! call seq_io_write(rest_file, gsmap, fractions_ix, 'fractions_ix', & ! whead=whead, wdata=wdata) @@ -1348,10 +1352,10 @@ end subroutine seq_rest_mb_write !=============================================================================== #ifdef MOABDEBUG - subroutine write_moab_state ( before_reading ) ! debug, write files + subroutine write_moab_state ( before_reading ) ! debug, write files use seq_comm_mct, only: mbaxid, mbixid, mboxid, mblxid, mbrxid, mbofxid ! coupler side instances use seq_comm_mct, only: num_moab_exports - use iso_c_binding + use iso_c_binding use iMOAB, only: iMOAB_WriteMesh implicit none @@ -1414,7 +1418,7 @@ subroutine write_moab_state ( before_reading ) ! debug, write files endif endif - end subroutine write_moab_state + end subroutine write_moab_state #endif end module seq_rest_mod diff --git a/driver-moab/shr/seq_infodata_mod.F90 b/driver-moab/shr/seq_infodata_mod.F90 index 512adb853b63..749edc2fdaa8 100644 --- a/driver-moab/shr/seq_infodata_mod.F90 +++ b/driver-moab/shr/seq_infodata_mod.F90 @@ -251,7 +251,8 @@ MODULE seq_infodata_mod integer(SHR_KIND_IN) :: iac_phase ! iac phase logical :: atm_aero ! atmosphere aerosols logical :: glc_g2lupdate ! update glc2lnd fields in lnd model - real(shr_kind_r8) :: max_cplstep_time ! abort if cplstep time exceeds this value + real(SHR_KIND_R8) :: max_cplstep_time ! abort if cplstep time exceeds this value + real(SHR_KIND_R8) :: rmean_rmv_ice_runoff ! running mean of removed Antarctic ice runoff !--- set from restart file --- character(SHR_KIND_CL) :: rest_case_name ! Short case identification !--- set by driver and may be time varying @@ -759,7 +760,7 @@ SUBROUTINE seq_infodata_Init( infodata, nmlfile, ID, pioid, cpl_tag) infodata%atm_prognostic = .false. infodata%lnd_prognostic = .false. infodata%rof_prognostic = .false. - infodata%rofocn_prognostic = .false. + infodata%rofocn_prognostic = .false. infodata%ocn_prognostic = .false. infodata%ocnrof_prognostic = .false. infodata%ocn_c2_glcshelf = .false. @@ -795,8 +796,8 @@ SUBROUTINE seq_infodata_Init( infodata, nmlfile, ID, pioid, cpl_tag) infodata%lnd_domain = 'none' infodata%rof_mesh = 'none' infodata%rof_domain = 'none' - infodata%ocn_domain = 'none' ! will be used for ocean data models only; will be used as a signal - infodata%ice_domain = 'none' ! will be used for ice data models only; will be used as a signal + infodata%ocn_domain = 'none' ! will be used for ocean data models only; will be used as a signal + infodata%ice_domain = 'none' ! will be used for ice data models only; will be used as a signal infodata%atm_mesh = 'none' ! will be used for atmosphere data models only; will be used as a signal ! not sure if it exists always actually @@ -813,6 +814,7 @@ SUBROUTINE seq_infodata_Init( infodata, nmlfile, ID, pioid, cpl_tag) infodata%atm_aero = .false. infodata%glc_g2lupdate = .false. infodata%glc_valid_input = .true. + infodata%rmean_rmv_ice_runoff = -1.0_SHR_KIND_R8 infodata%max_cplstep_time = max_cplstep_time infodata%model_doi_url = model_doi_url @@ -912,11 +914,13 @@ SUBROUTINE seq_infodata_Init( infodata, nmlfile, ID, pioid, cpl_tag) call seq_io_read(infodata%restart_file,pioid,infodata%nextsw_cday ,'seq_infodata_nextsw_cday') call seq_io_read(infodata%restart_file,pioid,infodata%precip_fact ,'seq_infodata_precip_fact') call seq_io_read(infodata%restart_file,pioid,infodata%rest_case_name,'seq_infodata_case_name') + call seq_io_read(infodata%restart_file,pioid,infodata%rmean_rmv_ice_runoff ,'seq_infodata_rmean_rmv_ice_runoff') endif !--- Send from CPLID ROOT to GLOBALID ROOT, use bcast as surrogate call shr_mpi_bcast(infodata%nextsw_cday,mpicom,pebcast=seq_comm_gloroot(CPLID)) call shr_mpi_bcast(infodata%precip_fact,mpicom,pebcast=seq_comm_gloroot(CPLID)) call shr_mpi_bcast(infodata%rest_case_name,mpicom,pebcast=seq_comm_gloroot(CPLID)) + call shr_mpi_bcast(infodata%rmean_rmv_ice_runoff,mpicom,pebcast=seq_comm_gloroot(CPLID)) endif if (seq_comm_iamroot(ID)) then @@ -1047,7 +1051,7 @@ SUBROUTINE seq_infodata_GetData_explicit( infodata, cime_model, case_name, case_ reprosum_use_ddpdd, reprosum_allow_infnan, & reprosum_diffmax, reprosum_recompute, & mct_usealltoall, mct_usevector, max_cplstep_time, model_doi_url, & - glc_valid_input, nlmaps_verbosity) + glc_valid_input, nlmaps_verbosity, rmean_rmv_ice_runoff) implicit none @@ -1238,6 +1242,7 @@ SUBROUTINE seq_infodata_GetData_explicit( infodata, cime_model, case_name, case_ real(shr_kind_r8), optional, intent(out) :: max_cplstep_time character(SHR_KIND_CL), optional, intent(OUT) :: model_doi_url logical, optional, intent(OUT) :: glc_valid_input + real(SHR_KIND_R8), optional, intent(OUT) :: rmean_rmv_ice_runoff ! running mean of removed Antarctic ice runoff !----- local ----- character(len=*), parameter :: subname = '(seq_infodata_GetData_explicit) ' @@ -1442,6 +1447,7 @@ SUBROUTINE seq_infodata_GetData_explicit( infodata, cime_model, case_name, case_ if ( present(model_doi_url) ) model_doi_url = infodata%model_doi_url if ( present(glc_valid_input)) glc_valid_input = infodata%glc_valid_input + if ( present(rmean_rmv_ice_runoff) ) rmean_rmv_ice_runoff = infodata%rmean_rmv_ice_runoff END SUBROUTINE seq_infodata_GetData_explicit @@ -1610,7 +1616,8 @@ SUBROUTINE seq_infodata_PutData_explicit( infodata, cime_model, case_name, case_ eps_aarea, eps_omask, eps_ogrid, eps_oarea, & reprosum_use_ddpdd, reprosum_allow_infnan, & reprosum_diffmax, reprosum_recompute, & - mct_usealltoall, mct_usevector, glc_valid_input, nlmaps_verbosity) + mct_usealltoall, mct_usevector, glc_valid_input, nlmaps_verbosity, & + rmean_rmv_ice_runoff) implicit none @@ -1798,6 +1805,7 @@ SUBROUTINE seq_infodata_PutData_explicit( infodata, cime_model, case_name, case_ logical, optional, intent(IN) :: atm_aero ! atm aerosols logical, optional, intent(IN) :: glc_g2lupdate ! update glc2lnd fields in lnd model logical, optional, intent(IN) :: glc_valid_input + real(SHR_KIND_R8), optional, intent(IN) :: rmean_rmv_ice_runoff ! running mean of removed Antarctic ice runoff !EOP @@ -1988,6 +1996,7 @@ SUBROUTINE seq_infodata_PutData_explicit( infodata, cime_model, case_name, case_ if ( present(atm_aero) ) infodata%atm_aero = atm_aero if ( present(glc_g2lupdate) ) infodata%glc_g2lupdate = glc_g2lupdate if ( present(glc_valid_input) ) infodata%glc_valid_input = glc_valid_input + if ( present(rmean_rmv_ice_runoff) ) infodata%rmean_rmv_ice_runoff = rmean_rmv_ice_runoff END SUBROUTINE seq_infodata_PutData_explicit @@ -2302,6 +2311,7 @@ subroutine seq_infodata_bcast(infodata,mpicom) call shr_mpi_bcast(infodata%glc_valid_input, mpicom) call shr_mpi_bcast(infodata%model_doi_url, mpicom) call shr_mpi_bcast(infodata%constant_zenith_deg, mpicom) + call shr_mpi_bcast(infodata%rmean_rmv_ice_runoff, mpicom) end subroutine seq_infodata_bcast @@ -2648,6 +2658,7 @@ subroutine seq_infodata_Exchange(infodata,ID,type) if (ocn2cplr) then call shr_mpi_bcast(infodata%precip_fact, mpicom, pebcast=cmppe) + call shr_mpi_bcast(infodata%rmean_rmv_ice_runoff, mpicom, pebcast=cmppe) endif if (cpl2r) then @@ -2655,6 +2666,7 @@ subroutine seq_infodata_Exchange(infodata,ID,type) call shr_mpi_bcast(infodata%precip_fact, mpicom, pebcast=cplpe) call shr_mpi_bcast(infodata%glc_g2lupdate, mpicom, pebcast=cplpe) call shr_mpi_bcast(infodata%glc_valid_input, mpicom, pebcast=cplpe) + call shr_mpi_bcast(infodata%rmean_rmv_ice_runoff, mpicom, pebcast=cplpe) endif end subroutine seq_infodata_Exchange @@ -3025,6 +3037,7 @@ SUBROUTINE seq_infodata_print( infodata ) write(logunit,F0S) subname,'iac_phase = ', infodata%iac_phase write(logunit,F0L) subname,'glc_g2lupdate = ', infodata%glc_g2lupdate + write(logunit,F0R) subname,'rmean_rmv_ice_runoff = ', infodata%rmean_rmv_ice_runoff ! endif END SUBROUTINE seq_infodata_print