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

Adds internal ocean frazil ice porosity #6802

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions components/mpas-ocean/bld/build-namelist
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@ 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_ice_porosity');
add_default($nl, 'config_frazil_fractional_thickness_limit');
add_default($nl, 'config_specific_heat_sea_water');
add_default($nl, 'config_frazil_maximum_depth');
Expand Down
1 change: 1 addition & 0 deletions components/mpas-ocean/bld/build-namelist-section
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ 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_ice_porosity');
add_default($nl, 'config_frazil_fractional_thickness_limit');
add_default($nl, 'config_specific_heat_sea_water');
add_default($nl, 'config_frazil_maximum_depth');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@
<config_frazil_under_land_ice>.true.</config_frazil_under_land_ice>
<config_frazil_heat_of_fusion>3.337e5</config_frazil_heat_of_fusion>
<config_frazil_ice_density>1000.0</config_frazil_ice_density>
<config_frazil_ice_porosity>-1.0</config_frazil_ice_porosity>
<config_frazil_fractional_thickness_limit>0.1</config_frazil_fractional_thickness_limit>
<config_specific_heat_sea_water>3.996e3</config_specific_heat_sea_water>
<config_frazil_maximum_depth>100.0</config_frazil_maximum_depth>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1539,6 +1539,14 @@ Valid values: Any positive real number.
Default: Defined in namelist_defaults.xml
</entry>

<entry id="config_frazil_ice_porosity" type="real"
category="frazil_ice" group="frazil_ice">
Internal porosity of frazil

Valid values: Positive real number from 0 to 1. Negative value reverts to using the reference salinity for internal frazil.
Default: Defined in namelist_defaults.xml
</entry>

<entry id="config_frazil_fractional_thickness_limit" type="real"
category="frazil_ice" group="frazil_ice">
maximum fraction of layer thickness than can be used or created at an instant by frazil.
Expand Down
10 changes: 9 additions & 1 deletion components/mpas-ocean/src/Registry.xml
Original file line number Diff line number Diff line change
Expand Up @@ -984,11 +984,15 @@
<nml_option name="config_frazil_heat_of_fusion" type="real" default_value="3.34e5" units="J kg^-1"
description="Energy per kilogram released when sea water freezes. NOTE: test and make consistent with E3SM."
possible_values="Any positive real number."
/>
/>
<nml_option name="config_frazil_ice_density" type="real" default_value="1000.0" units="kg m^-3"
description="Assumed density of frazil. NOTE: test and make consistent with E3SM."
possible_values="Any positive real number."
/>
<nml_option name="config_frazil_ice_porosity" type="real" default_value="-1.0" units="1"
description="Internal porosity of frazil"
possible_values="Positive real number from 0 to 1. Negative value reverts to using the reference salinity for internal frazil."
/>
<nml_option name="config_frazil_fractional_thickness_limit" type="real" default_value="0.1" units="non-dimensional"
description="maximum fraction of layer thickness than can be used or created at an instant by frazil."
possible_values="Any positive real number between 0 and 1."
Expand Down Expand Up @@ -4076,6 +4080,10 @@
description="surface pressure forcing due to weight of frazil ice"
packages="frazilIce"
/>
<var name="lowSalinityFrazilIce" type="real" dimensions="nCells Time" units="kg m^-2"
description="min(0,AccumulatedFrazilIceMass * reference salinity - accumulatedFrazilIceSalinity), non-zero indicates possible non-conservation"
packages="frazilIce"
/>
<var name="frazilIceFreshwaterFlux" type="real" dimensions="nCells Time" units="kg m^-2 s^-1"
description="Flux of frazil ice mass through the ocean surface. Negative is defined as mass leaving the ocean."
packages="frazilIce"
Expand Down
56 changes: 43 additions & 13 deletions components/mpas-ocean/src/shared/mpas_ocn_frazil_forcing.F
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP
real (kind=RKIND), dimension(:,:), pointer :: frazilTemperatureTendency
real (kind=RKIND), dimension(:,:), pointer :: frazilSalinityTendency
real (kind=RKIND), dimension(:), pointer :: frazilSurfacePressure
real (kind=RKIND), dimension(:), pointer :: lowSalinityFrazilIce
integer, dimension(:), pointer :: landIceMask, landIceFloatingMask

integer :: iCell, k, nCells
Expand Down Expand Up @@ -390,7 +391,9 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP
integer, pointer :: indexSalinityPtr !< index in tracers array for salinity
integer :: indexTemperature !< index in tracers array for temperature
integer :: indexSalinity !< index in tracers array for salinity
integer :: kBottomFrazil ! k index where testing for frazil begins
integer :: kBottomFrazil ! k index where testing for frazil begins
integer :: usePorosity ! 1 when computing internal frazil salinity using porosity
! 0 when using config_frazil_sea_ice_reference_salinity

logical :: underFloatingLandIce, underLandIce ! indicates if we are under land ice

Expand Down Expand Up @@ -435,6 +438,7 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP
call mpas_pool_get_array(forcingPool, 'frazilSalinityTendency', frazilSalinityTendency)
call mpas_pool_get_array(forcingPool, 'frazilLayerThicknessTendency', frazilLayerThicknessTendency)
call mpas_pool_get_array(forcingPool, 'frazilSurfacePressure', frazilSurfacePressure)
call mpas_pool_get_array(forcingPool, 'lowSalinityFrazilIce', lowSalinityFrazilIce)
call mpas_pool_get_array(forcingPool, 'landIceMask', landIceMask)
call mpas_pool_get_array(forcingPool, 'landIceFloatingMask', landIceFloatingMask)
call mpas_pool_get_array(forcingPool, 'frazilIceFreshwaterFlux', frazilIceFreshwaterFlux)
Expand All @@ -448,6 +452,13 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP
frazilSalinityTendency = 0.0_RKIND
frazilLayerThicknessTendency = 0.0_RKIND

! initialize frazil salinity conservation field
lowSalinityFrazilIce = 0.0_RKIND

! Determine if using porosity to compute internal frazilSalinity
usePorosity = 1
if (config_frazil_ice_porosity < 0.0_RKIND) usePorosity = 0 ! use config_frazil_sea_ice_reference_salinity

! frazil fields are needed only over 0 and 1 halos
nCells = nCellsArray( 2 )

Expand All @@ -457,7 +468,7 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP
!$omp private(underFloatingLandIce, underLandIce, kBottomFrazil, columnTemperatureMin, k, sumNewFrazilIceThickness, &
!$omp sumNewThicknessWeightedSaltContent, oceanFreezingTemperature, potential, &
!$omp freezingEnergy, meltingEnergy, frazilSalinity, newFrazilIceThickness, &
!$omp newThicknessWeightedSaltContent, meltedFrazilIceThickness, &
!$omp newThicknessWeightedSaltContent, meltedFrazilIceThickness, lowSalinityFrazilIce, &
!$omp meltedThicknessWeightedSaltContent)
do iCell=1,nCells

Expand Down Expand Up @@ -489,7 +500,7 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP
! find deepest level where frazil can be created
kBottomFrazil=maxLevelCell(iCell)
do k=maxLevelCell(iCell), minLevelCell(iCell), -1
! add the ssh so frazil can form below land ice, where the ssh is depressed
! add the ssh so frazil can form below land ice, where the ssh is depressed
if (-zMid(k,iCell) < -ssh(iCell) + config_frazil_maximum_depth) then
kBottomFrazil=k
exit
Expand Down Expand Up @@ -529,9 +540,10 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP

! get frazil salinity
if (underLandIce) then
frazilSalinity = 0.0_RKIND
frazilSalinity = usePorosity * config_frazil_ice_porosity * activeTracers(indexSalinity, k, iCell)
else
frazilSalinity = config_frazil_sea_ice_reference_salinity
frazilSalinity = usePorosity * config_frazil_ice_porosity * activeTracers(indexSalinity, k, iCell) &
+ config_frazil_sea_ice_reference_salinity * (1 - usePorosity)
end if
frazilSalinity = min( frazilSalinity, activeTracers(indexSalinity, k, iCell) )

Expand All @@ -541,7 +553,6 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP
! limit the frazil formed appropriately
newFrazilIceThickness = min(newFrazilIceThickness, layerThickness(k,iCell) * config_frazil_fractional_thickness_limit)


! Determine new salt in frazil
newThicknessWeightedSaltContent = newFrazilIceThickness * frazilSalinity

Expand All @@ -564,7 +575,6 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP
sumNewThicknessWeightedSaltContent = sumNewThicknessWeightedSaltContent + newThicknessWeightedSaltContent

else

! ocean water is warm enough to melt frazil

! test to see if there is frazil to be melted
Expand Down Expand Up @@ -600,31 +610,51 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP
/ dt

! keep track of new frazil ice
sumNewThicknessWeightedSaltContent = sumNewThicknessWeightedSaltContent - meltedThicknessWeightedSaltContent
sumNewFrazilIceThickness = sumNewFrazilIceThickness - meltedFrazilIceThickness
sumNewThicknessWeightedSaltContent = max(0.0_RKIND,sumNewThicknessWeightedSaltContent - meltedThicknessWeightedSaltContent)
sumNewFrazilIceThickness = max(0.0_RKIND,sumNewFrazilIceThickness - meltedFrazilIceThickness)

endif ! if (sumNewFrazilIceThickness > 0.0_RKIND)

endif ! if (freezingEnergy < 0)

enddo ! do k=kBottom,minLevelCell,-1

! frazilIceFreshwaterFlux forms part of the landIceFreshwaterFluxTotal computed in surface land ice fluxes
frazilIceFreshwaterFlux(iCell) = - (sumNewFrazilIceThickness * config_frazil_ice_density) / dt
! accumulate frazil mass to column total
! note: the accumulatedFrazilIceMass (at both time levels) is reset to zero after being sent to the coupler
accumulatedFrazilIceMassNew(iCell) = accumulatedFrazilIceMassOld(iCell) + sumNewFrazilIceThickness &
* config_frazil_ice_density
accumulatedFrazilIceSalinityNew(iCell) = accumulatedFrazilIceSalinityOld(iCell) + sumNewThicknessWeightedSaltContent
* config_frazil_ice_density

accumulatedFrazilIceSalinityNew(iCell) = accumulatedFrazilIceSalinityOld(iCell) + &
(1-usePorosity) * sumNewThicknessWeightedSaltContent

!NJ: Assume frazil salinity is the coupling salinity
if ( underLandIce ) then
! frazilIceFreshwaterFlux forms part of the landIceFreshwaterFluxTotal computed in surface land ice fluxes
frazilIceFreshwaterFlux(iCell) = - (sumNewFrazilIceThickness * config_frazil_ice_density) / dt
! accumulate frazil formed under land ice in case we're not coupling and we need to keep track of it
! for freshwater budgets
accumulatedLandIceFrazilMassNew(iCell) = accumulatedLandIceFrazilMassOld(iCell) &
+ sumNewFrazilIceThickness * config_frazil_ice_density
! There is no accumulatedLandIceFrazilSalinity because it is always 0
frazilSalinity = 0.0_RKIND
else
frazilSalinity = config_frazil_sea_ice_reference_salinity
end if

!Determine salt expelled in the upper layer to arrive at the assumed frazil salt for coupling
if (sumNewFrazilIceThickness > 0.0_RKIND .and. usePorosity .ge. 1) then
newThicknessWeightedSaltContent = sumNewFrazilIceThickness * frazilSalinity
if (newThicknessWeightedSaltContent > sumNewThicknessWeightedSaltContent) then
!Warning: salt conservation error. Track with lowSalinityFrazilIce
lowSalinityFrazilIce(iCell) = newThicknessWeightedSaltContent - sumNewThicknessWeightedSaltContent
accumulatedFrazilIceSalinityNew(iCell) = accumulatedFrazilIceSalinityOld(iCell) + max(0.0_RKIND, sumNewThicknessWeightedSaltContent)
else
!salt expelled at the surface
frazilSalinityTendency(minLevelCell(iCell),iCell) = frazilSalinityTendency(minLevelCell(iCell),iCell) + &
max(0.0_RKIND,(sumNewThicknessWeightedSaltContent - newThicknessWeightedSaltContent) ) / dt
accumulatedFrazilIceSalinityNew(iCell) = accumulatedFrazilIceSalinityOld(iCell) + newThicknessWeightedSaltContent
endif
endif ! if frazil ice is formed
enddo ! do iCell = 1, nCells
!$omp end do
!$omp end parallel
Expand Down
Loading