Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 5 additions & 3 deletions src/core_init_atmosphere/mpas_init_atm_cases.F
Original file line number Diff line number Diff line change
Expand Up @@ -6882,6 +6882,7 @@ real (kind=RKIND) function vertical_interp(target_z, nz, zf, order, extrap, surf
integer :: k, lm, lp
real (kind=RKIND) :: wm, wp
real (kind=RKIND) :: slope
real (kind=RKIND) :: lapse_rate

integer :: interp_order, extrap_type
real (kind=RKIND) :: surface, sealevel
Expand Down Expand Up @@ -6933,9 +6934,9 @@ real (kind=RKIND) function vertical_interp(target_z, nz, zf, order, extrap, surf
slope = (zf(2,nz) - zf(2,nz-1)) / (zf(1,nz) - zf(1,nz-1))
vertical_interp = zf(2,nz) + slope * (target_z - zf(1,nz))
else if (extrap_type == 2) then
call mpas_log_write('extrap_type == 2 not implemented for target_z >= zf(1,nz)', messageType=MPAS_LOG_ERR)
if (present(ierr)) ierr = 1
return
! Lapse-rate extrapolation: calculate lapse rate from top two levels
lapse_rate = (zf(2,nz) - zf(2,nz-1)) / (zf(1,nz) - zf(1,nz-1))
vertical_interp = zf(2,nz) + lapse_rate * (target_z - zf(1,nz))
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

For extrap_type == 2 (lapse-rate) at the upper boundary, this change computes lapse_rate from the top two levels, which makes it effectively the same as extrap_type == 1 linear extrapolation. In this same function, the lower-boundary lapse-rate branch uses a fixed 0.0065 K/m (line 6926), so the upper and lower implementations are now inconsistent. Please align the two (either both fixed-lapse-rate or both gradient-derived) and ensure linear vs lapse-rate remain meaningfully different options.

Suggested change
! Lapse-rate extrapolation: calculate lapse rate from top two levels
lapse_rate = (zf(2,nz) - zf(2,nz-1)) / (zf(1,nz) - zf(1,nz-1))
vertical_interp = zf(2,nz) + lapse_rate * (target_z - zf(1,nz))
! Lapse-rate extrapolation: use fixed lapse rate (0.0065 K/m)
vertical_interp = zf(2,nz) - (target_z - zf(1,nz))*0.0065

Copilot uses AI. Check for mistakes.
end if
return
end if
Expand Down Expand Up @@ -7522,3 +7523,4 @@ end function read_text_array


end module init_atm_cases

24 changes: 23 additions & 1 deletion src/core_init_atmosphere/mpas_init_atm_vinterp.F
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module init_atm_vinterp
!
! Purpose:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
real (kind=RKIND) function vertical_interp(target_z, nz, zf, order, extrap, surface_val, sealev_val)
real (kind=RKIND) function vertical_interp(target_z, nz, zf, order, extrap, surface_val, sealev_val, ierr)

implicit none

Expand All @@ -33,10 +33,12 @@ real (kind=RKIND) function vertical_interp(target_z, nz, zf, order, extrap, surf
integer, intent(in), optional :: extrap
real (kind=RKIND), intent(in), optional :: surface_val
real (kind=RKIND), intent(in), optional :: sealev_val
integer, intent(out), optional :: ierr ! error code: 0 = success, 1 = invalid extrapolation type

integer :: k, lm, lp
real (kind=RKIND) :: wm, wp
real (kind=RKIND) :: slope
real (kind=RKIND) :: lapse_rate

integer :: interp_order, extrap_type
real (kind=RKIND) :: surface, sealevel
Expand Down Expand Up @@ -66,6 +68,11 @@ real (kind=RKIND) function vertical_interp(target_z, nz, zf, order, extrap, surf
sealevel = 201300.0
end if

! Initialize ierr to 0 (success)
if (present(ierr)) then
ierr = 0
end if

!
! Extrapolation required
!
Expand All @@ -75,6 +82,13 @@ real (kind=RKIND) function vertical_interp(target_z, nz, zf, order, extrap, surf
else if (extrap_type == 1) then
slope = (zf(2,2) - zf(2,1)) / (zf(1,2) - zf(1,1))
vertical_interp = zf(2,1) + slope * (target_z - zf(1,1))
else if (extrap_type == 2) then
! Lapse-rate extrapolation: calculate lapse rate from bottom two levels
lapse_rate = (zf(2,2) - zf(2,1)) / (zf(1,2) - zf(1,1))
vertical_interp = zf(2,1) + lapse_rate * (target_z - zf(1,1))
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

extrap_type == 2 (lapse-rate) is implemented here using the same formula as extrap_type == 1 (linear), i.e., a slope computed from the bottom two levels. That makes the new lapse-rate option behaviorally identical to linear extrapolation. If lapse-rate is intended to be a fixed temperature lapse rate (as in the other vertical_interp implementation in mpas_init_atm_cases.F), please apply that constant lapse rate here (or otherwise document/rename the option so it’s not indistinguishable from linear).

Copilot uses AI. Check for mistakes.
else
vertical_interp = zf(2,1)
if (present(ierr)) ierr = 1
end if
Comment on lines 84 to 88
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

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

The PR description focuses on adding missing upper-boundary support for extrap_type==2, but this diff also changes the lower-boundary extrap_type==2 behavior from a fixed 0.0065 K/m to a least-squares fitted slope from the lowest levels. Please update the PR description (and any user-facing docs for config_extrap_airtemp='lapse-rate') to reflect this broader behavior change.

Copilot uses AI. Check for mistakes.
return
end if
Expand All @@ -84,6 +98,13 @@ real (kind=RKIND) function vertical_interp(target_z, nz, zf, order, extrap, surf
else if (extrap_type == 1) then
slope = (zf(2,nz) - zf(2,nz-1)) / (zf(1,nz) - zf(1,nz-1))
vertical_interp = zf(2,nz) + slope * (target_z - zf(1,nz))
Comment on lines 78 to 96
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

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

In the extrapolation branches, the linear extrapolation path assumes nz >= 2 (accesses zf(:,2) / zf(:,nz-1)). If the caller provides only a single vertical level (e.g., nz==1), this becomes an out-of-bounds access. Please add an explicit nz < 2 fallback (e.g., treat as constant extrapolation and/or set ierr + log an error) before computing the slope for extrap_type == 1.

Copilot uses AI. Check for mistakes.
else if (extrap_type == 2) then
! Lapse-rate extrapolation: calculate lapse rate from top two levels
lapse_rate = (zf(2,nz) - zf(2,nz-1)) / (zf(1,nz) - zf(1,nz-1))
vertical_interp = zf(2,nz) + lapse_rate * (target_z - zf(1,nz))
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

Upper-boundary extrap_type == 2 uses a lapse rate computed from the top two levels, which is mathematically equivalent to the existing extrap_type == 1 linear extrapolation. If lapse-rate is meant to behave differently from linear (e.g., fixed -6.5 K/km), this should be adjusted so the two extrapolation modes are not duplicates.

Copilot uses AI. Check for mistakes.
else
vertical_interp = zf(2,nz)
if (present(ierr)) ierr = 1
end if
Comment on lines +78 to 101
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

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

The extrapolation if/else if chain has no final else to handle unexpected extrap_type values. If a caller passes something other than {0,1,2}, vertical_interp can be returned uninitialized while ierr remains 0. Please add a default branch that logs an error and sets ierr (and/or falls back to constant extrapolation).

Copilot uses AI. Check for mistakes.
return
end if
Expand All @@ -109,3 +130,4 @@ real (kind=RKIND) function vertical_interp(target_z, nz, zf, order, extrap, surf
end function vertical_interp

end module init_atm_vinterp

Loading