Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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 src/core_init_atmosphere/mpas_init_atm_cases.F
Original file line number Diff line number Diff line change
Expand Up @@ -8154,3 +8154,4 @@ end function read_text_array


end module init_atm_cases

40 changes: 35 additions & 5 deletions src/core_init_atmosphere/mpas_init_atm_vinterp.F
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ real (kind=RKIND) function vertical_interp(target_z, nz, zf, order, extrap, surf
real (kind=RKIND), intent(in), optional :: sealev_val
integer, intent(out), optional :: ierr

integer :: k, lm, lp
integer :: k, lm, lp, n_lapse
real (kind=RKIND) :: wm, wp
real (kind=RKIND) :: slope
real (kind=RKIND) :: sum_x, sum_y, sum_x2, sum_xy, n_real

integer :: interp_order, extrap_type
real (kind=RKIND) :: surface, sealevel
Expand Down Expand Up @@ -81,7 +82,22 @@ real (kind=RKIND) function vertical_interp(target_z, nz, zf, order, extrap, surf
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
vertical_interp = zf(2,1) - (target_z - zf(1,1))*0.0065
n_lapse = min(nz, 3)
sum_x = 0.0_RKIND; sum_y = 0.0_RKIND
sum_x2 = 0.0_RKIND; sum_xy = 0.0_RKIND
do k = 1, n_lapse
sum_x = sum_x + zf(1,k)
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 lapse-rate extrapolation for the lower boundary (target_z < zf(1,1)) used to apply a fixed standard lapse rate (0.0065 K/m). This change switches extrap_type==2 to a least-squares slope fit from the lowest 1–3 input levels, which is a behavioral change beyond the PR description (which focuses on missing upper boundary support). Please confirm this is intended; if not, keep the fixed lapse-rate behavior for the lower boundary (and implement the same for the upper boundary) or update the PR description/namelist documentation accordingly.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The hard-code 0.0065 K/m threshold is a field-specific constant that only produce a reasonable extrapolation when it is done for temperature in K. However, this is a field-agnostic function that is also used to extrapolate humidity, for example, which might produce unphysical extrapolated values. We will have a change in PR description before merging it.

sum_y = sum_y + zf(2,k)
sum_x2 = sum_x2 + zf(1,k)**2
sum_xy = sum_xy + zf(1,k)*zf(2,k)
end do
n_real = real(n_lapse, RKIND)
if (n_lapse > 1) then
slope = (n_real*sum_xy - sum_x*sum_y) / (n_real*sum_x2 - sum_x**2)
else
slope = 0.0_RKIND
end if
vertical_interp = zf(2,1) + slope * (target_z - zf(1,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 @@ -92,9 +108,22 @@ 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))
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
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
n_lapse = min(nz, 3)
sum_x = 0.0_RKIND; sum_y = 0.0_RKIND
sum_x2 = 0.0_RKIND; sum_xy = 0.0_RKIND
do k = nz - n_lapse + 1, nz
sum_x = sum_x + zf(1,k)
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 least-squares slope calculation for extrap_type==2 is duplicated in both the lower- and upper-boundary extrapolation branches. Consider extracting the slope computation into a small helper routine/function (or a shared local block) so future adjustments (e.g., number of points, guarding against degenerate z spacing) don’t need to be made in two places.

Copilot uses AI. Check for mistakes.
sum_y = sum_y + zf(2,k)
sum_x2 = sum_x2 + zf(1,k)**2
sum_xy = sum_xy + zf(1,k)*zf(2,k)
end do
n_real = real(n_lapse, RKIND)
if (n_lapse > 1) then
slope = (n_real*sum_xy - sum_x*sum_y) / (n_real*sum_x2 - sum_x**2)
else
slope = 0.0_RKIND
end if
vertical_interp = zf(2,nz) + slope * (target_z - zf(1,nz))
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 @@ -120,3 +149,4 @@ real (kind=RKIND) function vertical_interp(target_z, nz, zf, order, extrap, surf
end function vertical_interp

end module init_atm_vinterp

Loading