Skip to content

Add SMB & SAT lapse rate feature#169

Open
matthewhoffman wants to merge 3 commits into
developfrom
matthewhoffman/mali/smb-lapse-rate
Open

Add SMB & SAT lapse rate feature#169
matthewhoffman wants to merge 3 commits into
developfrom
matthewhoffman/mali/smb-lapse-rate

Conversation

@matthewhoffman
Copy link
Copy Markdown

This PR implements a version of the ISMIP6 lapse rate adjustment for SMB and surface air temperature described here:
https://theghub.org/groups/ismip6/wiki/MainPage/ISMIP6ProjectionsGreenland?version=3
It is applied on every timestep (in contrast with ISMIP6 method to be applied once per year).

It also removes the config_surface_air_temperature_source='lapse' option, which has never been used. The new feature offers the same functionality and it would be unnecessarily complicated to support both ways of doing it.

The code supported calculating surface air temperature from a sea-level
reference temperature plus a lapse rate.  This option has never been
used and it would get complicated to support it along with the ismip6
lapse rate method, so I am removing it.
This commit implements a version of the ISMIP6 lapse rate adjustment
for SMB and surface air temperature described here:
https://theghub.org/groups/ismip6/wiki/MainPage/ISMIP6ProjectionsGreenland?version=3
It is applied on every timestep (in contrast with ISMIP6 method to be applied
once per year).
This commit revises the previous to ensure that we never modify
sfcMassBal so that is retains the input field.  All adjustments are made
to sfcMassBalApplied.
Also, rename li_apply_ismip6_atmosphere_forcing to
li_apply_atm_lapse_rate and update references
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Implements an ISMIP6-style elevation-change (lapse-rate) adjustment for surface mass balance (SMB) and surface air temperature (SAT) within MALI, and removes the legacy config_surface_air_temperature_source='lapse' pathway in favor of the new mechanism.

Changes:

  • Add li_apply_atm_lapse_rate to build lapse-rate-adjusted sfcMassBalApplied and surfaceAirTemperatureApplied, controlled by new namelist option config_apply_smb_sat_lapse_rate.
  • Switch physics consumers (thermal, tracer setup, calving restore, Albany mesh write) to use surfaceAirTemperatureApplied.
  • Extend Registry.xml with new lapse-rate/ref-elevation fields and remove the deprecated SAT lapse configuration option/description.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
components/mpas-albany-landice/src/mode_forward/mpas_li_advection.F Adds lapse-rate application routine; alters SMB application flow.
components/mpas-albany-landice/src/mode_forward/mpas_li_time_integration_fe_rk.F Calls lapse-rate application during the timestep sequence.
components/mpas-albany-landice/src/mode_forward/mpas_li_thermal.F Removes legacy SAT lapse option; uses applied SAT for thermal boundary condition.
components/mpas-albany-landice/src/mode_forward/mpas_li_calving.F Uses applied SAT during calving-front restore.
components/mpas-albany-landice/src/mode_forward/mpas_li_velocity_external.F Uses applied SAT in Albany ASCII mesh writing.
components/mpas-albany-landice/src/Registry.xml Adds new config + fields for SMB/SAT lapse-rate correction; removes old SAT lapse option.
Comments suppressed due to low confidence (2)

components/mpas-albany-landice/src/mode_forward/mpas_li_thermal.F:420

  • Thermal initialization still uses the raw surfaceAirTemperature to set initial surfaceTemperature/column temperatures (e.g., for config_temperature_init='linear' and 'sfc_air_temperature'). With the new lapse-rate feature, physics later uses surfaceAirTemperatureApplied, so runs with config_apply_smb_sat_lapse_rate=.true. can start from an initial thermal state that is inconsistent with the applied SAT. Consider computing/initializing surfaceAirTemperatureApplied during li_thermal_init and using it consistently for temperature initialization when lapse-rate adjustments are enabled.
         elseif (trim(config_temperature_init) == 'sfc_air_temperature') then

            allocate(pmpTemperatureCol(nVertLevels))
            do iCell = 1, nCellsSolve
               ! set the surface temperature to the surface air temperature or 273.15, whichever is less
               surfaceTemperature(iCell) = min(surfaceAirTemperature(iCell), kelvin_to_celsius)

               ! set the column temperature to surface air temp or PMP, whichever is less
               call pressure_melting_point_column(layerCenterSigma, thickness(iCell), pmpTemperatureCol)
               do k = 1, nVertLevels
                  temperature(k,iCell) = min(surfaceAirTemperature(iCell), pmpTemperatureCol(k) + kelvin_to_celsius)
               enddo

               ! set the basal temperature to surface air temp or PMP, whichever is less
               call pressure_melting_point(thickness(iCell), temperatureValue)
               basalTemperature(iCell) = min(surfaceAirTemperature(iCell), temperatureValue + kelvin_to_celsius)
            enddo
            deallocate(pmpTemperatureCol)

            waterFrac(:,:) = 0.0_RKIND

            if (config_print_thermal_info) then
               call mpas_log_write('Initialized ice column temperature to the surface air temperature')
            endif

         elseif (trim(config_temperature_init) == 'linear') then

            ! set up a linear temperature profile in each column
            ! T = surfaceAirTemperature at the ice surface, and T <= Tpmp at the bed

            ! initialize T = 273.15 K = 0 C everywhere

            temperature(:,:) = kelvin_to_celsius    ! = 273.15

            do iCell = 1, nCellsSolve

               call li_init_linear_temperature_in_column(&
                    nVertLevels,                   &
                    layerCenterSigma,              &
                    thickness(iCell),              &
                  surfaceAirTemperature(iCell),  &
                    temperature(:,iCell),          &
                    waterFrac(:,iCell),            &
                    surfaceTemperature(iCell),     &
                    basalTemperature(iCell))

components/mpas-albany-landice/src/mode_forward/mpas_li_advection.F:973

  • apply_mass_balance now reads from sfcMassBalApplied(iCell) (e.g., the zeroing/melt logic) without ever assigning it first. Since sfcMassBalApplied is declared intent(out), it is undefined on entry per Fortran semantics, and it is also mutated during the routine, so later RK stages can end up reusing a previously-modified value. Re-initialize sfcMassBalApplied at the top of this routine (or change the interface so an initialized “SMB-to-apply” field is passed as intent(in)/intent(inout) and recomputed each call) to ensure deterministic behavior across calls/stages.
      ! Initialize applied BMB field
      basalMassBalApplied(:) = basalMassBal(:)

      do iCell = 1, nCells

         ! initialize accumulation/ablation terms

         sfcAccum = 0.0_RKIND
         sfcAblat = 0.0_RKIND
         basalAccum = 0.0_RKIND
         basalAblat = 0.0_RKIND

         ! apply surface mass balance

         ! Zero out any positive surface mass balance for ice-free ocean cells
         if (sfcMassBalApplied(iCell) > 0.0_RKIND .and. &
            bedTopography(iCell) < config_sea_level .and. .not.(li_mask_is_ice(cellMask(iCell)) ) ) then
            sfcMassBalApplied(iCell) = 0.0_RKIND
         end if

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

! Thermal variables
call mpas_pool_get_array(thermalPool, 'temperature', temperature)
call mpas_pool_get_array(thermalPool, 'surfaceAirTemperature', surfaceAirTemperature)
call mpas_pool_get_array(thermalPool, 'surfaceAirTemperatureApplied', surfaceAirTemperature)
Comment on lines 252 to 259
! === Prepare for advection (including CFL checks) ===========
! This has to come first currently, because it sets the time step!
call li_apply_atm_lapse_rate(domain, err_tmp)
err = ior(err, err_tmp)

call mpas_timer_start("advection prep")
call prepare_advection(domain, err_tmp)
err = ior(err, err_tmp)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request testing needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants