From 5df79cf37093205422b64f1cdef846e79cae9590 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 6 Oct 2026 11:35:13 -0400 Subject: [PATCH] cam_snapshot: write the physics grid coordinates in radians Snapshot tapes now carry lat_rad and lon_rad, the column latitude and longitude in radians as the physics grid hands them to parameterizations, on both the before and after tapes. The history coordinates lat and lon are in degrees, and converting them back to radians in CAM-SIMA differs from CAM's values by one ulp at some columns (44 of 486 at ne3pg3), which seeds answer differences in every latitude-dependent scheme tested through FPHYStest. The CAM-SIMA null dycore prefers these fields when present. Answer impact: none (two new diagnostic fields on snapshot tapes only). Assisted-by: claude-fable:5.1 --- src/control/cam_snapshot_common.F90 | 64 +++++++++++++++++++++++++++++ src/physics/cam/cam_snapshot.F90 | 2 + src/physics/cam7/cam_snapshot.F90 | 2 + 3 files changed, 68 insertions(+) diff --git a/src/control/cam_snapshot_common.F90 b/src/control/cam_snapshot_common.F90 index 39ff43f1ae..42b17b9956 100644 --- a/src/control/cam_snapshot_common.F90 +++ b/src/control/cam_snapshot_common.F90 @@ -28,6 +28,7 @@ module cam_snapshot_common public :: cam_snapshot_ptend_outfld public :: snapshot_type public :: cam_state_snapshot_init +public :: cam_grid_snapshot_init public :: cam_cnst_snapshot_init public :: cam_tend_snapshot_init public :: cam_ptend_snapshot_init @@ -38,6 +39,7 @@ module cam_snapshot_common private :: snapshot_addfld_nd private :: state_snapshot_all_outfld +private :: grid_snapshot_all_outfld private :: cnst_snapshot_all_outfld private :: tend_snapshot_all_outfld private :: cam_in_snapshot_all_outfld @@ -72,6 +74,7 @@ module cam_snapshot_common end type pbuf_info_type integer :: nstate_var +integer :: ngrid_var integer :: ncnst_var integer :: ntend_var integer :: ncam_in_var @@ -82,6 +85,7 @@ module cam_snapshot_common ! Note the maximum number of variables for each type type (snapshot_type) :: state_snapshot(30) +type (snapshot_type) :: grid_snapshot(2) type (snapshot_type) :: cnst_snapshot(pcnst) type (snapshot_type) :: tend_snapshot(6) type (snapshot_type) :: cam_in_snapshot(pcnst+35) ! needs to be bigger than pcnst because cam_in%cflx is split by constituent and cam_in%dstflx by bin. @@ -120,6 +124,9 @@ subroutine cam_snapshot_all_outfld(file_num, state, tend, cam_in, cam_out, pbuf) ! Write out all the state fields call state_snapshot_all_outfld(lchnk, file_num, state) + ! Write out the physics grid coordinates in radians + call grid_snapshot_all_outfld(lchnk, file_num) + ! Write out all the constituent fields call cnst_snapshot_all_outfld(lchnk, file_num, state%q) @@ -288,6 +295,28 @@ subroutine cam_state_snapshot_init(cam_snapshot_before_num_in, cam_snapshot_afte end subroutine cam_state_snapshot_init +subroutine cam_grid_snapshot_init(cam_snapshot_before_num, cam_snapshot_after_num) + +!-------------------------------------------------------- +! This subroutine does the addfld calls for the physics grid coordinates in radians. +! The history coordinates lat and lon are written in degrees, and converting them back to +! radians in CAM-SIMA differs from the values CAM physics used by one ulp at some columns, +! which seeds answer differences in every latitude-dependent scheme. +! The CAM-SIMA null dycore prefers these fields when they are present on the snapshot. +!-------------------------------------------------------- + + integer,intent(in) :: cam_snapshot_before_num, cam_snapshot_after_num + + ngrid_var = 0 + + call snapshot_addfld( ngrid_var, grid_snapshot, cam_snapshot_before_num, cam_snapshot_after_num, & + 'grid%lat_rad', 'lat_rad', 'radians', horiz_only) + + call snapshot_addfld( ngrid_var, grid_snapshot, cam_snapshot_before_num, cam_snapshot_after_num, & + 'grid%lon_rad', 'lon_rad', 'radians', horiz_only) + +end subroutine cam_grid_snapshot_init + subroutine cam_cnst_snapshot_init(cam_snapshot_before_num, cam_snapshot_after_num) !-------------------------------------------------------- @@ -787,6 +816,41 @@ subroutine snapshot_addfld(nddt_var, ddt_snapshot, cam_snapshot_before_num, cam_ end subroutine snapshot_addfld +subroutine grid_snapshot_all_outfld(lchnk, file_num) + + use phys_grid, only: get_rlat_all_p, get_rlon_all_p + + integer, intent(in) :: lchnk + integer, intent(in) :: file_num + + real(r8) :: rcoord(pcols) + integer :: i + + do i=1, ngrid_var + + ! Turn on the writing for only the requested tape (file_num) + call cam_history_snapshot_activate(trim(grid_snapshot(i)%standard_name), file_num) + + ! Select the coordinate which is being written + select case(grid_snapshot(i)%ddt_string) + + case ('grid%lat_rad') + call get_rlat_all_p(lchnk, pcols, rcoord) + + case ('grid%lon_rad') + call get_rlon_all_p(lchnk, pcols, rcoord) + + case default + call endrun('ERROR in grid_snapshot_all_outfld: no case for '//trim(grid_snapshot(i)%ddt_string)) + + end select + + call outfld(grid_snapshot(i)%standard_name, rcoord, pcols, lchnk) + + end do + +end subroutine grid_snapshot_all_outfld + subroutine state_snapshot_all_outfld(lchnk, file_num, state) use physics_types, only: phys_te_idx, dyn_te_idx diff --git a/src/physics/cam/cam_snapshot.F90 b/src/physics/cam/cam_snapshot.F90 index 37cf062a32..3f475919d1 100644 --- a/src/physics/cam/cam_snapshot.F90 +++ b/src/physics/cam/cam_snapshot.F90 @@ -20,6 +20,7 @@ module cam_snapshot use cam_logfile, only: iulog use cam_snapshot_common, only: snapshot_type, cam_snapshot_deactivate, cam_snapshot_all_outfld, cam_snapshot_ptend_outfld use cam_snapshot_common, only: snapshot_type, cam_state_snapshot_init, cam_cnst_snapshot_init, cam_tend_snapshot_init +use cam_snapshot_common, only: cam_grid_snapshot_init use cam_snapshot_common, only: cam_ptend_snapshot_init, cam_in_snapshot_init, cam_out_snapshot_init use cam_snapshot_common, only: cam_pbuf_snapshot_init, snapshot_addfld @@ -64,6 +65,7 @@ subroutine cam_snapshot_init(cam_in_arr, cam_out_arr, pbuf, index) if (cam_snapshot_before_num <= 0 .and. cam_snapshot_after_num <= 0) return ! No snapshot files are being requested call cam_state_snapshot_init(cam_snapshot_before_num, cam_snapshot_after_num) + call cam_grid_snapshot_init(cam_snapshot_before_num, cam_snapshot_after_num) call cam_cnst_snapshot_init(cam_snapshot_before_num, cam_snapshot_after_num) call cam_tend_snapshot_init(cam_snapshot_before_num, cam_snapshot_after_num) call cam_ptend_snapshot_init(cam_snapshot_after_num) diff --git a/src/physics/cam7/cam_snapshot.F90 b/src/physics/cam7/cam_snapshot.F90 index 814fd20cd3..135778e786 100644 --- a/src/physics/cam7/cam_snapshot.F90 +++ b/src/physics/cam7/cam_snapshot.F90 @@ -20,6 +20,7 @@ module cam_snapshot use cam_logfile, only: iulog use cam_snapshot_common, only: snapshot_type, cam_snapshot_deactivate, cam_snapshot_all_outfld, cam_snapshot_ptend_outfld use cam_snapshot_common, only: snapshot_type, cam_state_snapshot_init, cam_cnst_snapshot_init, cam_tend_snapshot_init +use cam_snapshot_common, only: cam_grid_snapshot_init use cam_snapshot_common, only: cam_ptend_snapshot_init, cam_in_snapshot_init, cam_out_snapshot_init use cam_snapshot_common, only: cam_pbuf_snapshot_init, snapshot_addfld @@ -64,6 +65,7 @@ subroutine cam_snapshot_init(cam_in_arr, cam_out_arr, pbuf, index) if (cam_snapshot_before_num <= 0 .and. cam_snapshot_after_num <= 0) return ! No snapshot files are being requested call cam_state_snapshot_init(cam_snapshot_before_num, cam_snapshot_after_num) + call cam_grid_snapshot_init(cam_snapshot_before_num, cam_snapshot_after_num) call cam_cnst_snapshot_init(cam_snapshot_before_num, cam_snapshot_after_num) call cam_tend_snapshot_init(cam_snapshot_before_num, cam_snapshot_after_num) call cam_ptend_snapshot_init(cam_snapshot_after_num)