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

Skip using fluxes provided by land component for first time step #234

Open
wants to merge 5 commits into
base: ufs/dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 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
6 changes: 4 additions & 2 deletions physics/SFC_Models/Land/Noahmp/noahmpdrv.F90
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,8 @@ end subroutine noahmpdrv_finalize
subroutine noahmpdrv_run &
!...................................
! --- inputs:
( im, km, lsnowl, itime, ps, u1, v1, t1, q1, soiltyp,soilcol,&
( im, km, lsnowl, itime, flag_init, ps, u1, v1, t1, q1, &
soiltyp,soilcol, &
vegtype, sigmaf, dlwflx, dswsfc, snet, delt, tg3, cm, ch, &
prsl1, prslk1, prslki, prsik1, zf,pblh, dry, wind, slopetyp,&
shdmin, shdmax, snoalb, sfalb, flag_iter,con_g, &
Expand Down Expand Up @@ -526,6 +527,7 @@ subroutine noahmpdrv_run &
integer , intent(in) :: km ! vertical soil layer dimension
integer , intent(in) :: lsnowl ! lower bound for snow level arrays
integer , intent(in) :: itime ! NOT USED
logical , intent(in) :: flag_init ! flag signaling first time step
real(kind=kind_phys), dimension(:) , intent(in) :: ps ! surface pressure [Pa]
real(kind=kind_phys), dimension(:) , intent(in) :: u1 ! u-component of wind [m/s]
real(kind=kind_phys), dimension(:) , intent(in) :: v1 ! u-component of wind [m/s]
Expand Down Expand Up @@ -986,7 +988,7 @@ subroutine noahmpdrv_run &
!
! --- Just return if external land component is activated for two-way interaction
!
if (cpllnd .and. cpllnd2atm) return
if (cpllnd .and. cpllnd2atm .and. (.not. flag_init)) return
Copy link
Collaborator

@barlage barlage Dec 19, 2024

Choose a reason for hiding this comment

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

@uturuncoglu I'm a little confused at the logic now. I thought with the new approach that we wouldn't need to call ccpp noahmp at all. Isn't this saying that with the land component, on the first time step we need to run the ccpp noahmp?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@barlage let me check this part again. I might need to remove (.not. flag_init) since I think it is not neccecary. The logic is that the sfc_land will calculate the fluxes internally in the initial step (if it is cold run) and after that will get the fluxes from component model.

Copy link
Collaborator

Choose a reason for hiding this comment

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

that was my main point, that the changes to noahmpdrv.F90 and .meta don't seem necessary anymore.


do i = 1, im

Expand Down
7 changes: 7 additions & 0 deletions physics/SFC_Models/Land/Noahmp/noahmpdrv.meta
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,13 @@
dimensions = ()
type = integer
intent = in
[flag_init]
standard_name = flag_for_first_timestep
long_name = flag signaling first time step for time integration loop
units = flag
dimensions = ()
type = logical
intent = in
[ps]
standard_name = surface_air_pressure
long_name = surface pressure
Expand Down
114 changes: 89 additions & 25 deletions physics/SFC_Models/Land/sfc_land.F90
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
module sfc_land

use machine, only : kind_phys
use funcphys, only : fpvs

contains

Expand All @@ -28,22 +29,41 @@ module sfc_land
!! \section general General Algorithm
!! \section detailed Detailed Algorithm
!! @{
subroutine sfc_land_run(im, cpllnd, cpllnd2atm, flag_iter, dry, &
sncovr1_lnd, qsurf_lnd, evap_lnd, hflx_lnd, &
ep_lnd, t2mmp_lnd, q2mp_lnd, gflux_lnd, &
subroutine sfc_land_run(im, flag_init, flag_restart, &
cpllnd, cpllnd2atm, flag_iter, dry, &
t1, q1, prsl1, prslki, ps, tskin, wind, cm, ch, rd, eps, epsm1, &
rvrdm1, hvap, cp, sncovr1_lnd, qsurf_lnd, &
evap_lnd, hflx_lnd, ep_lnd, t2mmp_lnd, q2mp_lnd, gflux_lnd, &
runoff_lnd, drain_lnd, cmm_lnd, chh_lnd, zvfun_lnd, &
sncovr1, qsurf, evap, hflx, ep, t2mmp, q2mp, &
gflux, runoff, drain, cmm, chh, zvfun, &
errmsg, errflg)
errmsg, errflg, naux2d, aux2d)

implicit none

! Inputs
integer , intent(in) :: im
logical , intent(in) :: cpllnd
logical , intent(in) :: cpllnd2atm
logical , intent(in) :: flag_iter(:)
logical , intent(in) :: dry(:)
integer , intent(in) :: im
logical , intent(in) :: flag_init
logical , intent(in) :: flag_restart
logical , intent(in) :: cpllnd
logical , intent(in) :: cpllnd2atm
logical , intent(in) :: flag_iter(:)
logical , intent(in) :: dry(:)
real(kind=kind_phys), intent(in) :: t1(:)
real(kind=kind_phys), intent(in) :: q1(:)
real(kind=kind_phys), intent(in) :: prsl1(:)
real(kind=kind_phys), intent(in) :: prslki(:)
real(kind=kind_phys), intent(in) :: ps(:)
real(kind=kind_phys), intent(in) :: tskin(:)
real(kind=kind_phys), intent(in) :: wind(:)
real(kind=kind_phys), intent(in) :: cm(:)
real(kind=kind_phys), intent(in) :: ch(:)
real(kind=kind_phys), intent(in) :: rd
real(kind=kind_phys), intent(in) :: eps
real(kind=kind_phys), intent(in) :: epsm1
real(kind=kind_phys), intent(in) :: rvrdm1
real(kind=kind_phys), intent(in) :: hvap
real(kind=kind_phys), intent(in) :: cp
real(kind=kind_phys), intent(in), optional :: sncovr1_lnd(:)
real(kind=kind_phys), intent(in), optional :: qsurf_lnd(:)
real(kind=kind_phys), intent(in), optional :: evap_lnd(:)
Expand Down Expand Up @@ -75,32 +95,76 @@ subroutine sfc_land_run(im, cpllnd, cpllnd2atm, flag_iter, dry, &
character(len=*) , intent(out) :: errmsg
integer , intent(out) :: errflg

! Constant parameters
real(kind=kind_phys), parameter :: &
& one = 1.0_kind_phys, &
& zero = 0.0_kind_phys, &
& qmin = 1.0e-8_kind_phys

! Locals
integer :: i
real(kind=kind_phys) :: qss, rch, tem, cpinv, hvapi, elocp
real(kind=kind_phys), dimension(im) :: rho, q0

! Initialize CCPP error handling variables
errmsg = ''
errflg = 0

cpinv = one/cp
hvapi = one/hvap
elocp = hvap/cp

! Check coupling from component land to atmosphere
if (.not. cpllnd2atm) return

! Fill variables
do i = 1, im
sncovr1(i) = sncovr1_lnd(i)
qsurf(i) = qsurf_lnd(i)
hflx(i) = hflx_lnd(i)
evap(i) = evap_lnd(i)
ep(i) = ep_lnd(i)
t2mmp(i) = t2mmp_lnd(i)
q2mp(i) = q2mp_lnd(i)
gflux(i) = gflux_lnd(i)
drain(i) = drain_lnd(i)
runoff(i) = runoff_lnd(i)
cmm(i) = cmm_lnd(i)
chh(i) = chh_lnd(i)
zvfun(i) = zvfun_lnd(i)
enddo
! Check if it is cold or warm run
if (flag_init .and. .not. flag_restart) then
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@barlage I add this part to calculate land fluxes in the first time step. Let me know if you see any issue with it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

this makes sense to me

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@barlage The part that calculated land fluxes internally is producing very large values for latent and sensible heat flux. I am trying to debug it but it might be related to the way of calculation of qss (not sure now). Since this is based on sfc_ocean it might need to have some adjustment. Any suggestion?

Copy link
Collaborator

Choose a reason for hiding this comment

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

@uturuncoglu I was hoping we could get away with this simple approximation but perhaps there needs to be a constraint added based on available energy. Typically when this approach is used in the land model, there is an adjustment to qss for stomatal and soil evap resistance. What is being done here is essentially like a ponded surface, but I wouldn't think that would produce unreasonable values (though this could be happening over hot soils where the qss could get very large). In the land model, LH and SH are constrained by available energy, which we don't have here (neither does sfc_ocean), also we are considering them here to be independent, which they also aren't in the land model. But again, none of this should produce "very large" values, unless there is an initialization issue with some of the inputs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@barlage it seems that qss = fpvs(tskin(i)) is returning very large value for me even if tskin is in the range. Maybe we need to use another function. The values like 1442 is produced with curent version. Any idea?

Copy link
Collaborator

Choose a reason for hiding this comment

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

@uturuncoglu the qss coming from the function is vapor pressure in Pascals so 1400 is not unreasonable, it's the equivalent of about 0.009 kg/kg specific humidity

Copy link
Collaborator

Choose a reason for hiding this comment

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

If you are saying both fluxes are large, then I'm wondering if it's something with the input ch values

! Calculate fluxes internally
do i = 1, im
if (dry(i)) then
q0(i) = max(q1(i), qmin)
rho(i) = prsl1(i)/(rd*t1(i)*(one+rvrdm1*q0(i)))
qss = fpvs(tskin(i))
qss = eps*qss/(ps(i)+epsm1*qss)
rch = rho(i)*cp*ch(i)*wind(i)
tem = ch(i)*wind(i)
sncovr1(i) = zero
qsurf(i) = qss
hflx(i) = rch*(tskin(i)-t1(i)*prslki(i))
hflx(i) = hflx(i)*(1.0/rho(i))*cpinv
evap(i) = elocp*rch*(qss-q0(i))
ep(i) = evap(i)
evap(i) = evap(i)*(1.0/rho(i))*hvapi
t2mmp(i) = tskin(i)
q2mp(i) = qsurf(i)
gflux(i) = zero
drain(i) = zero
runoff(i) = zero
cmm(i) = cm(i)*wind(i)
chh(i) = rho(i)*tem
zvfun(i) = one
end if
enddo
else
! Use fluxes from land component model
do i = 1, im
if (dry(i)) then
sncovr1(i) = sncovr1_lnd(i)
qsurf(i) = qsurf_lnd(i)
hflx(i) = hflx_lnd(i)
evap(i) = evap_lnd(i)
ep(i) = ep_lnd(i)
t2mmp(i) = t2mmp_lnd(i)
q2mp(i) = q2mp_lnd(i)
gflux(i) = gflux_lnd(i)
drain(i) = drain_lnd(i)
runoff(i) = runoff_lnd(i)
cmm(i) = cmm_lnd(i)
chh(i) = chh_lnd(i)
zvfun(i) = zvfun_lnd(i)
end if
enddo
endif

end subroutine sfc_land_run

Expand Down
136 changes: 135 additions & 1 deletion physics/SFC_Models/Land/sfc_land.meta
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[ccpp-table-properties]
name = sfc_land
type = scheme
dependencies = ../../hooks/machine.F
dependencies = ../../tools/funcphys.f90,../../hooks/machine.F

########################################################################
[ccpp-arg-table]
Expand All @@ -14,6 +14,20 @@
dimensions = ()
type = integer
intent = in
[flag_init]
standard_name = flag_for_first_timestep
long_name = flag signaling first time step for time integration loop
units = flag
dimensions = ()
type = logical
intent = in
[flag_restart]
standard_name = flag_for_restart
long_name = flag for restart (warmstart) or coldstart
units = flag
dimensions = ()
type = logical
intent = in
[cpllnd]
standard_name = flag_for_land_coupling
long_name = flag controlling cpllnd collection (default off)
Expand Down Expand Up @@ -42,6 +56,126 @@
dimensions = (horizontal_loop_extent)
type = logical
intent = in
[t1]
standard_name = air_temperature_at_surface_adjacent_layer
long_name = surface layer mean temperature
units = K
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
intent = in
[q1]
standard_name = specific_humidity_at_surface_adjacent_layer
long_name = surface layer mean specific humidity
units = kg kg-1
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
intent = in
[ps]
standard_name = surface_air_pressure
long_name = surface pressure
units = Pa
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
intent = in
[prsl1]
standard_name = air_pressure_at_surface_adjacent_layer
long_name = surface layer mean pressure
units = Pa
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
intent = in
[prslki]
standard_name = ratio_of_exner_function_between_midlayer_and_interface_at_lowest_model_layer
long_name = Exner function ratio bt midlayer and interface at 1st layer
units = ratio
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
intent = in
[tskin]
standard_name = surface_skin_temperature_over_land
long_name = surface skin temperature over land
units = K
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
intent = in
[wind]
standard_name = wind_speed_at_lowest_model_layer
long_name = wind speed at lowest model level
units = m s-1
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
intent = in
[cm]
standard_name = surface_drag_coefficient_for_momentum_in_air_over_land
long_name = surface exchange coeff for momentum over land
units = none
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
intent = in
[ch]
standard_name = surface_drag_coefficient_for_heat_and_moisture_in_air_over_land
long_name = surface exchange coeff heat & moisture over land
units = none
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
intent = in
[eps]
standard_name = ratio_of_dry_air_to_water_vapor_gas_constants
long_name = rd/rv
units = none
dimensions = ()
type = real
kind = kind_phys
intent = in
[epsm1]
standard_name = ratio_of_dry_air_to_water_vapor_gas_constants_minus_one
long_name = (rd/rv) - 1
units = none
dimensions = ()
type = real
kind = kind_phys
intent = in
[rvrdm1]
standard_name = ratio_of_vapor_to_dry_air_gas_constants_minus_one
long_name = (rv/rd) - 1 (rv = ideal gas constant for water vapor)
units = none
dimensions = ()
type = real
kind = kind_phys
intent = in
[rd]
standard_name = gas_constant_of_dry_air
long_name = ideal gas constant for dry air
units = J kg-1 K-1
dimensions = ()
type = real
kind = kind_phys
intent = in
[hvap]
standard_name = latent_heat_of_vaporization_of_water_at_0C
long_name = latent heat of evaporation/sublimation
units = J kg-1
dimensions = ()
type = real
kind = kind_phys
intent = in
[cp]
standard_name = specific_heat_of_dry_air_at_constant_pressure
long_name = specific heat of dry air at constant pressure
units = J kg-1 K-1
dimensions = ()
type = real
kind = kind_phys
intent = in
[sncovr1_lnd]
standard_name = surface_snow_area_fraction_over_land_from_land
long_name = surface snow area fraction over land for coupling
Expand Down