Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
fe8aa45
Add NVP control switches
huitang-earth Apr 9, 2026
b635d4e
Add control switches in namelist definition.
huitang-earth Apr 9, 2026
f53ed36
Initialize a module for NVP layer dynamics and water balance.
huitang-earth Apr 10, 2026
8f5d482
Define NVP layer controllers and variables.
huitang-earth Apr 10, 2026
6f677b7
Pass NVP namelist control to FATES.
huitang-earth Apr 10, 2026
2043eaa
Add centralized parameter module for NVP (temporal solution).
huitang-earth Apr 10, 2026
3711441
Add NVP radiation related variables and parameters.
huitang-earth Apr 10, 2026
a1955f9
Add NVP radiation related variables into history output field.
huitang-earth Apr 10, 2026
e259d4b
Add NVP-enabled SNICAR_RT call.
huitang-earth Apr 10, 2026
80ca26e
Add NVP colum filter which can be used for NVP column loops.
huitang-earth Apr 10, 2026
78ef7a0
Add NVP namelist settings (temporary)
huitang-earth Apr 10, 2026
79cbded
Allow NVP optical properties to be ported into bottom snow layer (lay…
huitang-earth Apr 10, 2026
64bf7b1
Add NVP light absorption for both snow and no-snow case
huitang-earth Apr 10, 2026
2990172
Add NVP radiation wapper for FATES
huitang-earth Apr 10, 2026
a2cf476
Add FATES wrapper for dynamic NVP layer
huitang-earth Apr 10, 2026
84e0ed8
Add NVP temperature state variable t_nvp_col.
huitang-earth Apr 10, 2026
0481b00
Accomdate NVP as layer 0 (snow layer) in soil-snow temperature integ…
huitang-earth Apr 10, 2026
ceedb0f
Add NVP sensible heat flux.
huitang-earth Apr 10, 2026
85fb103
Add NVP sensible and latent heat flux .
huitang-earth Apr 11, 2026
5b1eaf4
Add surface humidity calculation for NVP (similar to soil).
huitang-earth Apr 11, 2026
522d8f5
Add influence of ice content on NVP water retention.
huitang-earth Apr 11, 2026
fea0c85
Add NVP water state variable.
huitang-earth Apr 12, 2026
6caec1b
Add NVP water flux variables.
huitang-earth Apr 12, 2026
56a9757
Add diagnostic NVP water variables.
huitang-earth Apr 12, 2026
5d4c676
Add NVP surface specific humidity.
huitang-earth Apr 12, 2026
b8109a6
Modify soil surface water flux due to NVP presence.
huitang-earth Apr 12, 2026
85d56f9
Add NVP layer water balance calculation.
huitang-earth Apr 12, 2026
50c6bf8
Add NVP photosynthesis wrapper.
huitang-earth Apr 12, 2026
922ab69
Add separate photosynthesis call for NVP.
huitang-earth Apr 12, 2026
6b68bdc
Add call for building NVP filter.
huitang-earth Apr 12, 2026
09c5ad0
Add patch to column integration for NVP evaporation flux.
huitang-earth Apr 12, 2026
d05b7e3
Add restart option for NVP layer.
huitang-earth Apr 12, 2026
ec18da5
Remove redundant update of flx _absdv and flx_absiv for NVP layer whe…
huitang-earth Apr 21, 2026
2bfdf63
Fixing bugs during compiling phase, no scientific changes.
huitang-earth Apr 26, 2026
bc302be
Improve treatment when water in NVP becomes ice.
huitang-earth Apr 28, 2026
6f1096a
Separate 'use_nvp' and 'col%nvp_layer'-related variables in the if st…
huitang-earth Apr 28, 2026
16945c6
Add NVP resitance to evaporation into Canopy and bareground flux calc…
huitang-earth Apr 28, 2026
c051fb8
Revert "Add NVP resitance to evaporation into Canopy and bareground f…
huitang-earth Apr 28, 2026
01641f4
NVP bug fix: always set a valid value for t_nvp_col.
huitang-earth Apr 30, 2026
5f4fd3b
Add debugging output to log files.
huitang-earth Apr 30, 2026
683a86a
Point FATES at Hui Tang's branch, commit 49c247b39.
samsrabin May 1, 2026
cda744e
NVP bug fix: add 'use_nvp' guard for calculating top soil layer infil…
huitang-earth May 3, 2026
6ed45f0
Merge remote-tracking branch 'tang_ssh/ctsm5.4.028_nvp'
huitang-earth May 4, 2026
2513aaf
bug fix: avoid too large hs values for h2osfc, when it is absent.
huitang-earth May 6, 2026
4156a30
Fix git-fleximod FATES
samsrabin May 10, 2026
f183b46
use_nvp now actually default false.
samsrabin May 11, 2026
dae7fe4
NVP namelist vars now handled in CLMBuildNamelist.pm.
samsrabin May 11, 2026
d39516d
Disable the use of canopy_fraction_pa for calculating frac_nvp(c) for…
huitang-earth May 12, 2026
c33254d
Use jbot_sno(c)==-1 directly (not filter_nvpc) so this can run on the…
huitang-earth May 12, 2026
d61e55f
Set qflx_ev_nvp(p) = 0._r8 when NVP is buried under snow
huitang-earth May 12, 2026
4423d8e
Exclude the NVP slot from snow hydrological calculations.
huitang-earth May 12, 2026
a142abc
Set nvp evaporation to 0 for its water balance calculation when it is…
huitang-earth May 12, 2026
4ec436d
Avoid NVP evap flux calculation when buried undersnow.
huitang-earth May 12, 2026
9670a66
Avoid NVP evap and heat flux calculation when buried undersnow (bareg…
huitang-earth May 12, 2026
5c42e3e
Key NVP bug fix: Set NVP area fraction — zero when NVP buried under s…
huitang-earth May 12, 2026
ad9c5fd
Write NVP debugging output to log files.
huitang-earth May 12, 2026
b1ac7a4
Merge remote-tracking branch 'tang_ssh/ctsm5.4.028_nvp'
huitang-earth May 12, 2026
c3a977a
Update FATES: Avoid unconditional minimum elai and esai for NVP.
samsrabin May 13, 2026
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
4 changes: 2 additions & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
#
[submodule "fates"]
path = src/fates
url = https://github.com/NGEET/fates
fxtag = sci.1.91.1_api.43.1.0
url = https://github.com/huitang-earth/fates
fxtag = b267a73b621b2156d3d6e3ae9289f1f43ca6fb0e
fxrequired = AlwaysRequired
# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed
fxDONOTUSEurl = https://github.com/NGEET/fates
Expand Down
7 changes: 5 additions & 2 deletions bld/CLMBuildNamelist.pm
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,8 @@ sub setup_cmdl_fates_mode {
"use_fates_daylength_factor", "fates_photosynth_acclimation", "fates_stomatal_model",
"fates_stomatal_assimilation", "fates_leafresp_model", "fates_cstarvation_model",
"fates_regeneration_model", "fates_hydro_solver", "fates_radiation_model", "fates_electron_transport_model",
"use_fates_managed_fire"
"use_fates_managed_fire",
"use_nvp", "use_nvp_undersnow", "nvp_rad_model_ground"
);

# dis-allow fates specific namelist items with non-fates runs
Expand Down Expand Up @@ -4887,7 +4888,8 @@ sub setup_logic_fates {
"use_fates_daylength_factor", "fates_photosynth_acclimation", "fates_stomatal_model",
"fates_stomatal_assimilation", "fates_leafresp_model", "fates_cstarvation_model",
"fates_regeneration_model", "fates_hydro_solver", "fates_radiation_model", "fates_electron_transport_model",
"use_fates_managed_fire"
"use_fates_managed_fire",
"use_nvp", "use_nvp_undersnow", "nvp_rad_model_ground"
);

foreach my $var ( @list ) {
Expand All @@ -4910,6 +4912,7 @@ sub setup_logic_fates {
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fates_spitfire_mode', 'use_fates'=>$nl_flags->{'use_fates'},
'use_fates_managed_fire'=>$nl->get_value('use_fates_managed_fire'),
'use_fates_sp'=>$nl_flags->{'use_fates_sp'} );
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_nvp');

my $suplnitro = $nl->get_value('suplnitro');
my $parteh_mode = $nl->get_value('fates_parteh_mode');
Expand Down
6 changes: 6 additions & 0 deletions bld/namelist_files/namelist_defaults_ctsm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,12 @@ attributes from the config_cache.xml file (with keys converted to upper-case).
<use_luna use_fates=".true." >.false.</use_luna>
<use_luna phys="clm4_5" use_fates=".false.">.false.</use_luna>

<!-- NVP (non-vascular plant: moss/lichen) ground layer -->
<!-- [PORTED by Hui Tang: NVP control flag defaults] -->
<use_nvp >.false.</use_nvp>
<use_nvp_undersnow >.false.</use_nvp_undersnow>
<nvp_rad_model_ground >.false.</nvp_rad_model_ground>

<!-- Flexible CN options -->
<MM_Nuptake_opt use_flexibleCN=".true." >.true.</MM_Nuptake_opt>
<CNratio_floating use_flexibleCN=".true." >.true.</CNratio_floating>
Expand Down
21 changes: 21 additions & 0 deletions bld/namelist_files/namelist_definition_ctsm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,27 @@ LUNA operates on C3 and non-crop vegetation (see vcmax_opt for how other veg is
LUNA: Leaf Utilization of Nitrogen for Assimilation
</entry>

<!-- NVP (non-vascular plant: moss/lichen) ground layer -->
<!-- [PORTED by Hui Tang: NVP control flags] -->
<entry id="use_nvp" type="logical" category="physics"
group="clm_inparm" valid_values="" value=".false.">
Toggle to activate the NVP (non-vascular plant: moss/lichen) ground layer.
Requires use_fates=".true.".
</entry>

<entry id="use_nvp_undersnow" type="logical" category="physics"
group="clm_inparm" valid_values="" value=".false.">
Allow the NVP layer to remain active and exchange fluxes when covered by snow.
Only relevant when use_nvp=".true.".
</entry>

<entry id="nvp_rad_model_ground" type="logical" category="physics"
group="clm_inparm" valid_values="" value=".false.">
Use FATES Beer's law radiation model for the NVP ground layer instead of
the CLM bare-ground scheme.
Only relevant when use_nvp=".true.".
</entry>

<entry id="use_hillslope" type="logical" category="physics"
group="clm_inparm" valid_values="" value=".false.">
Toggle to turn on the hillslope model
Expand Down
11 changes: 10 additions & 1 deletion src/biogeophys/BalanceCheckMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ subroutine BalanceCheck( bounds, &
!
! !USES:
use clm_varcon , only : spval
use clm_varctl , only : use_soil_moisture_streams
use clm_varctl , only : use_soil_moisture_streams, use_nvp ! [PORTED by Hui Tang: use_nvp for NVP debug print]
use clm_time_manager , only : get_step_size_real, get_nstep
use clm_time_manager , only : get_nstep_since_startup_or_lastDA_restart_or_pause
use CanopyStateType , only : canopystate_type
Expand Down Expand Up @@ -589,6 +589,15 @@ subroutine BalanceCheck( bounds, &
! add qflx_drain_perched and qflx_flood
if (col%active(c)) then

! [PORTED by Hui Tang: NVP debug — print j=0 water and all wb flux terms for c==1]
if (use_nvp .and. col%jbot_sno(c) == -1 .and. c == 1) then
write(iulog,*) '[NVP DBG] WBal c=',c,' snl=',col%snl(c), &
' ice0=',waterstate_inst%h2osoi_ice_col(c,0), &
' liq0=',waterstate_inst%h2osoi_liq_col(c,0), &
' snwcp_liq=', qflx_snwcp_liq(c)*dtime, &
' snwcp_ice=', qflx_snwcp_ice(c)*dtime
end if

errh2o_col(c) = endwb_col(c) - begwb_col(c) &
- (forc_rain_col(c) &
+ forc_snow_col(c) &
Expand Down
48 changes: 40 additions & 8 deletions src/biogeophys/BareGroundFluxesMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ subroutine BareGroundFluxes(bounds, num_noexposedvegp, filter_noexposedvegp, &
use clm_varpar , only : nlevgrnd
use clm_varcon , only : cpair, vkc, grav, denice, denh2o, tfrz
use clm_varcon , only : beta_param, nu_param, meier_param3
use clm_varctl , only : use_lch4, z0param_method
use clm_varctl , only : use_lch4, z0param_method, use_nvp, iulog
use landunit_varcon , only : istsoil, istcrop
use QSatMod , only : QSat
use SurfaceResistanceMod , only : do_soilevap_beta,do_soil_resistance_sl14
Expand Down Expand Up @@ -217,21 +217,27 @@ subroutine BareGroundFluxes(bounds, num_noexposedvegp, filter_noexposedvegp, &
t_grnd => temperature_inst%t_grnd_col , & ! Input: [real(r8) (:) ] ground surface temperature [K]
thv => temperature_inst%thv_col , & ! Input: [real(r8) (:) ] virtual potential temperature (kelvin)
thm => temperature_inst%thm_patch , & ! Input: [real(r8) (:) ] intermediate variable (forc_t+0.0098*forc_hgt_t_patch)
t_h2osfc => temperature_inst%t_h2osfc_col , & ! Input: [real(r8) (:) ] surface water temperature
beta => temperature_inst%beta_col , & ! Input: [real(r8) (:) ] coefficient of conective velocity [-]
t_h2osfc => temperature_inst%t_h2osfc_col , & ! Input: [real(r8) (:) ] surface water temperature
! [PORTED by Hui Tang: NVP layer temperature for bare-ground NVP flux]
t_nvp_col => temperature_inst%t_nvp_col , & ! Input: [real(r8) (:) ] NVP layer temperature [K]
beta => temperature_inst%beta_col , & ! Input: [real(r8) (:) ] coefficient of conective velocity [-]

qg_snow => waterdiagnosticbulk_inst%qg_snow_col , & ! Input: [real(r8) (:) ] specific humidity at snow surface [kg/kg]
qg_soil => waterdiagnosticbulk_inst%qg_soil_col , & ! Input: [real(r8) (:) ] specific humidity at soil surface [kg/kg]
qg_h2osfc => waterdiagnosticbulk_inst%qg_h2osfc_col , & ! Input: [real(r8) (:) ] specific humidity at h2osfc surface [kg/kg]
qg_soil => waterdiagnosticbulk_inst%qg_soil_col , & ! Input: [real(r8) (:) ] specific humidity at soil surface [kg/kg]
qg_h2osfc => waterdiagnosticbulk_inst%qg_h2osfc_col , & ! Input: [real(r8) (:) ] specific humidity at h2osfc surface [kg/kg]
! [PORTED by Hui Tang: NVP surface specific humidity for bare-ground NVP flux]
qg_nvp => waterdiagnosticbulk_inst%qg_nvp_col , & ! Input: [real(r8) (:) ] NVP surface specific humidity [kg/kg]
qg => waterdiagnosticbulk_inst%qg_col , & ! Input: [real(r8) (:) ] specific humidity at ground surface [kg/kg]
dqgdT => waterdiagnosticbulk_inst%dqgdT_col , & ! Input: [real(r8) (:) ] temperature derivative of "qg"
h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Input: [real(r8) (:,:) ] ice lens (kg/m2)
h2osoi_liq => waterstatebulk_inst%h2osoi_liq_col , & ! Input: [real(r8) (:,:) ] liquid water (kg/m2)
grnd_ch4_cond => ch4_inst%grnd_ch4_cond_patch , & ! Output: [real(r8) (:) ] tracer conductance for boundary layer [m/s]

eflx_sh_snow => energyflux_inst%eflx_sh_snow_patch , & ! Output: [real(r8) (:) ] sensible heat flux from snow (W/m**2) [+ to atm]
eflx_sh_soil => energyflux_inst%eflx_sh_soil_patch , & ! Output: [real(r8) (:) ] sensible heat flux from soil (W/m**2) [+ to atm]
eflx_sh_h2osfc => energyflux_inst%eflx_sh_h2osfc_patch , & ! Output: [real(r8) (:) ] sensible heat flux from soil (W/m**2) [+ to atm]
eflx_sh_snow => energyflux_inst%eflx_sh_snow_patch , & ! Output: [real(r8) (:) ] sensible heat flux from snow (W/m**2) [+ to atm]
eflx_sh_soil => energyflux_inst%eflx_sh_soil_patch , & ! Output: [real(r8) (:) ] sensible heat flux from soil (W/m**2) [+ to atm]
eflx_sh_h2osfc => energyflux_inst%eflx_sh_h2osfc_patch , & ! Output: [real(r8) (:) ] sensible heat flux from surface water (W/m**2) [+ to atm]
! [PORTED by Hui Tang: NVP sensible heat flux for bare ground]
eflx_sh_nvp => energyflux_inst%eflx_sh_nvp_patch , & ! Output: [real(r8) (:) ] sensible heat flux from NVP (W/m**2) [+ to atm]
eflx_sh_grnd => energyflux_inst%eflx_sh_grnd_patch , & ! Output: [real(r8) (:) ] sensible heat flux from ground (W/m**2) [+ to atm]
eflx_sh_tot => energyflux_inst%eflx_sh_tot_patch , & ! Output: [real(r8) (:) ] total sensible heat flux (W/m**2) [+ to atm]
taux => energyflux_inst%taux_patch , & ! Output: [real(r8) (:) ] wind (shear) stress: e-w (kg/m/s**2)
Expand Down Expand Up @@ -274,6 +280,8 @@ subroutine BareGroundFluxes(bounds, num_noexposedvegp, filter_noexposedvegp, &
qflx_ev_snow => waterfluxbulk_inst%qflx_ev_snow_patch , & ! Output: [real(r8) (:) ] evaporation flux from snow (mm H2O/s) [+ to atm]
qflx_ev_soil => waterfluxbulk_inst%qflx_ev_soil_patch , & ! Output: [real(r8) (:) ] evaporation flux from soil (mm H2O/s) [+ to atm]
qflx_ev_h2osfc => waterfluxbulk_inst%qflx_ev_h2osfc_patch , & ! Output: [real(r8) (:) ] evaporation flux from h2osfc (mm H2O/s) [+ to atm]
! [PORTED by Hui Tang: NVP evaporation flux for bare ground]
qflx_ev_nvp => waterfluxbulk_inst%qflx_ev_nvp_patch , & ! Output: [real(r8) (:) ] evaporation flux from NVP (mm H2O/s) [+ to atm]
qflx_evap_soi => waterfluxbulk_inst%qflx_evap_soi_patch , & ! Output: [real(r8) (:) ] soil evaporation (mm H2O/s) (+ = to atm)
qflx_evap_tot => waterfluxbulk_inst%qflx_evap_tot_patch , & ! Output: [real(r8) (:) ] qflx_evap_soi + qflx_evap_can + qflx_tran_veg
qflx_tran_veg => waterfluxbulk_inst%qflx_tran_veg_patch , & ! Output: [real(r8) (:) ] vegetation transpiration (mm H2O/s) (+ = to atm)
Expand All @@ -294,6 +302,10 @@ subroutine BareGroundFluxes(bounds, num_noexposedvegp, filter_noexposedvegp, &
do f = 1, num_noexposedvegp
p = filter_noexposedvegp(f)
c = patch%column(p)
if (use_nvp .and. col%nvp_layer_active(c)) then
write(iulog,'(a,2i6,2l2,2f10.5)') '[DBG noexposedvegp] p, c, is_bg, is_veg, wtcol, frac_nvp:', &
p, c, patch%is_bareground(p), patch%is_veg(p), patch%wtcol(p), col%frac_nvp(c)
end if
btran(p) = 0._r8
t_veg(p) = forc_t(c)
cf_bare = forc_pbot(c)/(SHR_CONST_RGAS*0.001_r8*thm(p))*1.e06_r8
Expand Down Expand Up @@ -478,17 +490,37 @@ subroutine BareGroundFluxes(bounds, num_noexposedvegp, filter_noexposedvegp, &
eflx_sh_snow(p) = -raih*(thm(p)-t_soisno(c,snl(c)+1))
eflx_sh_soil(p) = -raih*(thm(p)-t_soisno(c,1))
eflx_sh_h2osfc(p) = -raih*(thm(p)-t_h2osfc(c))
! [PORTED by Hui Tang: NVP sensible heat flux for bare ground, analogous to snow/h2osfc]
! Zero when NVP is buried under snow (snl < -1): the snow surface controls the energy balance.
! Only compute for the NVP veg patch (patch%is_veg), not the bareground gap patch.
if (use_nvp .and. patch%is_veg(p) .and. col%frac_nvp(c) > 0._r8 .and. col%snl(c) >= -1) then
eflx_sh_nvp(p) = -raih*(thm(p)-t_nvp_col(c))
else
eflx_sh_nvp(p) = 0._r8
end if

! water fluxes from soil
qflx_tran_veg(p) = 0._r8
qflx_evap_veg(p) = 0._r8
qflx_evap_soi(p) = -raiw*dqh(p)
qflx_evap_tot(p) = qflx_evap_soi(p)

print *, "qflx_evap_tot=", qflx_evap_soi(p), raiw, dqh(p)

! compute latent heat fluxes individually
qflx_ev_snow(p) = -raiw*(forc_q(c) - qg_snow(c))
qflx_ev_soil(p) = -raiw*(forc_q(c) - qg_soil(c))
qflx_ev_h2osfc(p) = -raiw*(forc_q(c) - qg_h2osfc(c))
! [PORTED by Hui Tang: NVP evaporation flux for bare ground, analogous to snow/h2osfc]
! Zero when NVP is buried under snow (snl < -1): qflx_ev_nvp_col drives ev_nvp_eff in
! NVPWaterBalance_Column; a non-zero value here when NVP is covered would add water to
! qflx_evap_tot_col without removing it from any tracked water store, causing errh2o.
! Only compute for the NVP veg patch (patch%is_veg), not the bareground gap patch.
if (use_nvp .and. patch%is_veg(p) .and. col%frac_nvp(c) > 0._r8 .and. col%snl(c) >= -1) then
qflx_ev_nvp(p) = -raiw*(forc_q(c) - qg_nvp(c))
else
qflx_ev_nvp(p) = 0._r8
end if

! 2 m height air temperature
t_ref2m(p) = thm(p) + temp1(p)*dth(p)*(1._r8/temp12m(p) - 1._r8/temp1(p))
Expand Down
Loading