Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add temperature and salinity to ocean extrapolation #124

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
36 changes: 24 additions & 12 deletions components/mpas-albany-landice/src/Registry.xml
Original file line number Diff line number Diff line change
Expand Up @@ -454,16 +454,24 @@
possible_values="any non-negative value"
/>
<nml_option name="config_ocean_data_extrapolation" type="logical" default_value=".false." units="unitless"
description="If true, extrapolate ocean data (temperature, salinity, thermal forcing) from external source into underneath the ice draft."
description="If true, extrapolate ocean data (temperature and salinity, or thermal forcing) from external source into underneath the ice draft."
possible_values=".true. or .false."
/>
<nml_option name="config_recalculate_thermal_forcing" type="logical" default_value=".false." units="unitless"
description="If true, ocean temperature and salinity are extrapolated under ice drafts and to glacier termini, where thermal forcing is then calculated according to options inconfig_thermal_forcing_param_type. If false, MALI will look for an external thermal forcing field to extrapolate instead, and the subsequent 2d thermal forcing field will be defined at the grounding line. Option is only valid if config_ocean_data_extrapolation is true."
possible_values=".true. or .false."
/>
<nml_option name="config_TF_param_type" type="character" default_value="ISMIP6melt" units="unitless"
description="Name of ocean thermal forcing parameterization method, as outlined in Hager et al. (2024). 'ISMIP6retreat' and 'AMretreat' ignore bathymetry and icebergs during extrapolation. 'ISMIP6melt' and 'AMmelt' account for bathymetry in extrapolation. 'AMberg' accounts for bathymetry and iceberg meltwater in extrapolation. 'AM' indicates a depth averaged thermal forcing, while 'ISMIP6retreat uses an average thermal forcing between 200-500m depth, and thermal forcing in 'ISMIP6melt' is taken at the grounding line. A final option, 'AMfit' uses input field icebergFjordMask to assign 'AMberg' to iceberg-laden fjords, and 'AMmelt' otherwise."
possible_values="'ISMIP6retreat','AMretreat','ISMIP6melt','AMmelt','AMberg','AMfit'"
/>
<nml_option name="config_TF_iceberg_depth" type="real" default_value="-175.0" units="m"
description="Depth above which to iceberg meltwater is important. If config_TF_param_type is set to 'AMberg' or 'AMfit', water above this depth will be altered to follow the submarine meltwater mixing line. Default value is taken from Hager et al. (2024)."
possible_values="Any negative real value"
/>
<nml_option name="config_ocean_data_extrap_ncells_extra" type="integer" default_value="10" units="unitless"
description="number of extra cells for over-extrapolation into grounded ice" possible_values="any non-negative value"
/>
<nml_option name="config_invalid_value_TF" type="real" default_value="1.0e36" units="unitless"
description="value assigned to indicate invalid thermal forcing value when config_ocean_data_extrapolation is set to true"
possible_values="Any real value"
/>
<nml_option name="config_weight_value_cell" type="real" default_value="0.9" units="unitless"
description="weight used to smooth horizontal extrapolation of ocean data field. Value close to 1 implies more weight of the current cell value versus the averaged value of the neighbouring cells around the cell"
possible_values="any real value between 0 and 1"
Expand Down Expand Up @@ -810,6 +818,7 @@
<var name="ismip6Runoff" packages="ismip6GroundedFaceMelt" />
<var name="ismip6_2dThermalForcing" packages="ismip6GroundedFaceMelt" />
<var name="origOceanMaskHoriz" packages="extrapOceanData" />
<var name="orig3dOceanCavityMask" packages="extrapOceanData" /> <!-- CAS 8/16/2024 -->
</stream>

<!-- An alternate way to allow the HO variables to exist in a separate file.
Expand Down Expand Up @@ -915,15 +924,14 @@
<var name="ismip6_2dThermalForcingCurrent" packages="ismip6GroundedFaceMelt" />
<var name="forcingTimeStamp" packages="ismip6GroundedFaceMelt" />
<!-- these variables are just for the ocean thermal forcing re-extrapolation scheme -->
<var name="origOceanMaskHoriz" packages="extrapOceanData" />
<var name="origOceanMaskHoriz" packages="extrapOceanData" />
<var name="orig3dOceanCavityMask" packages="extrapOceanData" /> <!-- CAS 8/16/2024 -->
<var name="validOceanMask" packages="extrapOceanData" />
<var name="validOceanMaskOrig" packages="extrapOceanData" />
<var name="availOceanMask" packages="extrapOceanData" />
<var name="growOceanMaskHoriz" packages="extrapOceanData" />
<var name="seedOceanMaskHoriz" packages="extrapOceanData" />
<var name="seedOceanMaskHorizInit" packages="extrapOceanData" />
<var name="TFoceanOld" packages="extrapOceanData" />
<var name="TFocean" packages="extrapOceanData" />
</stream>


Expand Down Expand Up @@ -1689,6 +1697,10 @@ is the value of that variable from the *previous* time level!
<var name="origOceanMaskHoriz" type="integer" dimensions="nCells" units="none"
description="2D mask for original valid ocean data (e.g., ISMIP6 original TF data)"
/>
<!-- CAS 8/16/2024 -->
<var name="orig3dOceanCavityMask" type="integer" dimensions="nISMIP6OceanLayers nCells Time" units="none"
description="3D mask for original valid ocean data that includes cavities (e.g., SORRM original TF data)"
/>
<var name="validOceanMask" type="integer" dimensions="nISMIP6OceanLayers nCells Time" units="none"
description="3D mask for indicating where ocean data is present (i.e., seed mask)"
/>
Expand All @@ -1707,11 +1719,11 @@ is the value of that variable from the *previous* time level!
<var name="seedOceanMaskHorizInit" type="integer" dimensions="nCells Time" units="none"
description="initial 2D seedMask before the over-extrapolation, for benchmark/debug purpose"
/>
<var name="TFoceanOld" type="real" dimensions="nISMIP6OceanLayers nCells Time" units="deg. C"
default_value="1.0"
<var name="MPAS_3dOceanTemperature" type="real" dimensions="nISMIP6OceanLayers nCells Time" units="deg. C"
description="MPAS-Ocean potential temperature to be extrapolated to all grounding lines if config_recalcuate_thermal_forcing is true."
/>
<var name="TFocean" type="real" dimensions="nISMIP6OceanLayers nCells Time" units="deg. C"
default_value="0.0"
<var name="MPAS_3dOceanSalinity" type="real" dimensions="nISMIP6OceanLayers nCells Time" units="g/kg"
description="MPAS-Ocean salinity to be extrapolated to all grounding lines if config_recalcuate_thermal_forcing is true."
/>
</var_struct>
<!-- ================ -->
Expand Down
2 changes: 1 addition & 1 deletion components/mpas-albany-landice/src/mode_forward/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ mpas_li_velocity_external.o: Interface_velocity_solver.o

mpas_li_bedtopo.o: mpas_li_advection.o

mpas_li_ocean_extrap.o:
mpas_li_ocean_extrap.o: mpas_li_calving.o

Interface_velocity_solver.o:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1466,27 +1466,63 @@ subroutine grounded_face_melt_ismip6(domain, applyToGrounded, &
call mpas_pool_get_array(geometryPool, 'ismip6shelfMelt_zOcean', zOcean)
call mpas_pool_get_array(geometryPool, 'ismip6shelfMelt_deltaT', ismip6shelfMelt_deltaT)

! Calculate thermal forcing based on bedTopography
TFocean(:) = 0.0_RKIND
do iCell = 1, nCells
if (bedTopography(iCell) < 0.0_RKIND) then
kk = 1
! Find deepest zOcean above ocean floor
do while ( (zOcean(kk) >= bedTopography(iCell)) .and. (kk < nISMIP6OceanLayers) )
kk = kk + 1
!Consolidate 3d profile to 2d depending on parameterization type
if ( (config_recalculate_thermal_forcing) .and. ( (config_TF_param_type == 'AMretreat') &
.or. (config_TF_param_type == 'AMmelt') .or. (config_TF_param_type == 'AMberg') &
.or. (config_TF_param_type == 'AMfit') ) ) then
! Depth weighted average
TFocean(:) = 0.0_RKIND
do iCell = 1, nCells
dzAccumulated = 0.0_RKIND
do iLayer = 1, nISMIP6OceanLayers
if (bedTopography(iCell) >= ismip6shelfMelt_zOcean(iLayer)) then
dz = abs(ismip6shelfMelt_zBndsOcean(2,iLayer) - ismip6shelfMelt_zBndsOcean(1,iLayer))
TFocean(iCell) = (TFocean(iCell) * dzAccumulated + ismip6shelfMelt_3dThermalForcing(iLayer,iCell) * dz) &
/ (dzAccumulated + dz) + ismip6shelfMelt_deltaT(iCell)
dzAccumulated = dzAccumulated + dz
endif
enddo
! If bed is shallower than first layer, use TF from the first layer.
! If bed is deeper than the bottomg ocean layer, use TF from the bottom layer.
if ( (kk == 1) .or. ( (kk == nISMIP6OceanLayers) .and. (zOcean(kk) >= bedTopography(iCell)) ) ) then
TFocean(iCell) = ismip6shelfMelt_3dThermalForcing(kk, iCell) + ismip6shelfMelt_deltaT(iCell)
! For all other bed depths, interpolate linearly between layers above and below bed depth.
else
TFocean(iCell) = ( (zOcean(kk-1) - bedTopography(iCell)) * ismip6shelfMelt_3dThermalForcing(kk, iCell) + &
enddo

elseif ( (config_recalculate_thermal_forcing) .and. (config_TF_param_type == 'ISMIP6retreat') ) then
! simple average between 200-500m
TFocean(:) = 0.0_RKIND
do iCell = 1, nCells
total = 0.0_RKIND
counter = 0
do iLayer = 1, nISMIP6OceanLayers
if ( (ismip6shelfMelt_zOcean(iLayer) >= 200.0_RKIND) .and. ( ismip6shelfMelt_zOcean(iLayer) <= 500.0_RKIND) &
.and. (bedTopography(iCell) >= ismip6shelfMelt_zOcean(iLayer))) then
total = ismip6shelfMelt_3dThermalForcing(iLayer,iCell) + total
counter = counter + 1
endif
enddo
TFocean(iCell) = total/counter + ismip6shelfMelt_deltaT(iCell)
enddo

elseif ( (config_TF_param_type == 'ISMIP6melt') .or. (.not. config_recalculate_thermal_forcing) ) then
! Calculate thermal forcing based solely on bedTopography. Default ISMIP6 method and ISMIP6melt are equivalent
TFocean(:) = 0.0_RKIND
do iCell = 1, nCells
if (bedTopography(iCell) < 0.0_RKIND) then
kk = 1
! Find deepest zOcean above ocean floor
do while ( (zOcean(kk) >= bedTopography(iCell)) .and. (kk < nISMIP6OceanLayers) )
kk = kk + 1
enddo
! If bed is shallower than first layer, use TF from the first layer.
! If bed is deeper than the bottomg ocean layer, use TF from the bottom layer.
if ( (kk == 1) .or. ( (kk == nISMIP6OceanLayers) .and. (zOcean(kk) >= bedTopography(iCell)) ) ) then
TFocean(iCell) = ismip6shelfMelt_3dThermalForcing(kk, iCell) + ismip6shelfMelt_deltaT(iCell)
! For all other bed depths, interpolate linearly between layers above and below bed depth.
else
TFocean(iCell) = ( (zOcean(kk-1) - bedTopography(iCell)) * ismip6shelfMelt_3dThermalForcing(kk, iCell) + &
(bedTopography(iCell) - zOcean(kk)) * ismip6shelfMelt_3dThermalForcing(kk-1, iCell) ) / &
(zOcean(kk-1) - zOcean(kk)) + ismip6shelfMelt_deltaT(iCell)
endif
endif
enddo
endif
end do
endif

faceMeltSpeed(:) = 0.0_RKIND
Expand Down
Loading