Skip to content

Commit c0f8e25

Browse files
committed
+Steps to correct Kelvin_initialization issues
This commit takes the first steps toward correcting problems with the Kelvin initialization code, including making the OBC nudging timescale an explicit parameter and adding a number of comments identifying concerns and suggesting possible improvements with the code that is used when KELVIN_WAVE_MODE > 0. This commit includes the introduction of the new runtime parameter KELVIN_WAVE_VEL_NUDGING_TIMESCALE, with a default value set to recover the current hard-coded answers. A new warning message cautions about the suspected problems with the internal wave version of the code. By default, all answers are bitwise identical in the 4 Kelvin wave test cases that can be found at github.com/ESMG/ESMG-configs, but there is a new parameter in the MOM_parameter_doc.all files these cases.
1 parent e3e9c69 commit c0f8e25

File tree

1 file changed

+38
-9
lines changed

1 file changed

+38
-9
lines changed

src/user/Kelvin_initialization.F90

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ module Kelvin_initialization
4545
real :: wave_period !< Period of the mode-0 waves [T ~> s]
4646
real :: ssh_amp !< Amplitude of the sea surface height forcing for mode-0 waves [Z ~> m]
4747
real :: inflow_amp !< Amplitude of the boundary velocity forcing for internal waves [L T-1 ~> m s-1]
48+
real :: OBC_nudging_time !< The timescale with which the inflowing open boundary velocities are nudged toward
49+
!! their intended values with the Kelvin wave test case [T ~> s], or a negative
50+
!! value to retain the value that is set when the OBC segments are initialized.
4851
end type Kelvin_OBC_CS
4952

5053
! This include declares and sets the variable "version".
@@ -114,10 +117,21 @@ function register_Kelvin_OBC(param_file, CS, US, OBC_Reg)
114117
"at the open boundaries.", units="m s-1", default=1.0, scale=US%m_s_to_L_T)
115118
endif
116119

120+
call get_param(param_file, mdl, "KELVIN_WAVE_VEL_NUDGING_TIMESCALE", CS%OBC_nudging_time, &
121+
"The timescale with which the inflowing open boundary velocities are nudged toward "//&
122+
"their intended values with the Kelvin wave test case, or a negative value to keep "//&
123+
"the value that is set when the OBC segments are initialized.", &
124+
units="s", default=1.0/(0.3*86400.), scale=US%s_to_T)
125+
!### Change the default nudging timescale to -1. or another value?
126+
117127
! Register the Kelvin open boundary.
118128
call register_OBC(casename, param_file, OBC_Reg)
119129
register_Kelvin_OBC = .true.
120130

131+
if (CS%mode > 0) call MOM_error(WARNING, &
132+
"register_Kelvin_OBC: The Kelvin_initialization code is not yet working properly unless KELVIN_WAVE_MODE = 0.")
133+
! TODO: Revisit and correct the internal Kelvin wave test case.
134+
121135
end function register_Kelvin_OBC
122136

123137
!> Clean up the Kelvin wave OBC from registry.
@@ -193,7 +207,7 @@ subroutine Kelvin_set_OBC_data(OBC, CS, G, GV, US, h, Time)
193207
real :: time_sec ! The time in the run [T ~> s]
194208
real :: cff ! The wave speed [L T-1 ~> m s-1]
195209
real :: N0 ! Brunt-Vaisala frequency times a rescaling of slopes [L Z-1 T-1 ~> s-1]
196-
real :: lambda ! Offshore decay scale [L-1 ~> m-1]
210+
real :: lambda ! Offshore decay scale, i.e. the inverse of the deformation radius of a mode [L-1 ~> m-1]
197211
real :: omega ! Wave frequency [T-1 ~> s-1]
198212
real :: PI ! The ratio of the circumference of a circle to its diameter [nondim]
199213
real :: depth_tot(SZI_(G),SZJ_(G)) ! The total depth of the ocean [Z ~> m]
@@ -233,13 +247,17 @@ subroutine Kelvin_set_OBC_data(OBC, CS, G, GV, US, h, Time)
233247
omega = 2.0 * PI / CS%wave_period
234248
val1 = sin(omega * time_sec)
235249
else
250+
! This is supposed to be a linear internal Kelvin wave case, so I do not understand the purpose
251+
! of the squared velocity here. -RWH
236252
mag_int = CS%inflow_amp**2
237253
N0 = sqrt((CS%rho_range / CS%rho_0) * (GV%g_Earth / CS%H0))
238254
lambda = PI * CS%mode * CS%F_0 / (CS%H0 * N0)
239255
! Two wavelengths in domain
240-
omega = (4.0 * CS%H0 * N0) / (CS%mode * US%m_to_L*G%len_lon)
241-
!### There is a bug here when len_lon is in km. This should be
242-
! omega = (4.0 * CS%H0 * N0) / (CS%mode * G%grid_unit_to_L*G%len_lon)
256+
! The reason for the factor of 0.001 is unclear, but it is needed to recreate the previous answers. -RWH
257+
omega = (4.0 * CS%H0 * N0) / (CS%mode * (0.001*G%grid_unit_to_L)*G%len_lon)
258+
! If the modal wave speed were calculated via wave_speeds(), we should have
259+
! lambda = CS%F_0 / CS%cg_mode
260+
! omega = (4.0 * PI / (G%grid_unit_to_L*G%len_lon)) * CS%cg_mode
243261
endif
244262

245263
sina = sin(CS%coast_angle)
@@ -251,9 +269,9 @@ subroutine Kelvin_set_OBC_data(OBC, CS, G, GV, US, h, Time)
251269
if (segment%direction == OBC_DIRECTION_E) cycle
252270
if (segment%direction == OBC_DIRECTION_N) cycle
253271

254-
! This should be somewhere else...
255-
!### This is supposed to be a timescale [T ~> s] but appears to be a rate in [s-1].
256-
segment%Velocity_nudging_timescale_in = US%s_to_T * 1.0/(0.3*86400)
272+
! If OBC_nudging_time is negative, the value of Velocity_nudging_timescale_in that was set
273+
! when the segments are initialized is retained.
274+
if (CS%OBC_nudging_time >= 0.0) segment%Velocity_nudging_timescale_in = CS%OBC_nudging_time
257275

258276
if (segment%direction == OBC_DIRECTION_W) then
259277
IsdB = segment%HI%IsdB ; IedB = segment%HI%IedB
@@ -281,11 +299,22 @@ subroutine Kelvin_set_OBC_data(OBC, CS, G, GV, US, h, Time)
281299
enddo
282300
endif
283301
else
284-
! Baroclinic, not rotated yet
302+
! Baroclinic, not rotated yet (and apparently not working as intended yet).
285303
segment%SSH(I,j) = 0.0
286304
segment%normal_vel_bt(I,j) = 0.0
305+
! I suspect that the velocities in both of the following loops should instead be
306+
! normal_vel(I,j,k) = CS%inflow_amp * CS%u_struct(k) * exp(-lambda * y) * cos(omega * time_sec)
307+
! In addition, there should be a specification of the interface-height anomalies at the
308+
! open boundaries that are specified as something like
309+
! eta_anom(I,j,K) = (CS%inflow_amp*depth_tot/CS%cg_mode) * CS%w_struct(K) * &
310+
! exp(-lambda * y) * cos(omega * time_sec)
311+
! In these expressions CS%u_struct and CS%w_struct could be returned from the subroutine wave_speeds
312+
! in MOM_wave_speed() based on the horizontally uniform initial state.
287313
if (segment%nudged) then
288314
do k=1,nz
315+
! Note that mag_int is the square of the specified inflow amplitude, in [L2 T-2 ~> m2 s-2].
316+
! The following expression is dimensionally correct, but I do not understand why the
317+
! normal velocities should scale with the square of their amplitude. -RWH
289318
segment%nudged_normal_vel(I,j,k) = mag_int * lambda / CS%F_0 * &
290319
exp(-lambda * y) * cos(PI * CS%mode * (k - 0.5) / nz) * &
291320
cos(omega * time_sec)
@@ -339,7 +368,7 @@ subroutine Kelvin_set_OBC_data(OBC, CS, G, GV, US, h, Time)
339368
enddo
340369
endif
341370
else
342-
! Not rotated yet
371+
! Not rotated yet (also see the notes above on how this case might be improved)
343372
segment%SSH(i,J) = 0.0
344373
segment%normal_vel_bt(i,J) = 0.0
345374
if (segment%nudged) then

0 commit comments

Comments
 (0)