Skip to content

Fix incorrect qrn gradient scaling in WRFDA radial velocity adjoint#2356

Open
Weiyu-Yang wants to merge 1 commit into
wrf-model:developfrom
Weiyu-Yang:fix-wrfda-rv-adjoint
Open

Fix incorrect qrn gradient scaling in WRFDA radial velocity adjoint#2356
Weiyu-Yang wants to merge 1 commit into
wrf-model:developfrom
Weiyu-Yang:fix-wrfda-rv-adjoint

Conversation

@Weiyu-Yang

Copy link
Copy Markdown

Fix incorrect gradient scaling of rain mixing ratio in WRFDA radial velocity adjoint

TYPE:
bug fix

KEYWORDS:
WRFDA, radar, radial velocity, adjoint, tangent linear, gradient, rain mixing ratio

SOURCE:
Weiyu Yang (Nanjing University of Information Science and Technology)

DESCRIPTION OF CHANGES:
Problem:
In the WRFDA radial velocity tangent linear code, the rain mixing ratio (qrn) is scaled by a factor of 1000 (qrn_g = qrn * 1000.). According to the strict definition of an adjoint operator (the transpose of the tangent linear operator), the backward propagation of the gradient must also be scaled by 1000 and accumulated. However, the current official adjoint code (da_radial_velocity_adj.inc) incorrectly applies an inverse operation (qrn = qrn_g * 0.001) instead of the transpose operation. This scales the gradient incorrectly by a factor of $10^{-6}$ compared to the true analytical adjoint, causing the traditional Adjoint Test to fail significantly.

Solution:
Modified the source code to strictly follow the mathematical transpose logic of the tangent linear operator:

  1. Initialized the local adjoint accumulator qrn_g to 0.0.
  2. Replaced the inverse operation with a proper adjoint accumulation: qrn = qrn + qrn_g * 1000.0.

ISSUE:
N/A

LIST OF MODIFIED FILES:
M var/da/da_radar/da_radial_velocity_adj.inc

TESTS CONDUCTED:

  1. Conducted an independent Tangent Linear (TL) and Adjoint (AD) test using double-precision (real*8). Before the fix, the adjoint test failed because the analytical gradient was scaled by 0.001 instead of 1000. After the fix, the test passed perfectly. The inner products (Hx)^T * (Hx) and x^T * H^T * (Hx) match exactly up to 15-16 significant digits (the machine precision limit) across perturbation scales from $10^{-1}$ to $10^{-10}$.
  2. The code compiles successfully.

RELEASE NOTE:
Fixed a gradient calculation bug in the WRFDA radial velocity adjoint operator (da_radial_velocity_adj.inc). The sensitivities of the rain mixing ratio (qrn) were previously scaled incorrectly due to the use of an inverse operation instead of a mathematical transpose operation. This fix ensures the strict accuracy of the adjoint gradient for radar radial velocity assimilation.

@Weiyu-Yang Weiyu-Yang requested a review from a team as a code owner June 18, 2026 16:08
@weiwangncar

Copy link
Copy Markdown
Collaborator

Regression test results:

Test Type              | Expected  | Received |  Failed
= = = = = = = = = = = = = = = = = = = = = = = =  = = = =
Number of Tests        : 23           24
Number of Builds       : 60           57
Number of Simulations  : 158           150        0
Number of Comparisons  : 95           86        0

Failed Simulations are: 
None
Which comparisons are not bit-for-bit: 
None

@weiwangncar weiwangncar changed the base branch from master to develop June 18, 2026 16:59
@Weiyu-Yang

Copy link
Copy Markdown
Author

To facilitate the review process, I have created a standalone Tangent Linear (TL) and Adjoint (AD) testing suite to verify the sensitivities of the rain mixing ratio (qrn) in the radar radial velocity operator, both before and after the bug fix.

1. Mathematical Foundation

The strict correctness of an adjoint operator is verified by the following inner product identity:
$$(\mathbf{H}(\alpha\Delta\mathbf{x}))^T (\mathbf{H}(\alpha\Delta\mathbf{x})) = (\alpha\Delta\mathbf{x})^T \mathbf{H}^T \mathbf{H}(\alpha\Delta\mathbf{x})$$
Where:

  • $\mathbf{H}$ is the tangent linear operator.
  • $\mathbf{H}^T$ is the adjoint operator (the transpose of $\mathbf{H}$).
  • $\Delta\mathbf{x}$ is the perturbation of the state vector.
  • $\alpha$ is the perturbation scaling factor (ranging from $10^{-10}$ to $10^{-1}$ in this test).

Theoretically, within machine floating-point precision, both sides of the equation (HxHx and xHHx) must be strictly equal.

2. Test Results Before the Fix

In the original official code (test_qr_ad_before_bug_fixed.txt), the test yields the following:

             Alpha                    HxHx                     xHHx   
   0.1000000000000000D+00   0.2042255926936121D-02   0.2042255926936121D-08
   0.1000000000000000D-01   0.2042255926936120D-04   0.2042255926936120D-10
   0.1000000000000000D-02   0.2042255926936121D-06   0.2042255926936121D-12
   0.1000000000000000D-03   0.2042255926936120D-08   0.2042255926936121D-14
   0.1000000000000000D-04   0.2042255926936122D-10   0.2042255926936122D-16
   0.1000000000000000D-05   0.2042255926936121D-12   0.2042255926936121D-18
   0.1000000000000000D-06   0.2042255926936120D-14   0.2042255926936120D-20
   0.1000000000000000D-07   0.2042255926936120D-16   0.2042255926936121D-22
   0.1000000000000000D-08   0.2042255926936121D-18   0.2042255926936121D-24
   0.1000000000000000D-09   0.2042255926936121D-20   0.2042255926936121D-26

Conclusion: As shown above, the right side (xHHx) differs from the left side (HxHx) by exactly a factor of $10^{-6}$. This perfectly confirms the mathematical flaw where the gradient was erroneously scaled by 0.001 instead of 1000.0.

3. Test Results After the Fix

After applying the correction (test_qr_ad_after_bug_fixed.txt), the output is:

              Alpha                    HxHx                     xHHx   
   0.1000000000000000D+00   0.2042255926936121D-02   0.2042255926936121D-02
   0.1000000000000000D-01   0.2042255926936120D-04   0.2042255926936120D-04
   0.1000000000000000D-02   0.2042255926936121D-06   0.2042255926936121D-06
   0.1000000000000000D-03   0.2042255926936120D-08   0.2042255926936120D-08
   0.1000000000000000D-04   0.2042255926936122D-10   0.2042255926936122D-10
   0.1000000000000000D-05   0.2042255926936121D-12   0.2042255926936121D-12
   0.1000000000000000D-06   0.2042255926936120D-14   0.2042255926936120D-14
   0.1000000000000000D-07   0.2042255926936120D-16   0.2042255926936120D-16
   0.1000000000000000D-08   0.2042255926936121D-18   0.2042255926936121D-18
   0.1000000000000000D-09   0.2042255926936121D-20   0.2042255926936121D-20

Conclusion: The adjoint test now passes perfectly, maintaining precision up to the limits of double-precision floating-point format.

4. Attached Files for Verification

Please find the attached tl_ad_test.zip which contains the source codes and outputs for reproducibility:

  • tl_ad_test_before_bug_fixed.f90: Source code for the TL/AD tests before the bug fix.
  • tl_ad_test_before_bug_fixed.exe: Standalone executable compiled via ifort (no external dependencies required).
  • test_qr_tl_before_bug_fixed.txt & test_qr_ad_before_bug_fixed.txt: Output results before the fix.
  • tl_ad_test_after_bug_fixed.f90: Source code for the TL/AD tests after the bug fix.
  • tl_ad_test_after_bug_fixed.exe: Standalone executable compiled via ifort.
  • test_qr_tl_after_bug_fixed.txt & test_qr_ad_after_bug_fixed.txt: Output results after the fix.

(Please see the attached tl_ad_test.zip file below)
tl_ad_test.zip

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.

3 participants