From 3e80bbca5162a712ba36c57304d74926d04fcb52 Mon Sep 17 00:00:00 2001 From: alex-huth Date: Mon, 4 Dec 2023 17:00:50 -0500 Subject: [PATCH 1/4] Calving of icebergs based on ice shelf flux through static ice front -This commit is the coupler contribution to calving of icebergs based on the ice-shelf flux through a static ice-shelf front. This flux is passed from MOM6 --> coupler --> SIS2 --> icebergs. -To use, simply add calve_ice_shelf_bergs=True to the coupler nml (and use the SIS2 and MOM6 commits that include ice-shelf calving). -"Calving" based on frozen discharge from the land model can also be used simultaneously, as long no cell has both nonzero frozen-discharge-based and ice-shelf calving. For example, land-discharge-based calving can be used for Greenland (without an ice-sheet component) and ice-shelf calving for Antarctica (with an ice-sheet component). -Note that the data_override variable for ice-shelf calving is Ocean_Ice_boundary%IS_calving to differentiate from the land-model discharge-calving override Land_Ice_Boundary%calving. --- full/coupler_main.F90 | 17 +++++++-- full/ice_ocean_flux_exchange.F90 | 59 ++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/full/coupler_main.F90 b/full/coupler_main.F90 index 277cd057..74af451a 100644 --- a/full/coupler_main.F90 +++ b/full/coupler_main.F90 @@ -373,6 +373,7 @@ program coupler_main use ice_model_mod, only: ice_data_type_chksum, ocn_ice_bnd_type_chksum use ice_model_mod, only: atm_ice_bnd_type_chksum, lnd_ice_bnd_type_chksum use ice_model_mod, only: unpack_ocean_ice_boundary, exchange_slow_to_fast_ice + use ice_model_mod, only: unpack_ocean_ice_boundary_calved_shelf_bergs use ice_model_mod, only: ice_model_fast_cleanup, unpack_land_ice_boundary use ice_model_mod, only: exchange_fast_to_slow_ice, update_ice_model_slow @@ -512,6 +513,8 @@ program coupler_main logical :: do_debug=.FALSE. !< If .TRUE. print additional debugging messages. integer :: check_stocks = 0 ! -1: never 0: at end of run only n>0: every n coupled steps logical :: use_hyper_thread = .false. + logical :: calve_ice_shelf_bergs = .false. !< If true, flux through a static ice front is converted + !!to point bergs namelist /coupler_nml/ current_date, calendar, force_date_from_namelist, & months, days, hours, minutes, seconds, dt_cpld, dt_atmos, & @@ -521,7 +524,8 @@ program coupler_main concurrent, do_concurrent_radiation, use_lag_fluxes, & check_stocks, restart_interval, do_debug, do_chksum, & use_hyper_thread, concurrent_ice, slow_ice_with_ocean, & - do_endpoint_chksum, combined_ice_and_ocean + do_endpoint_chksum, combined_ice_and_ocean, & + calve_ice_shelf_bergs integer :: initClock, mainClock, termClock @@ -751,6 +755,10 @@ program coupler_main call fms_mpp_clock_begin(newClock10e) call exchange_fast_to_slow_ice(Ice) call fms_mpp_clock_end(newClock10e) + call fms_mpp_clock_begin(newClock10f) + if (Ice%slow_ice_pe .and. calve_ice_shelf_bergs) & + call unpack_ocean_ice_boundary_calved_shelf_bergs(Ice, Ocean_ice_boundary) + call fms_mpp_clock_end(newClock10f) endif if (Ice%fast_ice_pe) then @@ -1004,6 +1012,10 @@ program coupler_main call fms_mpp_clock_begin(newClock10e) call exchange_fast_to_slow_ice(Ice) call fms_mpp_clock_end(newClock10e) + call fms_mpp_clock_begin(newClock10f) + if (Ice%slow_ice_pe .and. calve_ice_shelf_bergs) & + call unpack_ocean_ice_boundary_calved_shelf_bergs(Ice, Ocean_ice_boundary) + call fms_mpp_clock_end(newClock10f) endif ! ------ slow-ice model ------ @@ -1800,7 +1812,8 @@ subroutine coupler_init endif call fms_mpp_clock_begin(id_ocean_model_init) call ocean_model_init( Ocean, Ocean_state, Time_init, Time, & - gas_fields_ocn=gas_fields_ocn ) + gas_fields_ocn=gas_fields_ocn, & + calve_ice_shelf_bergs=calve_ice_shelf_bergs) call fms_mpp_clock_end(id_ocean_model_init) if (concurrent) then diff --git a/full/ice_ocean_flux_exchange.F90 b/full/ice_ocean_flux_exchange.F90 index a0219d9f..6c5e5d45 100644 --- a/full/ice_ocean_flux_exchange.F90 +++ b/full/ice_ocean_flux_exchange.F90 @@ -88,6 +88,8 @@ subroutine ice_ocean_flux_exchange_init(Time, Ice, Ocean, Ocean_state, ice_ocean !frazil and sea_level are optional, if not present they should be nullified allocate( ocean_ice_boundary%frazil(is:ie,js:je) ) allocate( ocean_ice_boundary%sea_level(is:ie,js:je) ) + allocate( ocean_ice_boundary%calving(is:ie,js:je) ) + allocate( ocean_ice_boundary%calving_hflx(is:ie,js:je) ) ! initialize boundary fields for override experiments (mjh) ocean_ice_boundary%u=0.0 ocean_ice_boundary%v=0.0 @@ -95,6 +97,8 @@ subroutine ice_ocean_flux_exchange_init(Time, Ice, Ocean, Ocean_state, ice_ocean ocean_ice_boundary%s=0.0 ocean_ice_boundary%frazil=0.0 ocean_ice_boundary%sea_level=0.0 + ocean_ice_boundary%calving=0.0 + ocean_ice_boundary%calving_hflx=0.0 ! allocate fields for extra tracers in ocean_ice_boundary if (.not.fms_coupler_type_initialized(ocean_ice_boundary%fields)) & @@ -221,7 +225,7 @@ end subroutine ice_ocean_flux_exchange_init !! fprec = mass of frozen precipitation since last !! time step (Kg/m2) !! runoff = mass of runoff since last time step (Kg/m2) - !! runoff = mass of calving since last time step (Kg/m2) + !! calving = mass of calving since last time step (Kg/m2) !! p_surf = surface pressure (Pa) !! subroutine flux_ice_to_ocean ( Time, Ice, Ocean, Ice_Ocean_Boundary ) @@ -371,7 +375,9 @@ end subroutine flux_ice_to_ocean_finish !! u_surf = zonal ocean current/ice motion (m/s) !! v_surf = meridional ocean current/ice motion (m/s) !! v_surf = meridional ocean current/ice motion (m/s) - !! sea_lev = sea level used to drive ice accelerations (m) + !! sea_lev = sea level used to drive ice accelerations (m) + !! calving = ice-sheet calving flux to ocean (kg m-2 s-1) + !! calving_hflx = heat flux associated with ice-sheet calving (W/m2) !! !! !! \throw FATAL, "Ocean_Ice_Boundary%xtype must be DIRECT or REDIST." @@ -408,6 +414,23 @@ subroutine flux_ocean_to_ice ( Time, Ocean, Ice, Ocean_Ice_Boundary ) endif endif + if( ASSOCIATED(Ocean_Ice_Boundary%calving) ) then + if(do_area_weighted_flux) then + Ocean_Ice_Boundary%calving = Ocean%calving * Ocean%area + call divide_by_area(data=Ocean_Ice_Boundary%calving, area=Ice%area) + else + Ocean_Ice_Boundary%calving = Ocean%calving + endif + endif + if( ASSOCIATED(Ocean_Ice_Boundary%calving_hflx) ) then + if(do_area_weighted_flux) then + Ocean_Ice_Boundary%calving_hflx = Ocean%calving_hflx * Ocean%area + call divide_by_area(data=Ocean_Ice_Boundary%calving_hflx, area=Ice%area) + else + Ocean_Ice_Boundary%calving_hflx = Ocean%calving_hflx + endif + endif + ! Extra fluxes call fms_coupler_type_copy_data(Ocean%fields, Ocean_Ice_Boundary%fields) @@ -438,6 +461,35 @@ subroutine flux_ocean_to_ice ( Time, Ocean, Ice, Ocean_Ice_Boundary ) else call fms_mpp_domains_redistribute(Ocean%Domain, Ocean%frazil, Ice%slow_Domain_NH, Ocean_Ice_Boundary%frazil) endif + endif + + if( ASSOCIATED(Ocean_Ice_Boundary%calving) ) then + if(do_area_weighted_flux) then + if (Ocean%is_ocean_pe) then + allocate(tmp(size(Ocean%area,1), size(Ocean%area,2))) + tmp(:,:) = Ocean%calving(:,:) * Ocean%area(:,:) + endif + call fms_mpp_domains_redistribute( Ocean%Domain, tmp, Ice%slow_Domain_NH, Ocean_Ice_Boundary%calving) + if (Ice%slow_ice_pe) & + call divide_by_area(data=Ocean_Ice_Boundary%calving, area=Ice%area) + if (Ocean%is_ocean_pe) deallocate(tmp) + else + call fms_mpp_domains_redistribute(Ocean%Domain, Ocean%calving, Ice%slow_Domain_NH, Ocean_Ice_Boundary%calving) + endif + endif + if( ASSOCIATED(Ocean_Ice_Boundary%calving_hflx) ) then + if(do_area_weighted_flux) then + if (Ocean%is_ocean_pe) then + allocate(tmp(size(Ocean%area,1), size(Ocean%area,2))) + tmp(:,:) = Ocean%calving_hflx(:,:) * Ocean%area(:,:) + endif + call fms_mpp_domains_redistribute( Ocean%Domain, tmp, Ice%slow_Domain_NH, Ocean_Ice_Boundary%calving_hflx) + if (Ice%slow_ice_pe) & + call divide_by_area(data=Ocean_Ice_Boundary%calving_hflx, area=Ice%area) + if (Ocean%is_ocean_pe) deallocate(tmp) + else + call fms_mpp_domains_redistribute(Ocean%Domain, Ocean%calving_hflx, Ice%slow_Domain_NH, Ocean_Ice_Boundary%calving_hflx) + endif endif ! Extra fluxes @@ -469,6 +521,9 @@ subroutine flux_ocean_to_ice_finish( Time, Ice, Ocean_Ice_Boundary ) call fms_data_override('ICE', 's', Ocean_Ice_Boundary%s, Time) call fms_data_override('ICE', 'frazil', Ocean_Ice_Boundary%frazil, Time) call fms_data_override('ICE', 'sea_level', Ocean_Ice_Boundary%sea_level, Time) + !Ice-shelf calving + call fms_data_override('ICE', 'IS_calving', Ocean_Ice_Boundary%calving, Time) + call fms_data_override('ICE', 'IS_calving_hflx', Ocean_Ice_Boundary%calving_hflx, Time) call fms_coupler_type_data_override('ICE', Ocean_Ice_Boundary%fields, Time) ! Perform diagnostic output for the ocean_ice_boundary fields From 1a1fb22876379a733492b4159dc5be06c266d5b0 Mon Sep 17 00:00:00 2001 From: alex-huth Date: Fri, 31 May 2024 17:23:34 -0400 Subject: [PATCH 2/4] make ice shelf calving parameters/routines public within full_coupler_mod.F90 --- full/full_coupler_mod.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/full/full_coupler_mod.F90 b/full/full_coupler_mod.F90 index 1ad27615..8930b029 100644 --- a/full/full_coupler_mod.F90 +++ b/full/full_coupler_mod.F90 @@ -102,6 +102,7 @@ module full_coupler_mod public :: update_land_model_fast, update_land_model_slow public :: update_ice_model_fast, set_ice_surface_fields public :: unpack_ocean_ice_boundary, exchange_slow_to_fast_ice + public :: unpack_ocean_ice_boundary_calved_shelf_bergs public :: ice_model_fast_cleanup, unpack_land_ice_boundary public :: exchange_fast_to_slow_ice, update_ice_model_slow public :: update_ocean_model, update_slow_ice_and_ocean @@ -219,7 +220,7 @@ module full_coupler_mod logical, public :: do_debug=.FALSE.!< If .TRUE. print additional debugging messages. integer, public :: check_stocks = 0 !< -1: never 0: at end of run only n>0: every n coupled steps logical, public :: use_hyper_thread = .false. - logical :: calve_ice_shelf_bergs = .false. !< If true, flux through a static ice front is converted + logical, public :: calve_ice_shelf_bergs = .false. !< If true, flux through a static ice front is converted !!to point bergs namelist /coupler_nml/ current_date, calendar, force_date_from_namelist, & From 7b315cfb348b126c8b4a51c665a7e7ca2f383bc5 Mon Sep 17 00:00:00 2001 From: alex-huth Date: Tue, 18 Jun 2024 10:02:30 -0400 Subject: [PATCH 3/4] add missing fms_mpp_clock_begin for iceberg calving from ice shelves --- full/coupler_main.F90 | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/full/coupler_main.F90 b/full/coupler_main.F90 index 5951bb4a..f80f2146 100644 --- a/full/coupler_main.F90 +++ b/full/coupler_main.F90 @@ -490,10 +490,11 @@ program coupler_main ! This call occurs all ice PEs. if (concurrent_ice) then call coupler_exchange_fast_to_slow_ice(Ice, coupler_clocks) - call fms_mpp_clock_begin(coupler_clocks%update_ice_model_slow_fast) - if (Ice%slow_ice_pe .and. calve_ice_shelf_bergs) & + if (Ice%slow_ice_pe .and. calve_ice_shelf_bergs) then + call fms_mpp_clock_begin(coupler_clocks%update_ice_model_slow_fast) call unpack_ocean_ice_boundary_calved_shelf_bergs(Ice, Ocean_ice_boundary) - call fms_mpp_clock_end(coupler_clocks%update_ice_model_slow_fast) + call fms_mpp_clock_end(coupler_clocks%update_ice_model_slow_fast) + endif endif ! call fms_mpp_set_current_pelist(Ice%pelist) is called if(.not.Ice%shared_slow_fast_PEs) @@ -738,9 +739,11 @@ program coupler_main ! This could be a point where the model is serialized; This calls on all ice PEs if (.not.concurrent_ice) then call coupler_exchange_fast_to_slow_ice(Ice, coupler_clocks, set_ice_current_pelist=.True.) - if (Ice%slow_ice_pe .and. calve_ice_shelf_bergs) & + if (Ice%slow_ice_pe .and. calve_ice_shelf_bergs) then + call fms_mpp_clock_begin(coupler_clocks%update_ice_model_slow_fast) call unpack_ocean_ice_boundary_calved_shelf_bergs(Ice, Ocean_ice_boundary) - call fms_mpp_clock_end(coupler_clocks%update_ice_model_slow_fast) + call fms_mpp_clock_end(coupler_clocks%update_ice_model_slow_fast) + endif endif ! ------ slow-ice model ------ From 7c82e91ff004c3642498144608d8f96d57453455 Mon Sep 17 00:00:00 2001 From: alex-huth Date: Wed, 21 Aug 2024 13:36:21 -0400 Subject: [PATCH 4/4] To reflect recent reorganization of coupler, moved calve_ice_shelf_bergs code to from coupler_main.F90 to full_coupler_mod.F90 --- full/coupler_main.F90 | 23 ++++++++++++----------- full/full_coupler_mod.F90 | 24 +++++++++++++++++++++--- full/ice_ocean_flux_exchange.F90 | 2 +- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/full/coupler_main.F90 b/full/coupler_main.F90 index a4ff6781..b3e9f649 100644 --- a/full/coupler_main.F90 +++ b/full/coupler_main.F90 @@ -278,6 +278,14 @@ !! the slow sea-ice processes are on the same PEs as the fast sea-ice. !! !! +!! calve_ice_shelf_bergs +!! logical +!! .FALSE. +!! If true, the ice sheet flux through a fixed ice-shelf front is +!! converted to icebergs, rather than initializing icebergs from frozen +!! freshwater discharge. +!! +!! !! restart_interval !! integer, dimension(6) !! (/0,0,0,0,0,0/) @@ -450,12 +458,8 @@ program coupler_main if (concurrent_ice) then !> This call occurs all ice PEs. call coupler_exchange_fast_to_slow_ice(Ice, coupler_clocks) - !> call fms_mpp_set_current_pelist(Ice%pelist) is called if(.not.Ice%shared_slow_fast_PEs) - if (Ice%slow_ice_pe .and. calve_ice_shelf_bergs) then - call fms_mpp_clock_begin(coupler_clocks%update_ice_model_slow_fast) - call unpack_ocean_ice_boundary_calved_shelf_bergs(Ice, Ocean_ice_boundary) - call fms_mpp_clock_end(coupler_clocks%update_ice_model_slow_fast) - endif + if (Ice%slow_ice_pe .and. calve_ice_shelf_bergs) & + call coupler_unpack_ocean_ice_boundary_calved_ice_shelf_bergs(Ice, Ocean_ice_boundary, coupler_clocks) endif if (Ice%fast_ice_pe) call coupler_set_ice_surface_fields(Ice, coupler_clocks) @@ -615,11 +619,8 @@ program coupler_main !> This could be a point where the model is serialized; This calls on all ice PEs if (.not.concurrent_ice) then call coupler_exchange_fast_to_slow_ice(Ice, coupler_clocks, set_ice_current_pelist=.True.) - if (Ice%slow_ice_pe .and. calve_ice_shelf_bergs) then - call fms_mpp_clock_begin(coupler_clocks%update_ice_model_slow_fast) - call unpack_ocean_ice_boundary_calved_shelf_bergs(Ice, Ocean_ice_boundary) - call fms_mpp_clock_end(coupler_clocks%update_ice_model_slow_fast) - endif + if (Ice%slow_ice_pe .and. calve_ice_shelf_bergs) & + call coupler_unpack_ocean_ice_boundary_calved_ice_shelf_bergs(Ice, Ocean_ice_boundary, coupler_clocks) endif !> slow-ice model !! This call occurs on whichever PEs handle the slow ice processess. diff --git a/full/full_coupler_mod.F90 b/full/full_coupler_mod.F90 index 011bc63b..79e4b0b9 100644 --- a/full/full_coupler_mod.F90 +++ b/full/full_coupler_mod.F90 @@ -101,7 +101,6 @@ module full_coupler_mod public :: update_slow_ice_and_ocean public :: send_ice_mask_sic public :: flux_ice_to_ocean_finish, flux_ice_to_ocean_stocks, flux_ocean_from_ice_stocks - public :: unpack_ocean_ice_boundary_calved_shelf_bergs public :: atmos_model_restart, land_model_restart, ice_model_restart, ocean_model_restart @@ -130,6 +129,7 @@ module full_coupler_mod public :: coupler_update_land_model_slow, coupler_flux_land_to_ice public :: coupler_unpack_land_ice_boundary, coupler_flux_ice_to_ocean + public :: coupler_unpack_ocean_ice_boundary_calved_ice_shelf_bergs public :: coupler_update_ice_model_slow_and_stocks, coupler_update_ocean_model public :: coupler_clock_type, coupler_components_type, coupler_chksum_type @@ -221,8 +221,9 @@ module full_coupler_mod logical, public :: do_debug=.FALSE.!< If .TRUE. print additional debugging messages. integer, public :: check_stocks = 0 !< -1: never 0: at end of run only n>0: every n coupled steps logical, public :: use_hyper_thread = .false. - logical, public :: calve_ice_shelf_bergs = .false. !< If true, flux through a static ice front is converted - !!to point bergs + logical, public :: calve_ice_shelf_bergs = .false. !< If true, the ice sheet flux through a fixed ice-shelf front is + !! converted to icebergs, rather than initializing icebergs from + !! frozen freshwater discharge namelist /coupler_nml/ current_date, calendar, force_date_from_namelist, & months, days, hours, minutes, seconds, dt_cpld, dt_atmos, & @@ -2311,6 +2312,23 @@ subroutine coupler_unpack_land_ice_boundary(Ice, Land_ice_boundary, coupler_cloc end subroutine coupler_unpack_land_ice_boundary + !> This subroutine calls unpack_ocean_ice_boundary_calved_shelf_bergs + subroutine coupler_unpack_ocean_ice_boundary_calved_ice_shelf_bergs(Ice, Ocean_ice_boundary, coupler_clocks) + + implicit none + type(ice_data_type), intent(inout) :: Ice !< Ice + type(ocean_ice_boundary_type), intent(inout) :: Ocean_ice_boundary !< Ocean_ice_boundary + type(coupler_clock_type), intent(inout) :: coupler_clocks !< coupler_clocks + + call fms_mpp_set_current_pelist(Ice%slow_pelist) + call fms_mpp_clock_begin(coupler_clocks%update_ice_model_slow_slow) + + call unpack_ocean_ice_boundary_calved_shelf_bergs(Ice, Ocean_ice_boundary) + + call fms_mpp_clock_end(coupler_clocks%update_ice_model_slow_slow) + + end subroutine coupler_unpack_ocean_ice_boundary_calved_ice_shelf_bergs + !> This subroutine calls update_ice_model_slow and flux_ice_to_ocean_stocks subroutine coupler_update_ice_model_slow_and_stocks(Ice, coupler_clocks) diff --git a/full/ice_ocean_flux_exchange.F90 b/full/ice_ocean_flux_exchange.F90 index d1821c44..3ab622dd 100644 --- a/full/ice_ocean_flux_exchange.F90 +++ b/full/ice_ocean_flux_exchange.F90 @@ -377,7 +377,7 @@ end subroutine flux_ice_to_ocean_finish !! v_surf = meridional ocean current/ice motion (m/s) !! v_surf = meridional ocean current/ice motion (m/s) !! sea_lev = sea level used to drive ice accelerations (m) - !! calving = ice-sheet calving flux to ocean (kg m-2 s-1) + !! calving = ice-sheet calving flux to ocean (kg/m2/s) !! calving_hflx = heat flux associated with ice-sheet calving (W/m2) !! !!