Skip to content

Tendency application update#299

Open
grantfirl wants to merge 67 commits intoufs-community:ufs/devfrom
grantfirl:feature/tendency_cleanup
Open

Tendency application update#299
grantfirl wants to merge 67 commits intoufs-community:ufs/devfrom
grantfirl:feature/tendency_cleanup

Conversation

@grantfirl
Copy link
Collaborator

@grantfirl grantfirl commented Jul 14, 2025

Description of Changes:

See https://docs.google.com/presentation/d/1LJbCrCVGYDvm0UPo8SR4KP6fT1VFocg-xLG399qGQ1w/edit?slide=id.g371ddcb3c06_0_238#slide=id.g371ddcb3c06_0_238 for a complete description.

Main points:

  • Converts all primary schemes to return tendencies rather than modify the physics state
  • Adds code to interstitial schemes to apply tendencies based on control from the host
  • Other minor changes (including lots of metadata changes) to implement the above
  • Obsolete schemes removed:
    • GFS_MP_generic_pre.F90
    • GFS_DCNV_generic_pre.F90
    • GFS_SCNV_generic_pre.F90
    • GFS_suite_stateout_reset.F90
    • GFS_suite_stateout_update.F90
    • mp_tempo_pre.F90
    • mp_thompson_pre.F90
  • New schemes:
    • GFS_photochemistry_post.F90 (because there was no generic interstitial scheme for this to apply tendencies)
    • mynnedmf_wrapper_post.F90 (because it doesn't use GFS_PBL_generic_post.F90)

Tests Conducted:

See the linked slides. This was tested in the following ways:

  • standard UFS regression tests (should change baseline results for most/all tests that actually run physics, although changes SHOULD be similar to a compiler change; scientific results should NOT change)
  • SCM tests comparing selected suites before/after differences to compiler/debug mode differences
  • UFS tests comparing selected suites before/after differences to compiler/debug mode differences

Dependencies:

None

Documentation:

TODO

Issue (optional):

None

Contributors (optional):

@grantfirl @VanderleiVargas-NOAA

grantfirl and others added 30 commits December 12, 2024 12:07
…emove *_of_new_state (default name refers to 'current' value)
…medmfvdifq return new tendencies and new tendency application block in GFS_PBL_generic_post
- Added tendency variables (`ten_t`, `ten_u`, `ten_v`) for temperature and wind tendencies in SAMF deep and shallow convection schemes.
- Updated relevant `.meta` files to reflect changes in variable intent (`inout` -> `in` where appropriate) and added tendencies.
- Modified Interstitials (`GFS_DCNV_generic_post`, `GFS_DCNV_generic_pre`, `GFS_SCNV_generic_post`, `GFS_SCNV_generic_pre`) to directly use tendencies instead of saved state variables.
- Removed redundant saved variables (`save_u`, `save_v`, `save_t`).
- Added `delt` to post interstitials.
…endency paradigm; cleanup saving of states no longer needed
@grantfirl
Copy link
Collaborator Author

@rhaesung @yangfanglin Here are some updated plots from testing: https://docs.google.com/presentation/d/1NXsgRd_2M-zAZIPlHagYhKa8W7TcJEftaR2sxjRvkfY/edit?slide=id.p#slide=id.p

These results were obtained last week, after the code had been updated to the latest develop branch. I've added a test using the conus13km_control because it uses the FV3_HRRR suite with smoke/dust active (this wasn't tested last time).

Based on these results, I'm still satisfied that these code changes aren't changing the scientific results at all. The exception is for the RAS scheme, which we're removing anyway, so I have not debugged the failed RTs.

@rhaesung
Copy link
Collaborator

rhaesung commented Feb 2, 2026

@grantfirl Thanks so much for the great work and for sharing the latest test results — I’ve started taking a look.
By the way, would you be open to a short meeting with you and @yangfanglin to talk through how we should review this large PR from the EMC side? I think it could help us align and make the review smoother. Let me know what you think!

@grantfirl
Copy link
Collaborator Author

@grantfirl Thanks so much for the great work and for sharing the latest test results — I’ve started taking a look. By the way, would you be open to a short meeting with you and @yangfanglin to talk through how we should review this large PR from the EMC side? I think it could help us align and make the review smoother. Let me know what you think!

@rhaesung Sure, I emailed you both offline to set up a time.

Copy link
Collaborator

@rhaesung rhaesung left a comment

Choose a reason for hiding this comment

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

@grantfirl I've had a chance to go through the convection schemes in this PR. Here is a summary of the key points I've flagged.

  1. Bugs: found a few indexing errors (ntr+1 vs ntr+2), missing /dt, and skipped ten_u updates.
  2. Consistency: the internal state updates (like qv) and diagnostic units (like QLCN/QICN) - just want to ensure they all align with the new tendency framework.
  3. Metadata minor cleanup

Thanks and looking forward to your thoughts!

[pu]
standard_name = x_wind_of_new_state
standard_name = x_wind
long_name = updated x-direction wind
Copy link
Collaborator

Choose a reason for hiding this comment

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

removing 'updated' would be more accurate. The same should be applied to pv, pt, and other meta files.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good point. I agree and I remember thinking it when I was making metadata edits, but I didn't bother due to long_names not being used to match anything. But, it makes sense to fix them because it can be misleading as-is. Will do.

@grantfirl
Copy link
Collaborator Author

@grantfirl I've had a chance to go through the convection schemes in this PR. Here is a summary of the key points I've flagged.

  1. Bugs: found a few indexing errors (ntr+1 vs ntr+2), missing /dt, and skipped ten_u updates.
  2. Consistency: the internal state updates (like qv) and diagnostic units (like QLCN/QICN) - just want to ensure they all align with the new tendency framework.
  3. Metadata minor cleanup

Thanks and looking forward to your thoughts!

Thanks @rhaesung for the thorough review. I'll address these right away.

@gspetro-NOAA
Copy link

@grantfirl @rhaesung Have the requested changes been addressed? The parent PRs were marked ready for review, so I wanted to check on this.

@grantfirl
Copy link
Collaborator Author

@grantfirl @rhaesung Have the requested changes been addressed? The parent PRs were marked ready for review, so I wanted to check on this.

No, I'm making the changes now. There will likely be some more testing that needs to happen beyond RTs yet too, so this shouldn't be scheduled for the merge queue yet.

Copy link
Collaborator

@rhaesung rhaesung left a comment

Choose a reason for hiding this comment

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

@grantfirl The overall direction of the refactor looks great! To bring GWD fully in line with your new framework, just a couple of points:

  1. Since generic post now handles diagnostic accumulation, please remove the manual updates in the primary schemes to avoid double-counting.
  2. Let's keep temperature tendencies alongside the wind to ensure all variables follow the same logic and maintain physical symmetry.

Copy link
Collaborator

@rhaesung rhaesung left a comment

Choose a reason for hiding this comment

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

@grantfirl For MP, I just have a few questions:

  1. Since you mentioned the tracer array issue in convection, I was curious about ten_q in MP. Is the mapping from individual species (dqc, dqr, etc.) to the general ten_q array handled automatically now, or do we still need to keep an eye on manual updates? Just want to make sure we don't hit the same snag there!
  2. On the precip variables (prcp, PREC), I noticed they're still intent(inout) without a guard flag like GWD's ugwp_seq_update. Are we worried about double-counting when generic_post kicks in, or is that handled elsewhere in the current UFS suites?
  3. Just a small safety check - I noticed some optional variables (like nc, nwfa) are accessed without present() checks.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Noticed the Nc (Number concentration) tendencies are missing from the post. Was this an intentional call, or did it just slip through? Just curious about keeping the 2-moment physical balance for the next step. Thoughts?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Originally, the number concentrations are only being set from a temporary variable from m_micro. Now, the tendency is being set in m_micro, so there isn't any need to do anything with the tendency in this post scheme. It does raise the point about consistency of the number concentrations when any of rain/snow/graupel mixing ratios would be made negative by the tendencies coming from m_micro. The original post scheme doesn't address this, and neither does the updated code.

Copy link
Collaborator

@rhaesung rhaesung left a comment

Choose a reason for hiding this comment

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

@grantfirl A few questions for the PBL schemes:

  1. Most schemes still modify legacy tracer arrays (rtg, dqdt) directly. Shouldn't we move these to ten_q to match the T, U, V strategy and your metadata?
  2. For 2D surface fluxes, some use = or += on intent(out). I saw a similar pattern in the MP schemes as well. Wouldn't it be better to handle these 2D variables using the same tendency guards as the 3D states?
  3. Many optional diagnostic arrays (like dtend) are missing present() checks.

Copy link
Collaborator

Choose a reason for hiding this comment

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

ten_u/v are initialized to 0 but never updated after shoc_work, effectively disabling wind mixing.

do i=1,nx
gq0(i,k,ntlnc) = ncpl(i,k)
ten_q(i,k,ntlnc) = (ncpl(i,k) - gq0(i,k,ntlnc))/dtp
gq0(i,k,ntinc) = ncpi(i,k)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should use ten_q instead.

enddo
endif
if(ldiag3d .and. dtidx(100+ntoz,index_of_process_pbl)>1) then
allocate(old_ozone(im,levs))
Copy link
Collaborator

Choose a reason for hiding this comment

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

We need to deallocate this.

real(kind_phys), dimension(:,:), intent(out) :: &
& dtdt, dudt, dvdt, dqdt_water_vapor, dqdt_liquid_cloud, &
& dqdt_ice, dqdt_snow, dqdt_ozone
real(kind_phys), dimension(:,:,:), intent(out) :: dqdt_all
Copy link
Collaborator

Choose a reason for hiding this comment

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

The dqdt_all is defined but doesn't seem to be populated with the actual tendencies.

Comment on lines 388 to 390
& allocate( EDDYVESTX ( MAXCAN ) )
if(.not.allocated(ZCANX))
& allocate( ZCANX ( MAXCAN ) )
Copy link
Collaborator

Choose a reason for hiding this comment

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

Pre-existing leak in EDDYVESTX/ZCANX. Needs deallocation before return.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Since dtsfc/dusfc are intent(out), won't += access uninitialized memory? Also, wouldn't populating both ten_q and qtnp cause double updates in the host model?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Tracers are still modifying rtg directly here. Shouldn't we switch to ten_q to stay consistent with the T, U, V refactoring? Also, won't direct assignment to 2D fluxes risk overwriting data from previous schemes?

@grantfirl
Copy link
Collaborator Author

grantfirl commented Mar 2, 2026

@rhaesung @yangfanglin FYI, I've added results for tests to cover the 6 additional schemes that we were interested in double-checking (RRTMGP, GF convection, nTiedtke convection, GFDL MP v3, NSSL MP, and TEMPO MP) to slides that I've shared before: https://docs.google.com/presentation/d/1NXsgRd_2M-zAZIPlHagYhKa8W7TcJEftaR2sxjRvkfY/edit?usp=sharing

See slides 20-43 for the new results. All of these schemes look to be behaving as expected with result changes within the same magnitude as obtained during a compiler change or optimization level change.

Because a RT that exercised nTiedtke didn't exist, a new RT was created for the nTiedtke scheme based off of a HAFS suite (since that application seems to have the most interest in this scheme). I'll have a separate PR in UFS WM and UFSATM that has the new HAFS RT setup that I'll link to this set of PRs. The HAFS team may want to look at the new test to doublecheck it; it's using a new SDF based off of the FV3_HAFS_v1_thompson_tedmf_gfdlsf suite but replaces SAMF convection with nTiedtke (only).

intent = inout
[gq0]
standard_name = specific_humidity_of_new_state
standard_name = 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.

name mismatch w other meta files. tracer concentration?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there a reason for using dtp for state updates but dtf for dtend diagnostics? If they aren't identical, the diagnostics won't match the actual state change?


! add radar temp tendency
! there is radar coverage
gt0(i,k) = save_t(i,k) + ttend*dtp
Copy link
Collaborator

Choose a reason for hiding this comment

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

Looks like this is a legacy overwrite bug. This should be changed to gt0(i,k)=gt0(i,k)+ttend*dtp.

Copy link
Collaborator

Choose a reason for hiding this comment

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

similar dtp vs dtf question here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

A few quick notes on the new post-routine:

  1. Including U, V, and T in this update logic seems to add unnecessary overhead, since photochemistry only affects tracers?
  2. I'm concerned about the missing zero-out safeguard here, similar to what we discussed for MG microphysics. Shouldn't we ensure O3 and H2O tendencies don't lead to negative concentrations?

endif

!htrsw is calculated in rrtmg_sw_post if using RRTMG and above if using RRTMGP
ten_t = htrsw
Copy link
Collaborator

Choose a reason for hiding this comment

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

Won't ten_t=htrsw overwrite the LW contribution from htrlw? Should these be accumulated instead?

Copy link
Collaborator

Choose a reason for hiding this comment

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

  1. Are the U,V, and Q loops necessary?
  2. You switched the diagnostics input from tgrs to gt0. Since gt0 might already be updated by LW radiation, won't this cause inconsistency in the diagnostic output?

Copy link
Collaborator

Choose a reason for hiding this comment

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

  1. I noticed that the else block for non-lsidea runs (which accumulates htrlw/htrsw into dtend) has been removed. Is this diagnostic logic being moved to a different routine, like the new radiation_post? If this is removed without a replacement, won't we lose the 3D budget diagnostics for lw/sw heating?
  2. ten_t, ten_u, ten_v, and ten_q are never used.

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.