Skip to content

Add Spectral Nudging Option and Fix Nudging Behavior When Files Are Missing#1402

Open
patcal wants to merge 2 commits into
ESCOMP:cam_developmentfrom
patcal:cam6_4_116_NudgingRevision
Open

Add Spectral Nudging Option and Fix Nudging Behavior When Files Are Missing#1402
patcal wants to merge 2 commits into
ESCOMP:cam_developmentfrom
patcal:cam6_4_116_NudgingRevision

Conversation

@patcal

@patcal patcal commented Sep 30, 2025

Copy link
Copy Markdown
Collaborator

This pull request addresses issues #1393 and #1273

For Issue #1273 an error exit with a message is invoked if a missing nudging file is encountered.

For Issue #1393 a module for computing spherical harmonics on the physics grid is implemented. The nudging module has additional functionality that uses this module to optionally filter nudging tendencies to scales larger then a specified truncation scale.

This functionality is controlled by 2 additional variables in the &nudging_nl namelist.
Nudge_SpectralFilter- LOGICAL Option to apply spherical harminic filtering to
the model state and target data so that nudging
tendencies are only applied to scales larger than
the specified truncation.

Nudge_SpectralNtrunc - INT The number of meridional spherical harmonic modes used
for spectral filtering. The nominal horizontal scale of
the filtering can be estimated as:

                                                          Hscale = PI*6350/Nudge_SpectralNtrunc

                                          i.e. Nudge_SpectralNtrunc=40 corresponds to a horizontal 
                                                 nudging scale  Hscale~500km.

@patcal patcal requested a review from fvitt September 30, 2025 05:29
@patcal patcal added bug-fix This PR was created to fix a specific bug. CoupledEval3 labels Sep 30, 2025
@cacraigucar cacraigucar self-assigned this Sep 30, 2025

@fvitt fvitt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Some initial questions and comments. Do you have a test case for spectral nudging that you can point me to? I can implement a regression test case.


logical :: Nudge_SpectralFilter =.false.
integer :: Nudge_SpectralNtrunc = -1
integer :: Nudge_SpectralNbasis = -1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I am not seeing where Nudge_SpectralNbasis gets sets. Is it always -1?

Comment on lines +1351 to +1355
write(iulog,*) 'NUDGING: WARNING - analyses file NOT FOUND. You can switch nudging '
write(iulog,*) 'NUDGING: OFF to coast thru a known gap in your files '
write(iulog,*) 'NUDGING: by commenting out the following endrun command.'
endif
call endrun('nudging_timestep_init:: ERROR Missing Nudging File')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should a namelist switch to turn on / off the abort behavior? I agree that aborting the run should be the default behavior.

Comment thread src/utils/spherical_harmonic_mod.F90 Outdated
!=======================================================================

!=======================================================================
! legacy spherepack routines

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

As far as I can tell, these spherepack routines are duplicates of the spherepack routines in zonal_mean_mod.F90. If so, the spherepack routines in zonal_mean_mod should be removed and zonal_mean_mod should use the routines here.

Comment thread src/utils/spherical_harmonic_mod.F90 Outdated


!=======================================================================
subroutine Invert_Matrix(I_Mat,Nbas,O_InvMat)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This looks like a duplicate of Invert_Matrix in zonal_mean_mod

Comment thread src/utils/spherical_harmonic_mod.F90 Outdated

! Type definitions
!-------------------
type SphericalHarmonic_t

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could the existing ZonalMean class be replaced by "special" use of this SphericalHarmonic class (m=0)?

@jtruesdal

Copy link
Copy Markdown
Collaborator

Thanks @patcal I'll see if I can update this to the head of the trunk.

! the specified truncation.
!
! Nudge_SpectralNtrunc - INT The number of meridional spherical harmonic modes used
! for spectral filtering. The nominal horizontal scale of

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
! for spectral filtering. The nominal horizontal scale of
! for spectral filtering. The nominal horizontal scale (km) of

real(r8),allocatable:: Zonal_Bamp3d(:,:)

logical :: Nudge_SpectralFilter =.false.
integer :: Nudge_SpectralNtrunc = -1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nudge_SpectralNtrunc should have a check in readnl to make sure its set to something other than the default of -1 along with a message letting the user know about the missing truncation value before attempting the initialization


<entry id="Nudge_SpectralNring" type="integer" category="nudging"
group="nudging_nl" valid_values="" >
Set size of local-area grid used to suppress Samping Errors.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Samping -> Sampling here and another 3 times below.

end do
end do

call shr_reprosum_calc(Csum, Bamp, count, nlcols, this%nbas, gbl_count=ngcols_p, commid=mpicom)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This shr_reprosum_calc call within the level loop will be a bottleneck. Can you compute the local covariance with input data and basis functions for all levels first and then make a single reprosum call. Something like this. Not tested.

! Flatten the vertical and basis dimensions to allow a single MPI reduction
nbas_x_nlev = this%nbas * nlev
allocate(Bamp_flat(nbas_x_nlev), stat=astat)
allocate(Csum(nlcols, nbas_x_nlev), stat=astat)

do ll= 1,nlev
do nn= 1,this%nbas
idx = (ll - 1) * this%nbas + nn
count = 0
do lchnk=begchunk,endchunk
ncols = get_ncols_p(lchnk)
do cc = 1,ncols
count=count+1
Csum(count,idx) = I_Gdata(cc,ll,lchnk)*this%basis(cc,lchnk,nn)*this%area(cc,lchnk)
end do
end do
end do
end do

call shr_reprosum_calc(Csum, Bamp_flat, count, nlcols, nbas_x_nlev, gbl_count=ngcols_p, commid=mpicom)

! Unpack the flattened amplitudes into the 2D output array
do ll= 1,nlev
do nn=1,this%nbas
idx = (ll - 1) * this%nbas + nn
O_Bamp(nn,ll) = Bamp_flat(idx)
end do
end do

! Compute Covariance with input data and basis functions
!--------------------------------------------------------
do ll= 1,nlev

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Pull reprosum out of level loop like in calc_SphericalHarmonic_3Damps_GS. Since this%map(n2, nn) is applied after the reduction, you can unpack Gcov into a temporary Gcov_by_level(nbas) array for each level, and then perform the map multiplication against Gcov_by_level.

end do
end do

call shr_reprosum_calc(Csum, Gcov, count, nlcols, this%nbas, gbl_count=ngcols_p, commid=mpicom)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same as other 2 3d routines, pull shr_reprosum_calc out of level loop.

@jtruesdal jtruesdal left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is a nice refactor. I didn't test the code to pull shr_reprosum out of the level loop it was just an example but something like that should work.

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

Labels

bug-fix This PR was created to fix a specific bug. CoupledEval3 Must have CESM3

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants