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 5 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>0.85</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">
Assumed porosity of frazil

Valid values: Any positive real number from 0 to 1.
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="0.85" units="1"
description="Assumed porosity of frazil"
possible_values="Any positive real number from 0 to 1."
/>
Comment on lines +992 to +995
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should call this something other than porosity. When I hear porosity, I assume that the volume of frazil ice formed is only porosity * frazil ice thickness tendency (* areaCell) because part of the frazil ice tendency (the volume advected upward) is pure seawater. But my understanding of the implementation is really that this is expressing the salinity of the frazil as a fraction of the surrounding seawater (the ice formed and latent heat extracted is the full frazil ice thickness tendency). So I wonder if a less confusing name would be something like config_frazil_ice_salinity_fraction.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also got a bit confused by the use of "porosity". I think the use of that term was partly responsible for the confusion we had in our webex discussion a little while back. I seemingly couldn't let go of the idea that not just salt but seawater was being captured and transported by frazil in this approach.

<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
45 changes: 35 additions & 10 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 @@ -435,6 +436,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 +450,9 @@ 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

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

Expand All @@ -457,7 +462,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,12 +494,14 @@ 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
endif
enddo
!NJ: Compute frazil all through the column
!kBottomFrazil=max(maxLevelCell(iCell)-1,kBottomFrazil)

! find minimum temperature between 1:kBottomFrazil
columnTemperatureMin = 1.0e30_RKIND
Expand Down Expand Up @@ -525,13 +532,14 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP
freezingEnergy = max(0.0_RKIND, -potential)
meltingEnergy = max(0.0_RKIND, potential)

!NJ: Assume frazil ice retains salt until precipitating at the surface
if (freezingEnergy > 0) then

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

Expand All @@ -541,7 +549,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 +571,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,8 +606,8 @@ 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)

Expand All @@ -614,17 +620,36 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP
! 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

!NJ: Assume frazil salinity is the coupling salinity
if ( underLandIce ) then
! 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

!NJ: Determine salt expelled in the upper layer to arrive at the assumed frazil salt for coupling
if (sumNewFrazilIceThickness > 0.0_RKIND) then
newThicknessWeightedSaltContent = sumNewFrazilIceThickness * frazilSalinity
if (newThicknessWeightedSaltContent > sumNewThicknessWeightedSaltContent) then
!NJ: Warning: salt conservation error. Track with lowSalinityFrazilIce
lowSalinityFrazilIce(iCell) = newThicknessWeightedSaltContent - sumNewThicknessWeightedSaltContent
accumulatedFrazilIceSalinityNew(iCell) = accumulatedFrazilIceSalinityOld(iCell) + max(0.0_RKIND, sumNewThicknessWeightedSaltContent)
else
!NJ: 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
else
accumulatedFrazilIceSalinityNew(iCell) = accumulatedFrazilIceSalinityOld(iCell)
endif ! if frazil ice is formed
enddo ! do iCell = 1, nCells
!$omp end do
!$omp end parallel
Expand Down
Loading