MOM6
Phillips_initialization.F90
Go to the documentation of this file.
2 !***********************************************************************
3 !* GNU General Public License *
4 !* This file is a part of MOM. *
5 !* *
6 !* MOM is free software; you can redistribute it and/or modify it and *
7 !* are expected to follow the terms of the GNU General Public License *
8 !* as published by the Free Software Foundation; either version 2 of *
9 !* the License, or (at your option) any later version. *
10 !* *
11 !* MOM is distributed in the hope that it will be useful, but WITHOUT *
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
13 !* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public *
14 !* License for more details. *
15 !* *
16 !* For the full text of the GNU General Public License, *
17 !* write to: Free Software Foundation, Inc., *
18 !* 675 Mass Ave, Cambridge, MA 02139, USA. *
19 !* or see: http://www.gnu.org/licenses/gpl.html *
20 !***********************************************************************
21 
25 use mom_get_input, only : directories
26 use mom_grid, only : ocean_grid_type
27 use mom_io, only : close_file, fieldtype, file_exists
28 use mom_io, only : open_file, read_data, read_axis_data, single_file
29 use mom_io, only : write_field, slasher
35 
36 implicit none ; private
37 
38 #include <MOM_memory.h>
39 
44 
45 ! This include declares and sets the variable "version".
46 #include "version_variable.h"
47 
48 contains
49 
50 !> Initialize thickness field.
51 subroutine phillips_initialize_thickness(h, G, GV, param_file, just_read_params)
52  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
53  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
54  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
55  intent(out) :: h !< The thickness that is being initialized, in m.
56  type(param_file_type), intent(in) :: param_file !< A structure indicating the open file
57  !! to parse for model parameter values.
58  logical, optional, intent(in) :: just_read_params !< If present and true, this call will
59  !! only read parameters without changing h.
60 
61  real :: eta0(szk_(g)+1) ! The 1-d nominal positions of the interfaces.
62  real :: eta_im(szj_(g),szk_(g)+1) ! A temporary array for zonal-mean eta, m.
63  real :: eta1D(szk_(g)+1) ! Interface height relative to the sea surface
64  ! positive upward, in m.
65  real :: damp_rate, jet_width, jet_height, y_2
66  real :: half_strat, half_depth
67  logical :: just_read ! If true, just read parameters but set nothing.
68  character(len=40) :: mdl = "Phillips_initialize_thickness" ! This subroutine's name.
69  integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed, nz
70 
71  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
72  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
73 
74  eta_im(:,:) = 0.0
75 
76  just_read = .false. ; if (present(just_read_params)) just_read = just_read_params
77 
78  if (.not.just_read) call log_version(param_file, mdl, version)
79  call get_param(param_file, mdl, "HALF_STRAT_DEPTH", half_strat, &
80  "The maximum depth of the ocean.", units="nondim", &
81  default = 0.5, do_not_log=just_read)
82  call get_param(param_file, mdl, "JET_WIDTH", jet_width, &
83  "The width of the zonal-mean jet.", units="km", &
84  fail_if_missing=.not.just_read, do_not_log=just_read)
85  call get_param(param_file, mdl, "JET_HEIGHT", jet_height, &
86  "The interface height scale associated with the \n"//&
87  "zonal-mean jet.", units="m", &
88  fail_if_missing=.not.just_read, do_not_log=just_read)
89 
90  if (just_read) return ! All run-time parameters have been read, so return.
91 
92  half_depth = g%max_depth*half_strat
93  eta0(1) = 0.0 ; eta0(nz+1) = -g%max_depth
94  do k=2,1+nz/2 ; eta0(k) = -half_depth*(2.0*(k-1)/real(nz)) ; enddo
95  do k=2+nz/2,nz+1
96  eta0(k) = -g%max_depth - 2.0*(g%max_depth-half_depth) * ((k-(nz+1))/real(nz))
97  enddo
98 
99  do j=js,je
100  eta_im(j,1) = 0.0 ; eta_im(j,nz+1) = -g%max_depth
101  enddo
102  do k=2,nz ; do j=js,je
103  y_2 = g%geoLatT(is,j) - g%south_lat - 0.5*g%len_lat
104  eta_im(j,k) = eta0(k) + &
105  jet_height * tanh(y_2 / jet_width)
106 ! jet_height * atan(y_2 / jet_width)
107  if (eta_im(j,k) > 0.0) eta_im(j,k) = 0.0
108  if (eta_im(j,k) < -g%max_depth) eta_im(j,k) = -g%max_depth
109  enddo ; enddo
110 
111  do j=js,je ; do i=is,ie
112 ! This sets the initial thickness (in m) of the layers. The !
113 ! thicknesses are set to insure that: 1. each layer is at least an !
114 ! Angstrom thick, and 2. the interfaces are where they should be !
115 ! based on the resting depths and interface height perturbations, !
116 ! as long at this doesn't interfere with 1. !
117  eta1d(nz+1) = -1.0*g%bathyT(i,j)
118  do k=nz,1,-1
119  eta1d(k) = eta_im(j,k)
120  if (eta1d(k) < (eta1d(k+1) + gv%Angstrom_z)) then
121  eta1d(k) = eta1d(k+1) + gv%Angstrom_z
122  h(i,j,k) = gv%Angstrom_z
123  else
124  h(i,j,k) = eta1d(k) - eta1d(k+1)
125  endif
126  enddo
127  enddo ; enddo
128 
129 end subroutine phillips_initialize_thickness
130 
131 !> Initialize velocity fields.
132 subroutine phillips_initialize_velocity(u, v, G, GV, param_file, just_read_params)
133  type(ocean_grid_type), intent(in) :: G !< Grid structure
134  type(verticalgrid_type), intent(in) :: GV !< Vertical grid structure
135  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
136  intent(out) :: u !< i-component of velocity [m/s]
137  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
138  intent(out) :: v !< j-component of velocity [m/s]
139  type(param_file_type), intent(in) :: param_file !< A structure indicating the open file to
140  !! parse for modelparameter values.
141  logical, optional, intent(in) :: just_read_params !< If present and true, this call will
142  !! only read parameters without changing h.
143 
144  real :: damp_rate, jet_width, jet_height, x_2, y_2
145  real :: velocity_amplitude, pi
146  integer :: i, j, k, is, ie, js, je, nz, m
147  logical :: just_read ! If true, just read parameters but set nothing.
148  character(len=40) :: mdl = "Phillips_initialize_velocity" ! This subroutine's name.
149  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
150 
151  just_read = .false. ; if (present(just_read_params)) just_read = just_read_params
152 
153  if (.not.just_read) call log_version(param_file, mdl, version)
154  call get_param(param_file, mdl, "VELOCITY_IC_PERTURB_AMP", velocity_amplitude, &
155  "The magnitude of the initial velocity perturbation.", &
156  units="m s-1", default=0.001, do_not_log=just_read)
157  call get_param(param_file, mdl, "JET_WIDTH", jet_width, &
158  "The width of the zonal-mean jet.", units="km", &
159  fail_if_missing=.not.just_read, do_not_log=just_read)
160  call get_param(param_file, mdl, "JET_HEIGHT", jet_height, &
161  "The interface height scale associated with the \n"//&
162  "zonal-mean jet.", units="m", &
163  fail_if_missing=.not.just_read, do_not_log=just_read)
164 
165  if (just_read) return ! All run-time parameters have been read, so return.
166 
167  u(:,:,:) = 0.0
168  v(:,:,:) = 0.0
169 
170  pi = 4.0*atan(1.0)
171 
172  ! Use thermal wind shear to give a geostrophically balanced flow.
173  do k=nz-1,1 ; do j=js,je ; do i=is-1,ie
174  y_2 = g%geoLatCu(i,j) - g%south_lat - 0.5*g%len_lat
175 ! This uses d/d y_2 atan(y_2 / jet_width)
176 ! u(I,j,k) = u(I,j,k+1) + (1e-3 * jet_height / &
177 ! (jet_width * (1.0 + (y_2 / jet_width)**2))) * &
178 ! (2.0 * GV%g_prime(K+1) / (G%CoriolisBu(I,J) + G%CoriolisBu(I,J-1)))
179 ! This uses d/d y_2 tanh(y_2 / jet_width)
180  u(i,j,k) = u(i,j,k+1) + (1e-3 * (jet_height / jet_width) * &
181  (sech(y_2 / jet_width))**2 ) * &
182  (2.0 * gv%g_prime(k+1) / (g%CoriolisBu(i,j) + g%CoriolisBu(i,j-1)))
183  enddo ; enddo ; enddo
184 
185  do k=1,nz ; do j=js,je ; do i=is-1,ie
186  y_2 = (g%geoLatCu(i,j) - g%south_lat - 0.5*g%len_lat) / g%len_lat
187  x_2 = (g%geoLonCu(i,j) - g%west_lon - 0.5*g%len_lon) / g%len_lon
188  if (g%geoLonCu(i,j) == g%west_lon) then
189  ! This modification is required so that the perturbations are identical for
190  ! symmetric and non-symmetric memory. It is exactly equivalent to
191  ! taking the longitude at the eastern edge of the domain, so that x_2 ~= 0.5.
192  x_2 = ((g%west_lon + g%len_lon*REAL(g%ieg-(g%isg-1))/REAL(g%domain%niglobal)) - &
193  G%west_lon - 0.5*G%len_lon) / g%len_lon
194  endif
195  u(i,j,k) = u(i,j,k) + velocity_amplitude * ((real(k)-0.5)/real(nz)) * &
196  (0.5 - abs(2.0*x_2) + 0.1*abs(cos(10.0*pi*x_2)) - abs(sin(5.0*pi*y_2)))
197  do m=1,10
198  u(i,j,k) = u(i,j,k) + 0.2*velocity_amplitude * ((real(k)-0.5)/real(nz)) * &
199  cos(2.0*m*pi*x_2 + 2*m) * cos(6.0*pi*y_2)
200  enddo
201  enddo ; enddo ; enddo
202 
203 end subroutine phillips_initialize_velocity
204 
205 !> Sets up the the inverse restoration time (Idamp), and
206 ! the values towards which the interface heights and an arbitrary
207 ! number of tracers should be restored within each sponge.
208 subroutine phillips_initialize_sponges(G, use_temperature, tv, param_file, CSp, h)
209  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
210  logical, intent(in) :: use_temperature !< Switch for temperature.
211  type(thermo_var_ptrs), intent(in) :: tv !< A structure containing pointers
212  !! to any available thermodynamic
213  !! fields, potential temperature and
214  !! salinity or mixed layer density.
215  !! Absent fields have NULL ptrs.
216  type(param_file_type), intent(in) :: param_file !< A structure indicating the
217  !! open file to parse for model
218  !! parameter values.
219  type(sponge_cs), pointer :: CSp !< A pointer that is set to point to
220  !! the control structure for the
221  !! sponge module.
222  real, intent(in), dimension(SZI_(G),SZJ_(G), SZK_(G)) :: h !< Thickness field.
223 
224  real :: eta0(szk_(g)+1) ! The 1-d nominal positions of the interfaces.
225  real :: eta(szi_(g),szj_(g),szk_(g)+1) ! A temporary array for eta, m.
226  real :: temp(szi_(g),szj_(g),szk_(g)) ! A temporary array for other variables. !
227  real :: Idamp(szi_(g),szj_(g)) ! The inverse damping rate, in s-1.
228  real :: eta_im(szj_(g),szk_(g)+1) ! A temporary array for zonal-mean eta, m.
229  real :: Idamp_im(szj_(g)) ! The inverse zonal-mean damping rate, in s-1.
230  real :: damp_rate, jet_width, jet_height, y_2
231  real :: half_strat, half_depth
232  character(len=40) :: mdl = "Phillips_initialize_sponges" ! This subroutine's name.
233 
234  integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed, nz
235  logical, save :: first_call = .true.
236 
237  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
238  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
239 
240  eta(:,:,:) = 0.0 ; temp(:,:,:) = 0.0 ; idamp(:,:) = 0.0
241  eta_im(:,:) = 0.0 ; idamp_im(:) = 0.0
242 
243  if (first_call) call log_version(param_file, mdl, version)
244  first_call = .false.
245  call get_param(param_file, mdl, "HALF_STRAT_DEPTH", half_strat, &
246  "The maximum depth of the ocean.", units="nondim", &
247  default = 0.5)
248  call get_param(param_file, mdl, "SPONGE_RATE", damp_rate, &
249  "The rate at which the zonal-mean sponges damp.", units="s-1", &
250  default = 1.0/(10.0*86400.0))
251 
252  call get_param(param_file, mdl, "JET_WIDTH", jet_width, &
253  "The width of the zonal-mean jet.", units="km", &
254  fail_if_missing=.true.)
255  call get_param(param_file, mdl, "JET_HEIGHT", jet_height, &
256  "The interface height scale associated with the \n"//&
257  "zonal-mean jet.", units="m", &
258  fail_if_missing=.true.)
259 
260  half_depth = g%max_depth*half_strat
261  eta0(1) = 0.0 ; eta0(nz+1) = -g%max_depth
262  do k=2,1+nz/2 ; eta0(k) = -half_depth*(2.0*(k-1)/real(nz)) ; enddo
263  do k=2+nz/2,nz+1
264  eta0(k) = -g%max_depth - 2.0*(g%max_depth-half_depth) * ((k-(nz+1))/real(nz))
265  enddo
266 
267  do j=js,je
268  idamp_im(j) = damp_rate
269  eta_im(j,1) = 0.0 ; eta_im(j,nz+1) = -g%max_depth
270  enddo
271  do k=2,nz ; do j=js,je
272  y_2 = g%geoLatT(is,j) - g%south_lat - 0.5*g%len_lat
273  eta_im(j,k) = eta0(k) + &
274  jet_height * tanh(y_2 / jet_width)
275 ! jet_height * atan(y_2 / jet_width)
276  if (eta_im(j,k) > 0.0) eta_im(j,k) = 0.0
277  if (eta_im(j,k) < -g%max_depth) eta_im(j,k) = -g%max_depth
278  enddo ; enddo
279 
280  call initialize_sponge(idamp, eta, g, param_file, csp, idamp_im, eta_im)
281 
282 end subroutine phillips_initialize_sponges
283 
284 !> sech calculates the hyperbolic secant.
285 function sech(x)
286  real, intent(in) :: x !< Input value.
287  real :: sech !< Result.
288 
289  ! This is here to prevent overflows or underflows.
290  if (abs(x) > 228.) then
291  sech = 0.0
292  else
293  sech = 2.0 / (exp(x) + exp(-x))
294  endif
295 end function sech
296 
297 !> Initialize topography.
298 subroutine phillips_initialize_topography(D, G, param_file, max_depth)
299  type(dyn_horgrid_type), intent(in) :: G !< The dynamic horizontal grid type
300  real, dimension(G%isd:G%ied,G%jsd:G%jed), &
301  intent(out) :: D !< Ocean bottom depth in m
302  type(param_file_type), intent(in) :: param_file !< Parameter file structure
303  real, intent(in) :: max_depth !< Maximum depth of model in m
304 
305  real :: PI, Htop, Wtop, Ltop, offset, dist, &
306  x1, x2, x3, x4, y1, y2
307  integer :: i,j,is,ie,js,je
308  character(len=40) :: mdl = "Phillips_initialize_topography" ! This subroutine's name.
309 
310  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
311 
312  pi = 4.0*atan(1.0)
313 
314  call get_param(param_file, mdl, "PHILLIPS_HTOP", htop, &
315  "The maximum height of the topography.", units="m", &
316  fail_if_missing=.true.)
317 ! Htop=0.375*G%max_depth ! max height of topog. above max_depth
318  wtop=0.5*g%len_lat ! meridional width of drake and mount
319  ltop=0.25*g%len_lon ! zonal width of topographic features
320  offset=0.1*g%len_lat ! meridional offset from center
321  dist=0.333*g%len_lon ! distance between drake and mount
322  ! should be longer than Ltop/2
323 
324  y1=g%south_lat+0.5*g%len_lat+offset-0.5*wtop; y2=y1+wtop
325  x1=g%west_lon+0.1*g%len_lon; x2=x1+ltop; x3=x1+dist; x4=x3+3.0/2.0*ltop
326 
327  do i=is,ie ; do j=js,je
328  d(i,j)=0.0
329  if (g%geoLonT(i,j)>x1 .and. g%geoLonT(i,j)<x2) then
330  d(i,j) = htop*sin(pi*(g%geoLonT(i,j)-x1)/(x2-x1))**2
331  if (g%geoLatT(i,j)>y1 .and. g%geoLatT(i,j)<y2) then
332  d(i,j)=d(i,j)*(1-sin(pi*(g%geoLatT(i,j)-y1)/(y2-y1))**2)
333  end if
334  else if (g%geoLonT(i,j)>x3 .and. g%geoLonT(i,j)<x4 .and. &
335  g%geoLatT(i,j)>y1 .and. g%geoLatT(i,j)<y2) then
336  d(i,j) = 2.0/3.0*htop*sin(pi*(g%geoLonT(i,j)-x3)/(x4-x3))**2 &
337  *sin(pi*(g%geoLatT(i,j)-y1)/(y2-y1))**2
338  end if
339  d(i,j)=max_depth-d(i,j)
340  enddo; enddo
341 
342 end subroutine phillips_initialize_topography
343 
344 !> \namespace phillips_initialization
345 !!
346 !! By Robert Hallberg, April 1994 - June 2002 *
347 !! *
348 !! This subroutine initializes the fields for the simulations. *
349 !! The one argument passed to initialize, Time, is set to the *
350 !! current time of the simulation. The fields which are initialized *
351 !! here are: *
352 !! u - Zonal velocity in m s-1. *
353 !! v - Meridional velocity in m s-1. *
354 !! h - Layer thickness in m. (Must be positive.) *
355 !! D - Basin depth in m. (Must be positive.) *
356 !! f - The Coriolis parameter, in s-1. *
357 !! g - The reduced gravity at each interface, in m s-2. *
358 !! Rlay - Layer potential density (coordinate variable) in kg m-3. *
359 !! If ENABLE_THERMODYNAMICS is defined: *
360 !! T - Temperature in C. *
361 !! S - Salinity in psu. *
362 !! If SPONGE is defined: *
363 !! A series of subroutine calls are made to set up the damping *
364 !! rates and reference profiles for all variables that are damped *
365 !! in the sponge. *
366 !! Any user provided tracer code is also first linked through this *
367 !! subroutine. *
368 !! *
369 !! Forcing-related fields (taux, tauy, buoy, ustar, etc.) are set *
370 !! in MOM_surface_forcing.F90. *
371 !! *
372 !! These variables are all set in the set of subroutines (in this *
373 !! file) Phillips_initialize_thickness, Phillips_initialize_velocity, *
374 !! Phillips_initialize_topography and Phillips_initialize_sponges *
375 !! that seet up fields that are specific to the Phillips instability *
376 !! test case. *
377 !! *
378 !! Macros written all in capital letters are defined in MOM_memory.h. *
379 !! *
380 !! A small fragment of the grid is shown below: *
381 !! *
382 !! j+1 x ^ x ^ x At x: q, f *
383 !! j+1 > o > o > At ^: v, tauy *
384 !! j x ^ x ^ x At >: u, taux *
385 !! j > o > o > At o: h, D, buoy, tr, T, S, ustar *
386 !! j-1 x ^ x ^ x *
387 !! i-1 i i+1 At x & ^: *
388 !! i i+1 At > & o: *
389 !! *
390 !! The boundaries always run through q grid points (x). *
391 end module phillips_initialization
subroutine, public read_axis_data(filename, axis_name, var)
Definition: MOM_io.F90:424
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:19
Calculates density of sea water from T, S and P.
Definition: MOM_EOS.F90:45
Provides the ocean grid type.
Definition: MOM_grid.F90:2
By Robert Hallberg, April 1994 - June 2002 *This subroutine initializes the fields for the simulation...
This module contains I/O framework code.
Definition: MOM_io.F90:2
subroutine, public phillips_initialize_sponges(G, use_temperature, tv, param_file, CSp, h)
Sets up the the inverse restoration time (Idamp), and.
subroutine, public phillips_initialize_velocity(u, v, G, GV, param_file, just_read_params)
Initialize velocity fields.
subroutine, public phillips_initialize_thickness(h, G, GV, param_file, just_read_params)
Initialize thickness field.
This module contains the tracer_registry_type and the subroutines that handle registration of tracers...
subroutine, public calculate_density_derivs(T, S, pressure, drho_dT, drho_dS, start, npts, EOS)
Calls the appropriate subroutine to calculate density derivatives for 1-D array inputs.
Definition: MOM_EOS.F90:214
subroutine, public initialize_sponge(Iresttime, int_height, G, param_file, CS, Iresttime_i_mean, int_height_i_mean)
Definition: MOM_sponge.F90:142
subroutine, public set_up_sponge_field(sp_val, f_ptr, G, nlay, CS, sp_val_i_mean)
Definition: MOM_sponge.F90:271
Type to carry basic tracer information.
logical function, public is_root_pe()
subroutine, public mom_mesg(message, verb, all_print)
Provides subroutines for quantities specific to the equation of state.
Definition: MOM_EOS.F90:2
real function sech(x)
sech calculates the hyperbolic secant.
The thermo_var_ptrs structure contains pointers to an assortment of thermodynamic fields that may be ...
subroutine, public phillips_initialize_topography(D, G, param_file, max_depth)
Initialize topography.
subroutine, public mom_error(level, message, all_print)
A control structure for the equation of state.
Definition: MOM_EOS.F90:55