Skip to content

WRF-urban-NbS development#2272

Merged
weiwangncar merged 24 commits intowrf-model:developfrom
chenghaow:urban_nbs
Feb 13, 2026
Merged

WRF-urban-NbS development#2272
weiwangncar merged 24 commits intowrf-model:developfrom
chenghaow:urban_nbs

Conversation

@chenghaow
Copy link

@chenghaow chenghaow commented Jan 14, 2026

Development of the WRF-urban-NbS module within the single-layer urban canopy model

TYPE: new feature

KEYWORDS: urban canopy models, urban trees, nature-based solutions, urban grass, urban hydrology, radiative view factors

SOURCE: Yuqi Huang (University of Oklahoma), Chenghao Wang (University of Oklahoma), Cenlin He (NCAR)

DESCRIPTION OF CHANGES:
Problem: The current WRF-urban modeling system employs a single-layer urban canopy model (SLUCM) that assumes a dry street canyon. While a green roof module exists, ground vegetation and street trees are not represented. As a result, key nature-based solution (NbS) processes such as evapotranspiration, radiative shading, and soil–vegetation–atmosphere interactions are not captured. In addition, radiative exchanges involving trees are not explicitly resolved. A version of the urban tree module within SLUCM was developed and tested for the contiguous U.S. but only accounted for shading in a simplified way:

  • Wang, C., Wang, Z. H., & Yang, J. (2018). Cooling effect of urban trees on the built environment of contiguous United States. Earth's Future, 6(8), 1066–1081. https://doi.org/10.1029/2018EF000891

Solution:
This PR introduces urban ground vegetation and street trees into the single-layer urban canopy model. Round-shaped urban trees are explicitly represented, resolving evapotranspiration, shading, and root water uptake. Radiative exchanges between trees and surrounding urban elements are solved using newly implemented analytical view factors.
The development is largely based on the Arizona State University Single-Layer Urban Canopy Model (ASLUM v3.1) and its hydrologically enhanced version, ASLUM-Hydro, and extends their capabilities within the WRF-Urban framework. See the following two papers for ASLUM v3.1 and ASLUM-Hydro:

This PR also includes the following fixes:

  1. Shadow option: The default of SHADOW was changed to .true.. In the previous default setting, street-canyon shadowing was not considered. We can switch this back if you think the default should remain unchanged.
  2. Impervious water retention: Minor bug fixes related to water retention depth over impervious surfaces. These only apply when IMP_SCHEME == 2 (the default in the table is 1).
  3. Radiative (green) roof term (GROPTION = 1): Changed RGR = EPSV*(RX-SIG*(TA**4.)/60.) to RGR = EPSV*(RX-SIG*(TGRP**4.)/60.). This is a bug fix. Note that the default table value for GROPTION is 0.

ISSUE: NA

LIST OF MODIFIED FILES:
The following files were modified (generated using git diff --name-only master urban_nbs):

  • Registry/Registry.EM_COMMON
  • dyn_em/module_first_rk_step_part1.F
  • dyn_em/start_em.F
  • phys/module_physics_init.F
  • phys/module_sf_clm.F
  • phys/module_sf_noahdrv.F
  • phys/module_sf_urban.F
  • phys/module_surface_driver.F
  • run/URBPARM.TBL
  • run/URBPARM_LCZ.TBL
  • run/URBPARM_UZE.TBL
  • wrftladj/module_physics_init_ad.F
  • wrftladj/module_physics_init_tl.F
  • wrftladj/start_em_ad.F
  • wrftladj/start_em_tl.F

TESTS CONDUCTED:

  • Successfully tested in offline mode coupled with the HRLDAS system
  • Demonstrated systematic performance improvements across 20 global urban sites when evaluated against flux-tower observations from the Urban-PLUMBER project
  • Successfully compiled on the NCAR Derecho system
  • Short-term online WRF simulations are currently ongoing

Note:
Successful compilation requires Noah-MP-related source files that are not included in WRF v3.7.1, including a modified version of module_sf_noahmpdrv.F. These changes will be addressed in a separate PR dedicated to Noah-MP.

RELEASE NOTE:
This PR introduces urban ground vegetation and street trees into the single-layer urban canopy model and based the following two manuscripts in development:

  • Huang, Y., Wang, C., & He, C. Integrating nature-based solutions into the WRF-urban modeling system. Manuscript in prepration.
  • Wang, C., Huang, Y., Miller, D. L., Katz, D., & Ghosh, A. K. Analytical view factors for urban canopy models with trees: model development and case study in New York City. Manuscript in preparation.

Update dyn_em files with new WRF-urban-nbs related variables
Largely enhanced module_sf_urban.F to incorporate nature-based solutions (including urban trees)
Update phys files with new WRF-urban-nbs related variables
Update TBL files with new WRF-urban-nbs related variables
Update wrftladj files with new WRF-urban-nbs related variables
@chenghaow chenghaow requested review from a team as code owners January 14, 2026 20:11
@cenlinhe
Copy link
Contributor

This PR will fail the regression test because the NoahMP link has not been updated yet. The developers are working to update the noahmp github for this changes and will update the commit soon once the noahmp link is updated.

@weiwangncar
Copy link
Collaborator

weiwangncar commented Jan 15, 2026

@chenghaow This PR fails for multiple tests when real*8 is used. To try real*8 compilation, do configure -r8. A sample compilation output is attached here.
output_10.txt

- Removed double-precision-related code based on HRLDAS offline model
- Uncommented distributed aerodynamic roughness length related code to be consistent with WRF v4.7.1
@chenghaow
Copy link
Author

@weiwangncar Thanks for sharing the compilation log. We found that the issue is caused by an inconsistency in module_sf_urban.F between WRF v4.7.1 and HRLDAS (specifically the DLOG function). To address this, we (1) commented out the double-precision-related code inherited from the HRLDAS urban module, and (2) restored the distributed aerodynamic roughness length code that had been removed from the HRLDAS urban module. We are now testing the compilation on our end on Derecho.

@cenlinhe I'll open a separate issue in the HRLDAS repo on this.

@cenlinhe
Copy link
Contributor

yes, Noah-MP uses a different double precision flag (DOUBLE_PREC) than WRF (DOUBLE_PRECISION). My NoahMPv5 coupling will resolve this issue, but it's good that you reverted back to the original WRF-Urban treatment. Please make sure that you did not remove any other default urban code in the WRF version (do not use HRLDAS version).

@chenghaow
Copy link
Author

yes, Noah-MP uses a different double precision flag (DOUBLE_PREC) than WRF (DOUBLE_PRECISION). My NoahMPv5 coupling will resolve this issue, but it's good that you reverted back to the original WRF-Urban treatment. Please make sure that you did not remove any other default urban code in the WRF version (do not use HRLDAS version).

Sure. We will keep the double precision flag in the offline version though.

@cenlinhe
Copy link
Contributor

HRLDAS version of the urban code may lag a few recent WRF-Urban updates.

Duplicate declarations removed
@chenghaow
Copy link
Author

The current version successfully compiled on Derecho with ./configure -r8

@weiwangncar
Copy link
Collaborator

@chenghaow The last regression tests failed on three cases. Attached is the output file from this group of tests (search for kiaps2):
output_19.txt

Also removed temporary fix for singularity matrix in tree energy budget
@cenlinhe
Copy link
Contributor

This PR needs to be merged first before the refactored NoahMP coupling PR (#2268) because this PR modifies the non-refactored NoahMP urban driver. Once this urban PR is merged, I will need to update the Noah-MP urban driver in the refactored code and hence the refactored NoahMP coupling PR above to avoid any merge conflicts.

@chenghaow
Copy link
Author

@weiwangncar Looks like our recent fix failed the regression tests. Would you please share the output file? Thanks!

@weiwangncar
Copy link
Collaborator

@chenghaow See attached file here (tests for kiaps2 namelists):
output_19.txt

Singular matrix in Urban Tree Energy Budget
@chenghaow chenghaow requested a review from a team as a code owner January 19, 2026 18:38
Stabilize urban tree energy budget solve with damped diagonal fallback
@weiwangncar
Copy link
Collaborator

@chenghaow Can you address the last comment by @dudhia? Thanks.

@chenghaow
Copy link
Author

@chenghaow Can you address the last comment by @dudhia? Thanks.

Sure. I'll change TREEOPTION: 1 to TREEOPTION: 0 as the default option in URBPARM.TBL, URBPARM_LCZ.TBL, and URBPARM_UZE.TBL and run another round of regression tests.

change `TREEOPTION: 1` to `TREEOPTION: 0` as the default option in `URBPARM.TBL`, `URBPARM_LCZ.TBL`, and `URBPARM_UZE.TBL`
@weiwangncar
Copy link
Collaborator

@chenghaow Thanks for the change. Would the default now produce identical results as if the option is not there?
Also, although it is not a big deal, we prefer code added without much 'signatures', such as '! added by Chenghao Wang' - if one is interested in the history of the code, git can find everything.

@dudhia dudhia changed the base branch from release-v4.7.1 to develop February 10, 2026 16:21
@dudhia
Copy link
Collaborator

dudhia commented Feb 11, 2026

@chenghaow We would like confirmation this does not affect results when the option is switched off before approving the PR.

@chenghaow
Copy link
Author

chenghaow commented Feb 11, 2026

Hi @dudhia and @weiwangncar

With TREEOPTION: 0 model outputs should be close to the original version. But we did fix three issues in module_sf_urban.F:

  1. Shadow option: The default of SHADOW was changed to .true.. In the previous default setting, street-canyon shadowing was not considered. We can switch this back if you think the default should remain unchanged.
  2. Impervious water retention: Minor bug fixes related to water retention depth over impervious surfaces. These only apply when IMP_SCHEME == 2 (the default in the table is 1).
  3. Radiative (green) roof term (GROPTION = 1): Changed RGR = EPSV*(RX-SIG*(TA**4.)/60.) to RGR = EPSV*(RX-SIG*(TGRP**4.)/60.). This is a bug fix. Note that the default table value for GROPTION is 0.

So, if users stick with the default table values, the only expected difference relative to the original SLUCM would come from the street-canyon shadow effect.

@cenlinhe also looping in Cenlin here.

@dudhia
Copy link
Collaborator

dudhia commented Feb 11, 2026

OK, we will approve it if @cenlinhe can confirm that these changes are fine. Thanks.

@cenlinhe
Copy link
Contributor

these changes look fine to me.
Does anyone know why this SHADOW is turned off in previous versions by default. Is it related to model stability? If yes, maybe we should switch the SHADOW option back to .false. If not , then we should keep it to .true. as in this PR.

@dudhia
Copy link
Collaborator

dudhia commented Feb 11, 2026

@cenlinhe as far as I can tell it has been .false. since it was added in 2006. I will approve this commit for now and we can return to this issue later.

@dudhia
Copy link
Collaborator

dudhia commented Feb 11, 2026

I looked at the code and to be used correctly SHADOW needs diffuse and direct solar separately. These are available but probably not passed in.

@cenlinhe
Copy link
Contributor

I looked at the code and to be used correctly SHADOW needs diffuse and direct solar separately. These are available but probably not passed in.

I think both diffuse and direct solar are passed in by default. @chenghaow could you please double check and confirm?

@chenghaow
Copy link
Author

The default version uses LSOLAR = .FALSE., which means SLUCM internally partitions the input total SW into direct and diffuse through a predefined ratio SRATIO=0.75.

Of course one may pass direct and diffuse from WRF-solar, but the default SLUCM don't need them.

@cenlinhe
Copy link
Contributor

The default version uses LSOLAR = .FALSE., which means SLUCM internally partitions the input total SW into direct and diffuse through a predefined ratio SRATIO=0.75.

Of course one may pass direct and diffuse from WRF-solar, but the default SLUCM don't need them.

But this LSOLAR = .FALSE. does not prevent users from activating the SHADOW option, right?

@chenghaow
Copy link
Author

You are right. But no matter whether shadow is activated or not, the default version still doesn’t need direct and diffuse SW passed from other modules.

@cenlinhe
Copy link
Contributor

You are right. But no matter whether shadow is activated or not, the default version still doesn’t need direct and diffuse SW passed from other modules.

In that case, I am fine with your current settings, keep the SHADOW = .true. by default.

@weiwangncar
Copy link
Collaborator

@chenghaow Can you please add the three fixes in the PR message as well as in the RELEASE NOTE section? Thanks!

@weiwangncar
Copy link
Collaborator

@chenghaow Also, although it is not a big deal, we prefer code added without much 'signatures', such as '! added by Chenghao Wang' - if one is interested in the history of the code, git can find everything.

@weiwangncar weiwangncar self-requested a review February 12, 2026 09:28
Copy link
Collaborator

@dudhia dudhia left a comment

Choose a reason for hiding this comment

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

Remaining changes mentioned in review are minor text only and can be done later.

@weiwangncar weiwangncar merged commit e39e090 into wrf-model:develop Feb 13, 2026
4 checks passed
@tslin2
Copy link
Contributor

tslin2 commented Feb 17, 2026

these changes look fine to me. Does anyone know why this SHADOW is turned off in previous versions by default. Is it related to model stability? If yes, maybe we should switch the SHADOW option back to .false. If not , then we should keep it to .true. as in this PR.

I tested this option previously in the previous version; the SHADOW==.true. seemed to make the model crash. I cannot remember what the issue was, maybe due to model stability but it can be tested in the future.

@chenghaow
Copy link
Author

these changes look fine to me. Does anyone know why this SHADOW is turned off in previous versions by default. Is it related to model stability? If yes, maybe we should switch the SHADOW option back to .false. If not , then we should keep it to .true. as in this PR.

I tested this option previously in the previous version; the SHADOW==.true. seemed to make the model crash. I cannot remember what the issue was, maybe due to model stability but it needs more testing in the future.

That’s strange. SHADOW should definitely be turned on; otherwise, both shortwave and longwave radiation within street canyon will be (largely) biased. Note that SHADOW = .true. is the default setting in this NbS version, since resolving tree shading effects requires it. Yuqi has been testing this version always with SHADOW = .true., and to my knowledge he hasn't encountered any model crashes due to the shading module. We will continue testing and will share updates if we identify instability issues.

@tslin2
Copy link
Contributor

tslin2 commented Feb 17, 2026

these changes look fine to me. Does anyone know why this SHADOW is turned off in previous versions by default. Is it related to model stability? If yes, maybe we should switch the SHADOW option back to .false. If not , then we should keep it to .true. as in this PR.

I tested this option previously in the previous version; the SHADOW==.true. seemed to make the model crash. I cannot remember what the issue was, maybe due to model stability but it needs more testing in the future.

That’s strange. SHADOW should definitely be turned on; otherwise, both shortwave and longwave radiation within street canyon will be (largely) biased. Note that SHADOW = .true. is the default setting in this NbS version, since resolving tree shading effects requires it. Yuqi has been testing this version always with SHADOW = .true., and to my knowledge he hasn't encountered any model crashes due to the shading module. We will continue testing and will share updates if we identify instability issues.

Thank you for sharing that. My previous run crashed in a different version, which could also be due to other issues.

@dudhia
Copy link
Collaborator

dudhia commented Feb 17, 2026

I note that LSOLAR is FALSE in the urban module and there is also code in module_sf_urban that will ignore separate diffuse and direct inputs even if TRUE. Setting LSOLAR to TRUE is not that easy because some older shortwave schemes don't provide separate diffuse and direct. Ideally LSOLAR will be tied to the sw radiation option instead of in the LSM drivers.

@weiwangncar
Copy link
Collaborator

@chenghaow @cenlinhe @tslin2 Do you have a minimum (or maximum) or a typical value for the lowest model layer (between full levels) we can recommend the users to apply when using SLUCM with and without the tree option?

@chenghaow
Copy link
Author

@chenghaow @cenlinhe @tslin2 Do you have a minimum (or maximum) or a typical value for the lowest model layer (between full levels) we can recommend the users to apply when using SLUCM with and without the tree option?

No. In this version, all urban trees are set to be lower than the mean building height. So whether the model crashes or not still depends on the relationship between the mean building height and the first atmospheric layer, just like in the original SLUCM, and is ultimately controlled by the input building height data.

@chenghaow
Copy link
Author

I note that LSOLAR is FALSE in the urban module and there is also code in module_sf_urban that will ignore separate diffuse and direct inputs even if TRUE. Setting LSOLAR to TRUE is not that easy because some older shortwave schemes don't provide separate diffuse and direct. Ideally LSOLAR will be tied to the sw radiation option instead of in the LSM drivers.

Totally agree.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants