MOM6
MOM_tidal_forcing.F90
Go to the documentation of this file.
1 !> Tidal contributions to geopotential
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
6 use mom_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end, &
7  clock_module
8 use mom_domains, only : pass_var
9 use mom_error_handler, only : mom_error, fatal, warning
11 use mom_grid, only : ocean_grid_type
12 use mom_io, only : field_exists, file_exists, mom_read_data
13 use mom_time_manager, only : time_type, time_type_to_real
14 
15 implicit none ; private
16 
19 
20 #include <MOM_memory.h>
21 
22 integer, parameter :: max_constituents = 10 !< The maximum number of tidal
23  !! constituents that could be used.
24 
25 !> The control structure for the MOM_tidal_forcing module
26 type, public :: tidal_forcing_cs ; private
27  logical :: use_sal_scalar !< If true, use the scalar approximation when
28  !! calculating self-attraction and loading.
29  logical :: tidal_sal_from_file !< If true, Read the tidal self-attraction
30  !! and loading from input files, specified
31  !! by TIDAL_INPUT_FILE.
32  logical :: use_prev_tides !< If true, use the SAL from the previous
33  !! iteration of the tides to facilitate convergence.
34  real :: sal_scalar !< The constant of proportionality between sea surface
35  !! height (really it should be bottom pressure) anomalies
36  !! and bottom geopotential anomalies.
37  integer :: nc !< The number of tidal constituents in use.
38  real, dimension(MAX_CONSTITUENTS) :: &
39  freq, & !< The frequency of a tidal constituent [s-1].
40  phase0, & !< The phase of a tidal constituent at time 0, in radians.
41  amp, & !< The amplitude of a tidal constituent at time 0 [m].
42  love_no !< The Love number of a tidal constituent at time 0 [nondim].
43  integer :: struct(max_constituents) !< An encoded spatial structure for each constituent
44  character (len=16) :: const_name(max_constituents) !< The name of each constituent
45 
46  real, pointer, dimension(:,:,:) :: &
47  sin_struct => null(), & !< The sine and cosine based structures that can
48  cos_struct => null(), & !< be associated with the astronomical forcing.
49  cosphasesal => null(), & !< The cosine and sine of the phase of the
50  sinphasesal => null(), & !< self-attraction and loading amphidromes.
51  ampsal => null(), & !< The amplitude of the SAL [m].
52  cosphase_prev => null(), & !< The cosine and sine of the phase of the
53  sinphase_prev => null(), & !< amphidromes in the previous tidal solutions.
54  amp_prev => null() !< The amplitude of the previous tidal solution [m].
55 end type tidal_forcing_cs
56 
57 integer :: id_clock_tides !< CPU clock for tides
58 
59 contains
60 
61 !> This subroutine allocates space for the static variables used
62 !! by this module. The metrics may be effectively 0, 1, or 2-D arrays,
63 !! while fields like the background viscosities are 2-D arrays.
64 !! ALLOC is a macro defined in MOM_memory.h for allocate or nothing with
65 !! static memory.
66 subroutine tidal_forcing_init(Time, G, param_file, CS)
67  type(time_type), intent(in) :: time !< The current model time.
68  type(ocean_grid_type), intent(inout) :: g !< The ocean's grid structure.
69  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters.
70  type(tidal_forcing_cs), pointer :: cs !< A pointer that is set to point to the control
71  !! structure for this module.
72  ! Local variables
73  real, dimension(SZI_(G), SZJ_(G)) :: &
74  phase, & ! The phase of some tidal constituent.
75  lat_rad, lon_rad ! Latitudes and longitudes of h-points in radians.
76  real :: deg_to_rad
77  real, dimension(MAX_CONSTITUENTS) :: freq_def, phase0_def, amp_def, love_def
78  logical :: use_const ! True if a constituent is being used.
79  logical :: use_m2, use_s2, use_n2, use_k2, use_k1, use_o1, use_p1, use_q1
80  logical :: use_mf, use_mm
81  logical :: tides ! True if a tidal forcing is to be used.
82  logical :: fail_if_missing = .true.
83 ! This include declares and sets the variable "version".
84 #include "version_variable.h"
85  character(len=40) :: mdl = "MOM_tidal_forcing" ! This module's name.
86  character(len=128) :: mesg
87  character(len=200) :: tidal_input_files(4*max_constituents)
88  integer :: i, j, c, is, ie, js, je, isd, ied, jsd, jed, nc
89  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
90  isd = g%isd ; ied = g%ied ; jsd = g%jsd; jed = g%jed
91 
92  if (associated(cs)) then
93  call mom_error(warning, "tidal_forcing_init called with an associated "// &
94  "control structure.")
95  return
96  endif
97 
98  ! Read all relevant parameters and write them to the model log.
99  call log_version(param_file, mdl, version, "")
100  call get_param(param_file, mdl, "TIDES", tides, &
101  "If true, apply tidal momentum forcing.", default=.false.)
102 
103  if (.not.tides) return
104 
105  allocate(cs)
106 
107  ! Set up the spatial structure functions for the diurnal, semidiurnal, and
108  ! low-frequency tidal components.
109  allocate(cs%sin_struct(isd:ied,jsd:jed,3)) ; cs%sin_struct(:,:,:) = 0.0
110  allocate(cs%cos_struct(isd:ied,jsd:jed,3)) ; cs%cos_struct(:,:,:) = 0.0
111  deg_to_rad = 4.0*atan(1.0)/180.0
112  do j=js-1,je+1 ; do i=is-1,ie+1
113  lat_rad(i,j) = g%geoLatT(i,j)*deg_to_rad
114  lon_rad(i,j) = g%geoLonT(i,j)*deg_to_rad
115  enddo ; enddo
116  do j=js-1,je+1 ; do i=is-1,ie+1
117  cs%sin_struct(i,j,1) = -sin(2.0*lat_rad(i,j)) * sin(lon_rad(i,j))
118  cs%cos_struct(i,j,1) = sin(2.0*lat_rad(i,j)) * cos(lon_rad(i,j))
119  cs%sin_struct(i,j,2) = -cos(lat_rad(i,j))**2 * sin(2.0*lon_rad(i,j))
120  cs%cos_struct(i,j,2) = cos(lat_rad(i,j))**2 * cos(2.0*lon_rad(i,j))
121  cs%sin_struct(i,j,3) = 0.0
122  cs%cos_struct(i,j,3) = (0.5-1.5*sin(lat_rad(i,j))**2)
123  enddo ; enddo
124 
125  call get_param(param_file, mdl, "TIDE_M2", use_m2, &
126  "If true, apply tidal momentum forcing at the M2 "//&
127  "frequency. This is only used if TIDES is true.", &
128  default=.false.)
129  call get_param(param_file, mdl, "TIDE_S2", use_s2, &
130  "If true, apply tidal momentum forcing at the S2 "//&
131  "frequency. This is only used if TIDES is true.", &
132  default=.false.)
133  call get_param(param_file, mdl, "TIDE_N2", use_n2, &
134  "If true, apply tidal momentum forcing at the N2 "//&
135  "frequency. This is only used if TIDES is true.", &
136  default=.false.)
137  call get_param(param_file, mdl, "TIDE_K2", use_k2, &
138  "If true, apply tidal momentum forcing at the K2 "//&
139  "frequency. This is only used if TIDES is true.", &
140  default=.false.)
141  call get_param(param_file, mdl, "TIDE_K1", use_k1, &
142  "If true, apply tidal momentum forcing at the K1 "//&
143  "frequency. This is only used if TIDES is true.", &
144  default=.false.)
145  call get_param(param_file, mdl, "TIDE_O1", use_o1, &
146  "If true, apply tidal momentum forcing at the O1 "//&
147  "frequency. This is only used if TIDES is true.", &
148  default=.false.)
149  call get_param(param_file, mdl, "TIDE_P1", use_p1, &
150  "If true, apply tidal momentum forcing at the P1 "//&
151  "frequency. This is only used if TIDES is true.", &
152  default=.false.)
153  call get_param(param_file, mdl, "TIDE_Q1", use_q1, &
154  "If true, apply tidal momentum forcing at the Q1 "//&
155  "frequency. This is only used if TIDES is true.", &
156  default=.false.)
157  call get_param(param_file, mdl, "TIDE_MF", use_mf, &
158  "If true, apply tidal momentum forcing at the MF "//&
159  "frequency. This is only used if TIDES is true.", &
160  default=.false.)
161  call get_param(param_file, mdl, "TIDE_MM", use_mm, &
162  "If true, apply tidal momentum forcing at the MM "//&
163  "frequency. This is only used if TIDES is true.", &
164  default=.false.)
165 
166  ! Determine how many tidal components are to be used.
167  nc = 0
168  if (use_m2) nc=nc+1 ; if (use_s2) nc=nc+1
169  if (use_n2) nc=nc+1 ; if (use_k2) nc=nc+1
170  if (use_k1) nc=nc+1 ; if (use_o1) nc=nc+1
171  if (use_p1) nc=nc+1 ; if (use_q1) nc=nc+1
172  if (use_mf) nc=nc+1 ; if (use_mm) nc=nc+1
173  cs%nc = nc
174 
175  if (nc == 0) then
176  call mom_error(fatal, "tidal_forcing_init: "// &
177  "TIDES are defined, but no tidal constituents are used.")
178  return
179  endif
180 
181  call get_param(param_file, mdl, "TIDAL_SAL_FROM_FILE", cs%tidal_sal_from_file, &
182  "If true, read the tidal self-attraction and loading "//&
183  "from input files, specified by TIDAL_INPUT_FILE. "//&
184  "This is only used if TIDES is true.", default=.false.)
185  call get_param(param_file, mdl, "USE_PREVIOUS_TIDES", cs%use_prev_tides, &
186  "If true, use the SAL from the previous iteration of the "//&
187  "tides to facilitate convergent iteration. "//&
188  "This is only used if TIDES is true.", default=.false.)
189  call get_param(param_file, mdl, "TIDE_USE_SAL_SCALAR", cs%use_sal_scalar, &
190  "If true and TIDES is true, use the scalar approximation "//&
191  "when calculating self-attraction and loading.", &
192  default=.not.cs%tidal_sal_from_file)
193  ! If it is being used, sal_scalar MUST be specified in param_file.
194  if (cs%use_sal_scalar .or. cs%use_prev_tides) &
195  call get_param(param_file, mdl, "TIDE_SAL_SCALAR_VALUE", cs%sal_scalar, &
196  "The constant of proportionality between sea surface "//&
197  "height (really it should be bottom pressure) anomalies "//&
198  "and bottom geopotential anomalies. This is only used if "//&
199  "TIDES and TIDE_USE_SAL_SCALAR are true.", units="m m-1", &
200  fail_if_missing=.true.)
201 
202  if (nc > max_constituents) then
203  write(mesg,'("Increase MAX_CONSTITUENTS in MOM_tidal_forcing.F90 to at least",I3, &
204  &"to accommodate all the registered tidal constituents.")') nc
205  call mom_error(fatal, "MOM_tidal_forcing"//mesg)
206  endif
207 
208  do c=1,4*max_constituents ; tidal_input_files(c) = "" ; enddo
209 
210  if (cs%tidal_sal_from_file .or. cs%use_prev_tides) then
211  call get_param(param_file, mdl, "TIDAL_INPUT_FILE", tidal_input_files, &
212  "A list of input files for tidal information.", &
213  default = "", fail_if_missing=.true.)
214  endif
215 
216  ! Set the parameters for all components that are in use.
217  c=0
218  if (use_m2) then
219  c=c+1 ; cs%const_name(c) = "M2" ; cs%freq(c) = 1.4051890e-4 ; cs%struct(c) = 2
220  cs%love_no(c) = 0.693 ; cs%amp(c) = 0.242334 ; cs%phase0(c) = 0.0
221  freq_def(c) = cs%freq(c) ; love_def(c) = cs%love_no(c)
222  amp_def(c) = cs%amp(c) ; phase0_def(c) = cs%phase0(c)
223  endif
224 
225  if (use_s2) then
226  c=c+1 ; cs%const_name(c) = "S2" ; cs%freq(c) = 1.4544410e-4 ; cs%struct(c) = 2
227  cs%love_no(c) = 0.693 ; cs%amp(c) = 0.112743 ; cs%phase0(c) = 0.0
228  freq_def(c) = cs%freq(c) ; love_def(c) = cs%love_no(c)
229  amp_def(c) = cs%amp(c) ; phase0_def(c) = cs%phase0(c)
230  endif
231 
232  if (use_n2) then
233  c=c+1 ; cs%const_name(c) = "N2" ; cs%freq(c) = 1.3787970e-4 ; cs%struct(c) = 2
234  cs%love_no(c) = 0.693 ; cs%amp(c) = 0.046397 ; cs%phase0(c) = 0.0
235  freq_def(c) = cs%freq(c) ; love_def(c) = cs%love_no(c)
236  amp_def(c) = cs%amp(c) ; phase0_def(c) = cs%phase0(c)
237  endif
238 
239  if (use_k2) then
240  c=c+1 ; cs%const_name(c) = "K2" ; cs%freq(c) = 1.4584234e-4 ; cs%struct(c) = 2
241  cs%love_no(c) = 0.693 ; cs%amp(c) = 0.030684 ; cs%phase0(c) = 0.0
242  freq_def(c) = cs%freq(c) ; love_def(c) = cs%love_no(c)
243  amp_def(c) = cs%amp(c) ; phase0_def(c) = cs%phase0(c)
244  endif
245 
246  if (use_k1) then
247  c=c+1 ; cs%const_name(c) = "K1" ; cs%freq(c) = 0.7292117e-4 ; cs%struct(c) = 1
248  cs%love_no(c) = 0.736 ; cs%amp(c) = 0.141565 ; cs%phase0(c) = 0.0
249  freq_def(c) = cs%freq(c) ; love_def(c) = cs%love_no(c)
250  amp_def(c) = cs%amp(c) ; phase0_def(c) = cs%phase0(c)
251  endif
252 
253  if (use_o1) then
254  c=c+1 ; cs%const_name(c) = "O1" ; cs%freq(c) = 0.6759774e-4 ; cs%struct(c) = 1
255  cs%love_no(c) = 0.695 ; cs%amp(c) = 0.100661 ; cs%phase0(c) = 0.0
256  freq_def(c) = cs%freq(c) ; love_def(c) = cs%love_no(c)
257  amp_def(c) = cs%amp(c) ; phase0_def(c) = cs%phase0(c)
258  endif
259 
260  if (use_p1) then
261  c=c+1 ; cs%const_name(c) = "P1" ; cs%freq(c) = 0.7252295e-4 ; cs%struct(c) = 1
262  cs%love_no(c) = 0.706 ; cs%amp(c) = 0.046848 ; cs%phase0(c) = 0.0
263  freq_def(c) = cs%freq(c) ; love_def(c) = cs%love_no(c)
264  amp_def(c) = cs%amp(c) ; phase0_def(c) = cs%phase0(c)
265  endif
266 
267  if (use_q1) then
268  c=c+1 ; cs%const_name(c) = "Q1" ; cs%freq(c) = 0.6495854e-4 ; cs%struct(c) = 1
269  cs%love_no(c) = 0.695 ; cs%amp(c) = 0.019273 ; cs%phase0(c) = 0.0
270  freq_def(c) = cs%freq(c) ; love_def(c) = cs%love_no(c)
271  amp_def(c) = cs%amp(c) ; phase0_def(c) = cs%phase0(c)
272  endif
273 
274  if (use_mf) then
275  c=c+1 ; cs%const_name(c) = "MF" ; cs%freq(c) = 0.053234e-4 ; cs%struct(c) = 3
276  cs%love_no(c) = 0.693 ; cs%amp(c) = 0.042041 ; cs%phase0(c) = 0.0
277  freq_def(c) = cs%freq(c) ; love_def(c) = cs%love_no(c)
278  amp_def(c) = cs%amp(c) ; phase0_def(c) = cs%phase0(c)
279  endif
280 
281  if (use_mm) then
282  c=c+1 ; cs%const_name(c) = "MM" ; cs%freq(c) = 0.026392e-4 ; cs%struct(c) = 3
283  cs%love_no(c) = 0.693 ; cs%amp(c) = 0.022191 ; cs%phase0(c) = 0.0
284  freq_def(c) = cs%freq(c) ; love_def(c) = cs%love_no(c)
285  amp_def(c) = cs%amp(c) ; phase0_def(c) = cs%phase0(c)
286  endif
287 
288  ! Parse the input file to potentially override the default values for the
289  ! frequency, amplitude and initial phase of each constituent, and log the
290  ! values that are actually used.
291  do c=1,nc
292  call get_param(param_file, mdl, "TIDE_"//trim(cs%const_name(c))//"_FREQ", cs%freq(c), &
293  "Frequency of the "//trim(cs%const_name(c))//" tidal constituent. "//&
294  "This is only used if TIDES and TIDE_"//trim(cs%const_name(c))// &
295  " are true.", units="s-1", default=freq_def(c))
296  call get_param(param_file, mdl, "TIDE_"//trim(cs%const_name(c))//"_AMP", cs%amp(c), &
297  "Amplitude of the "//trim(cs%const_name(c))//" tidal constituent. "//&
298  "This is only used if TIDES and TIDE_"//trim(cs%const_name(c))// &
299  " are true.", units="m", default=amp_def(c))
300  call get_param(param_file, mdl, "TIDE_"//trim(cs%const_name(c))//"_PHASE_T0", cs%phase0(c), &
301  "Phase of the "//trim(cs%const_name(c))//" tidal constituent at time 0. "//&
302  "This is only used if TIDES and TIDE_"//trim(cs%const_name(c))// &
303  " are true.", units="radians", default=phase0_def(c))
304  enddo
305 
306  if (cs%tidal_sal_from_file) then
307  allocate(cs%cosphasesal(isd:ied,jsd:jed,nc))
308  allocate(cs%sinphasesal(isd:ied,jsd:jed,nc))
309  allocate(cs%ampsal(isd:ied,jsd:jed,nc))
310  do c=1,nc
311  ! Read variables with names like PHASE_SAL_M2 and AMP_SAL_M2.
312  call find_in_files(tidal_input_files,"PHASE_SAL_"//trim(cs%const_name(c)),phase,g)
313  call find_in_files(tidal_input_files,"AMP_SAL_"//trim(cs%const_name(c)),cs%ampsal(:,:,c),g)
314  call pass_var(phase, g%domain,complete=.false.)
315  call pass_var(cs%ampsal(:,:,c),g%domain,complete=.true.)
316  do j=js-1,je+1 ; do i=is-1,ie+1
317  cs%cosphasesal(i,j,c) = cos(phase(i,j)*deg_to_rad)
318  cs%sinphasesal(i,j,c) = sin(phase(i,j)*deg_to_rad)
319  enddo ; enddo
320  enddo
321  endif
322 
323  if (cs%USE_PREV_TIDES) then
324  allocate(cs%cosphase_prev(isd:ied,jsd:jed,nc))
325  allocate(cs%sinphase_prev(isd:ied,jsd:jed,nc))
326  allocate(cs%amp_prev(isd:ied,jsd:jed,nc))
327  do c=1,nc
328  ! Read variables with names like PHASE_PREV_M2 and AMP_PREV_M2.
329  call find_in_files(tidal_input_files,"PHASE_PREV_"//trim(cs%const_name(c)),phase,g)
330  call find_in_files(tidal_input_files,"AMP_PREV_"//trim(cs%const_name(c)),cs%amp_prev(:,:,c),g)
331  call pass_var(phase, g%domain,complete=.false.)
332  call pass_var(cs%amp_prev(:,:,c),g%domain,complete=.true.)
333  do j=js-1,je+1 ; do i=is-1,ie+1
334  cs%cosphase_prev(i,j,c) = cos(phase(i,j)*deg_to_rad)
335  cs%sinphase_prev(i,j,c) = sin(phase(i,j)*deg_to_rad)
336  enddo ; enddo
337  enddo
338  endif
339 
340  id_clock_tides = cpu_clock_id('(Ocean tides)', grain=clock_module)
341 
342 end subroutine tidal_forcing_init
343 
344 !> This subroutine finds a named variable in a list of files and reads its
345 !! values into a domain-decomposed 2-d array
346 subroutine find_in_files(filenames, varname, array, G)
347  character(len=*), dimension(:), intent(in) :: filenames !< The names of the files to search for the named variable
348  character(len=*), intent(in) :: varname !< The name of the variable to read
349  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
350  real, dimension(SZI_(G),SZJ_(G)), intent(out) :: array !< The array to fill with the data
351  ! Local variables
352  integer :: nf
353 
354  do nf=1,size(filenames)
355  if (len_trim(filenames(nf)) == 0) cycle
356  if (field_exists(filenames(nf), varname, g%Domain%mpp_domain)) then
357  call mom_read_data(filenames(nf), varname, array, g%Domain)
358  return
359  endif
360  enddo
361 
362  do nf=size(filenames),1,-1
363  if (file_exists(filenames(nf), g%Domain)) then
364  call mom_error(fatal, "MOM_tidal_forcing.F90: Unable to find "// &
365  trim(varname)//" in any of the tidal input files, last tried "// &
366  trim(filenames(nf)))
367  endif
368  enddo
369 
370  call mom_error(fatal, "MOM_tidal_forcing.F90: Unable to find any of the "// &
371  "tidal input files, including "//trim(filenames(1)))
372 
373 end subroutine find_in_files
374 
375 !> This subroutine calculates returns the partial derivative of the local
376 !! geopotential height with the input sea surface height due to self-attraction
377 !! and loading.
378 subroutine tidal_forcing_sensitivity(G, CS, deta_tidal_deta)
379  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure.
380  type(tidal_forcing_cs), pointer :: cs !< The control structure returned by a previous call to tidal_forcing_init.
381  real, intent(out) :: deta_tidal_deta !< The partial derivative of eta_tidal with
382  !! the local value of eta [nondim].
383 
384  if (cs%USE_SAL_SCALAR .and. cs%USE_PREV_TIDES) then
385  deta_tidal_deta = 2.0*cs%SAL_SCALAR
386  elseif (cs%USE_SAL_SCALAR .or. cs%USE_PREV_TIDES) then
387  deta_tidal_deta = cs%SAL_SCALAR
388  else
389  deta_tidal_deta = 0.0
390  endif
391 end subroutine tidal_forcing_sensitivity
392 
393 !> This subroutine calculates the geopotential anomalies that drive the tides,
394 !! including self-attraction and loading. Optionally, it also returns the
395 !! partial derivative of the local geopotential height with the input sea surface
396 !! height. For now, eta and eta_tidal are both geopotential heights in depth
397 !! units, but probably the input for eta should really be replaced with the
398 !! column mass anomalies.
399 subroutine calc_tidal_forcing(Time, eta, eta_tidal, G, CS, deta_tidal_deta, m_to_Z)
400  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure.
401  type(time_type), intent(in) :: time !< The time for the caluculation.
402  real, dimension(SZI_(G),SZJ_(G)), intent(in) :: eta !< The sea surface height anomaly from
403  !! a time-mean geoid [Z ~> m].
404  real, dimension(SZI_(G),SZJ_(G)), intent(out) :: eta_tidal !< The tidal forcing geopotential height
405  !! anomalies [Z ~> m].
406  type(tidal_forcing_cs), pointer :: cs !< The control structure returned by a
407  !! previous call to tidal_forcing_init.
408  real, optional, intent(out) :: deta_tidal_deta !< The partial derivative of
409  !! eta_tidal with the local value of
410  !! eta [nondim].
411  real, optional, intent(in) :: m_to_z !< A scaling factor from m to the units of eta.
412 
413  ! Local variables
414  real :: eta_astro(szi_(g),szj_(g))
415  real :: eta_sal(szi_(g),szj_(g))
416  real :: now ! The relative time in seconds.
417  real :: amp_cosomegat, amp_sinomegat
418  real :: cosomegat, sinomegat
419  real :: m_z ! A scaling factor from m to depth units.
420  real :: eta_prop ! The nondimenional constant of proportionality beteen eta and eta_tidal.
421  integer :: i, j, c, m, is, ie, js, je, isq, ieq, jsq, jeq
422  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
423  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
424 
425  if (.not.associated(cs)) return
426 
427  call cpu_clock_begin(id_clock_tides)
428 
429  if (cs%nc == 0) then
430  do j=jsq,jeq+1 ; do i=isq,ieq+1 ; eta_tidal(i,j) = 0.0 ; enddo ; enddo
431  return
432  endif
433 
434  now = time_type_to_real(time)
435 
436  if (cs%USE_SAL_SCALAR .and. cs%USE_PREV_TIDES) then
437  eta_prop = 2.0*cs%SAL_SCALAR
438  elseif (cs%USE_SAL_SCALAR .or. cs%USE_PREV_TIDES) then
439  eta_prop = cs%SAL_SCALAR
440  else
441  eta_prop = 0.0
442  endif
443 
444  if (present(deta_tidal_deta)) then
445  deta_tidal_deta = eta_prop
446  do j=jsq,jeq+1 ; do i=isq,ieq+1 ; eta_tidal(i,j) = 0.0 ; enddo ; enddo
447  else
448  do j=jsq,jeq+1 ; do i=isq,ieq+1
449  eta_tidal(i,j) = eta_prop*eta(i,j)
450  enddo ; enddo
451  endif
452 
453  m_z = 1.0 ; if (present(m_to_z)) m_z = m_to_z
454 
455  do c=1,cs%nc
456  m = cs%struct(c)
457  amp_cosomegat = m_z*cs%amp(c)*cs%love_no(c) * cos(cs%freq(c)*now + cs%phase0(c))
458  amp_sinomegat = m_z*cs%amp(c)*cs%love_no(c) * sin(cs%freq(c)*now + cs%phase0(c))
459  do j=jsq,jeq+1 ; do i=isq,ieq+1
460  eta_tidal(i,j) = eta_tidal(i,j) + (amp_cosomegat*cs%cos_struct(i,j,m) + &
461  amp_sinomegat*cs%sin_struct(i,j,m))
462  enddo ; enddo
463  enddo
464 
465  if (cs%tidal_sal_from_file) then ; do c=1,cs%nc
466  cosomegat = cos(cs%freq(c)*now)
467  sinomegat = sin(cs%freq(c)*now)
468  do j=jsq,jeq+1 ; do i=isq,ieq+1
469  eta_tidal(i,j) = eta_tidal(i,j) + m_z*cs%ampsal(i,j,c) * &
470  (cosomegat*cs%cosphasesal(i,j,c) + sinomegat*cs%sinphasesal(i,j,c))
471  enddo ; enddo
472  enddo ; endif
473 
474  if (cs%USE_PREV_TIDES) then ; do c=1,cs%nc
475  cosomegat = cos(cs%freq(c)*now)
476  sinomegat = sin(cs%freq(c)*now)
477  do j=jsq,jeq+1 ; do i=isq,ieq+1
478  eta_tidal(i,j) = eta_tidal(i,j) - m_z*cs%SAL_SCALAR*cs%amp_prev(i,j,c) * &
479  (cosomegat*cs%cosphase_prev(i,j,c) + sinomegat*cs%sinphase_prev(i,j,c))
480  enddo ; enddo
481  enddo ; endif
482 
483  call cpu_clock_end(id_clock_tides)
484 
485 end subroutine calc_tidal_forcing
486 
487 !> This subroutine deallocates memory associated with the tidal forcing module.
488 subroutine tidal_forcing_end(CS)
489  type(tidal_forcing_cs), pointer :: cs !< The control structure returned by a previous call
490  !! to tidal_forcing_init; it is deallocated here.
491 
492  if (associated(cs%sin_struct)) deallocate(cs%sin_struct)
493  if (associated(cs%cos_struct)) deallocate(cs%cos_struct)
494 
495  if (associated(cs%cosphasesal)) deallocate(cs%cosphasesal)
496  if (associated(cs%sinphasesal)) deallocate(cs%sinphasesal)
497  if (associated(cs%ampsal)) deallocate(cs%ampsal)
498 
499  if (associated(cs%cosphase_prev)) deallocate(cs%cosphase_prev)
500  if (associated(cs%sinphase_prev)) deallocate(cs%sinphase_prev)
501  if (associated(cs%amp_prev)) deallocate(cs%amp_prev)
502 
503  if (associated(cs)) deallocate(cs)
504 
505 end subroutine tidal_forcing_end
506 
507 !> \namespace tidal_forcing
508 !!
509 !! Code by Robert Hallberg, August 2005, based on C-code by Harper
510 !! Simmons, February, 2003, in turn based on code by Brian Arbic.
511 !!
512 !! The main subroutine in this file calculates the total tidal
513 !! contribution to the geopotential, including self-attraction and
514 !! loading terms and the astronomical contributions. All options
515 !! are selected with entries in a file that is parsed at run-time.
516 !! Overall tides are enabled with the run-time parameter 'TIDES=True'.
517 !! Tidal constituents must be individually enabled with lines like
518 !! 'TIDE_M2=True'. This file has default values of amplitude,
519 !! frequency, Love number, and phase at time 0 for the Earth's M2,
520 !! S2, N2, K2, K1, O1, P1, Q1, MF, and MM tidal constituents, but
521 !! the frequency, amplitude and phase ant time 0 for each constituent
522 !! can be changed at run time by setting variables like TIDE_M2_FREQ,
523 !! TIDE_M2_AMP and TIDE_M2_PHASE_T0 (for M2).
524 !!
525 !! In addition, the approach to calculating self-attraction and
526 !! loading is set at run time. The default is to use the scalar
527 !! approximation, with a coefficient TIDE_SAL_SCALAR_VALUE that must
528 !! be set in the run-time file (for global runs, 0.094 is typical).
529 !! Alternately, TIDAL_SAL_FROM_FILE can be set to read the SAL from
530 !! a file containing the results of a previous simulation. To iterate
531 !! the SAL to convergence, USE_PREVIOUS_TIDES may be useful (for
532 !! details, see Arbic et al., 2004, DSR II). With TIDAL_SAL_FROM_FILE
533 !! or USE_PREVIOUS_TIDES,a list of input files must be provided to
534 !! describe each constituent's properties from a previous solution.
535 
536 end module mom_tidal_forcing
mom_time_manager
Wraps the FMS time manager functions.
Definition: MOM_time_manager.F90:2
mom_tidal_forcing::tidal_forcing_init
subroutine, public tidal_forcing_init(Time, G, param_file, CS)
This subroutine allocates space for the static variables used by this module. The metrics may be effe...
Definition: MOM_tidal_forcing.F90:67
mom_tidal_forcing::find_in_files
subroutine find_in_files(filenames, varname, array, G)
This subroutine finds a named variable in a list of files and reads its values into a domain-decompos...
Definition: MOM_tidal_forcing.F90:347
mom_tidal_forcing::max_constituents
integer, parameter max_constituents
The maximum number of tidal constituents that could be used.
Definition: MOM_tidal_forcing.F90:22
mom_file_parser::log_version
An overloaded interface to log version information about modules.
Definition: MOM_file_parser.F90:109
mom_domains::pass_var
Do a halo update on an array.
Definition: MOM_domains.F90:49
mom_file_parser::param_file_type
A structure that can be parsed to read and document run-time parameters.
Definition: MOM_file_parser.F90:54
mom_file_parser::get_param
An overloaded interface to read and log the values of various types of parameters.
Definition: MOM_file_parser.F90:102
mom_io
This module contains I/O framework code.
Definition: MOM_io.F90:2
mom_tidal_forcing
Tidal contributions to geopotential.
Definition: MOM_tidal_forcing.F90:2
mom_tidal_forcing::calc_tidal_forcing
subroutine, public calc_tidal_forcing(Time, eta, eta_tidal, G, CS, deta_tidal_deta, m_to_Z)
This subroutine calculates the geopotential anomalies that drive the tides, including self-attraction...
Definition: MOM_tidal_forcing.F90:400
mom_tidal_forcing::tidal_forcing_cs
The control structure for the MOM_tidal_forcing module.
Definition: MOM_tidal_forcing.F90:26
mom_domains
Describes the decomposed MOM domain and has routines for communications across PEs.
Definition: MOM_domains.F90:2
mom_io::mom_read_data
Read a data field from a file.
Definition: MOM_io.F90:74
mom_cpu_clock
Wraps the MPP cpu clock functions.
Definition: MOM_cpu_clock.F90:2
mom_file_parser
The MOM6 facility to parse input files for runtime parameters.
Definition: MOM_file_parser.F90:2
mom_tidal_forcing::id_clock_tides
integer id_clock_tides
CPU clock for tides.
Definition: MOM_tidal_forcing.F90:57
mom_grid
Provides the ocean grid type.
Definition: MOM_grid.F90:2
mom_io::file_exists
Indicate whether a file exists, perhaps with domain decomposition.
Definition: MOM_io.F90:68
mom_error_handler::mom_error
subroutine, public mom_error(level, message, all_print)
This provides a convenient interface for writing an mpp_error message with run-time filter based on a...
Definition: MOM_error_handler.F90:72
mom_tidal_forcing::tidal_forcing_end
subroutine, public tidal_forcing_end(CS)
This subroutine deallocates memory associated with the tidal forcing module.
Definition: MOM_tidal_forcing.F90:489
mom_error_handler
Routines for error handling and I/O management.
Definition: MOM_error_handler.F90:2
mom_grid::ocean_grid_type
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:26
mom_tidal_forcing::tidal_forcing_sensitivity
subroutine, public tidal_forcing_sensitivity(G, CS, deta_tidal_deta)
This subroutine calculates returns the partial derivative of the local geopotential height with the i...
Definition: MOM_tidal_forcing.F90:379