MOM6
MOM_sponge.F90
Go to the documentation of this file.
1 module mom_sponge
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 
22 !********+*********+*********+*********+*********+*********+*********+**
23 !* *
24 !* By Robert Hallberg, March 1999-June 2000 *
25 !* *
26 !* This program contains the subroutines that implement sponge *
27 !* regions, in which the stratification and water mass properties *
28 !* are damped toward some profiles. There are three externally *
29 !* callable subroutines in this file. *
30 !* *
31 !* initialize_sponge determines the mapping from the model *
32 !* variables into the arrays of damped columns. This remapping is *
33 !* done for efficiency and to conserve memory. Only columns which *
34 !* have positive inverse damping times and which are deeper than a *
35 !* supplied depth are placed in sponges. The inverse damping *
36 !* time is also stored in this subroutine, and memory is allocated *
37 !* for all of the reference profiles which will subsequently be *
38 !* provided through calls to set_up_sponge_field. The first two *
39 !* arguments are a two-dimensional array containing the damping *
40 !* rates, and the interface heights to damp towards. *
41 !* *
42 !* set_up_sponge_field is called to provide a reference profile *
43 !* and the location of the field that will be damped back toward *
44 !* that reference profile. A third argument, the number of layers *
45 !* in the field is also provided, but this should always be nz. *
46 !* *
47 !* Apply_sponge damps all of the fields that have been registered *
48 !* with set_up_sponge_field toward their reference profiles. The *
49 !* four arguments are the thickness to be damped, the amount of time *
50 !* over which the damping occurs, and arrays to which the movement *
51 !* of fluid into a layer from above and below will be added. The *
52 !* effect on momentum of the sponge may be accounted for later using *
53 !* the movement of water recorded in these later arrays. *
54 !* *
55 !* All of the variables operated upon in this file are defined at *
56 !* the thickness points. *
57 !* *
58 !* Macros written all in capital letters are defined in MOM_memory.h. *
59 !* *
60 !* A small fragment of the grid is shown below: *
61 !* *
62 !* j+1 x ^ x ^ x At x: q *
63 !* j+1 > o > o > At ^: v *
64 !* j x ^ x ^ x At >: u *
65 !* j > o > o > At o: h, T, S, Iresttime, ea, eb *
66 !* j-1 x ^ x ^ x *
67 !* i-1 i i+1 At x & ^: *
68 !* i i+1 At > & o: *
69 !* *
70 !* The boundaries always run through q grid points (x). *
71 !* *
72 !********+*********+*********+*********+*********+*********+*********+**
73 
74 use mom_coms, only : sum_across_pes
76 use mom_diag_mediator, only : diag_ctrl
77 use mom_error_handler, only : mom_error, fatal, note, warning, is_root_pe
79 use mom_grid, only : ocean_grid_type
81 use mom_time_manager, only : time_type
83 
84 ! Planned extension: Support for time varying sponge targets.
85 
86 implicit none ; private
87 
88 #include <MOM_memory.h>
89 
92 
93 type :: p3d
94  real, dimension(:,:,:), pointer :: p => null()
95 end type p3d
96 type :: p2d
97  real, dimension(:,:), pointer :: p => null()
98 end type p2d
99 
100 type, public :: sponge_cs ; private
101  logical :: bulkmixedlayer ! If true, a refined bulk mixed layer is used with
102  ! nkml sublayers and nkbl buffer layer.
103  integer :: nz ! The total number of layers.
104  integer :: isc, iec, jsc, jec ! The index ranges of the computational domain.
105  integer :: isd, ied, jsd, jed ! The index ranges of the data domain.
106  integer :: num_col ! The number of sponge points within the
107  ! computational domain.
108  integer :: fldno = 0 ! The number of fields which have already been
109  ! registered by calls to set_up_sponge_field
110  integer, pointer :: col_i(:) => null() ! Arrays containing the i- and j- indicies
111  integer, pointer :: col_j(:) => null() ! of each of the columns being damped.
112  real, pointer :: iresttime_col(:) => null() ! The inverse restoring time of
113  ! each column.
114  real, pointer :: rcv_ml_ref(:) => null() ! The value toward which the mixed layer
115  ! coordinate-density is being damped, in kg m-3.
116  real, pointer :: ref_eta(:,:) => null() ! The value toward which the interface
117  ! heights are being damped.
118  type(p3d) :: var(max_fields_) ! Pointers to the fields that are being damped.
119  type(p2d) :: ref_val(max_fields_) ! The values to which the fields are damped.
120 
121  logical :: do_i_mean_sponge ! If true, apply sponges to the i-mean fields.
122  real, pointer :: iresttime_im(:) => null() ! The inverse restoring time of
123  ! each row for i-mean sponges.
124  real, pointer :: rcv_ml_ref_im(:) => null() ! The value toward which the i-mean
125  ! mixed layer coordinate-density is being damped,
126  ! in kg m-3.
127  real, pointer :: ref_eta_im(:,:) => null() ! The value toward which the i-mean
128  ! interface heights are being damped.
129  type(p2d) :: ref_val_im(max_fields_) ! The values toward which the i-means of
130  ! fields are damped.
131 
132  type(diag_ctrl), pointer :: diag ! A structure that is used to regulate the
133  ! timing of diagnostic output.
134  integer :: id_w_sponge = -1
135 
136 end type sponge_cs
137 
138 contains
139 
140 subroutine initialize_sponge(Iresttime, int_height, G, param_file, CS, &
141  Iresttime_i_mean, int_height_i_mean)
142  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
143  real, dimension(SZI_(G),SZJ_(G)), intent(in) :: Iresttime
144  real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1), intent(in) :: int_height
145  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
146  type(sponge_cs), pointer :: CS
147  real, dimension(SZJ_(G)), optional, intent(in) :: Iresttime_i_mean
148  real, dimension(SZJ_(G),SZK_(G)+1), optional, intent(in) :: int_height_i_mean
149 
150 ! This subroutine determines the number of points which are within
151 ! sponges in this computational domain. Only points that have
152 ! positive values of Iresttime and which mask2dT indicates are ocean
153 ! points are included in the sponges. It also stores the target interface
154 ! heights.
155 
156 ! Arguments: Iresttime - The inverse of the restoring time, in s-1.
157 ! (in) int_height - The interface heights to damp back toward, in m.
158 ! (in) G - The ocean's grid structure.
159 ! (in) param_file - A structure indicating the open file to parse for
160 ! model parameter values.
161 ! (in/out) CS - A pointer that is set to point to the control structure
162 ! for this module
163 ! This include declares and sets the variable "version".
164 #include "version_variable.h"
165  character(len=40) :: mdl = "MOM_sponge" ! This module's name.
166  logical :: use_sponge
167  integer :: i, j, k, col, total_sponge_cols
168 
169  if (associated(cs)) then
170  call mom_error(warning, "initialize_sponge called with an associated "// &
171  "control structure.")
172  return
173  endif
174 
175 ! Set default, read and log parameters
176  call log_version(param_file, mdl, version)
177  call get_param(param_file, mdl, "SPONGE", use_sponge, &
178  "If true, sponges may be applied anywhere in the domain. \n"//&
179  "The exact location and properties of those sponges are \n"//&
180  "specified from MOM_initialization.F90.", default=.false.)
181 
182  if (.not.use_sponge) return
183  allocate(cs)
184 
185  if (present(iresttime_i_mean) .neqv. present(int_height_i_mean)) &
186  call mom_error(fatal, "initialize_sponge: The optional arguments \n"//&
187  "Iresttime_i_mean and int_height_i_mean must both be present \n"//&
188  "if either one is.")
189 
190  cs%do_i_mean_sponge = present(iresttime_i_mean)
191 
192  cs%nz = g%ke
193  cs%isc = g%isc ; cs%iec = g%iec ; cs%jsc = g%jsc ; cs%jec = g%jec
194  cs%isd = g%isd ; cs%ied = g%ied ; cs%jsd = g%jsd ; cs%jed = g%jed
195  ! CS%bulkmixedlayer may be set later via a call to set_up_sponge_ML_density.
196  cs%bulkmixedlayer = .false.
197 
198  cs%num_col = 0 ; cs%fldno = 0
199  do j=g%jsc,g%jec ; do i=g%isc,g%iec
200  if ((iresttime(i,j)>0.0) .and. (g%mask2dT(i,j)>0)) &
201  cs%num_col = cs%num_col + 1
202  enddo ; enddo
203 
204  if (cs%num_col > 0) then
205 
206  allocate(cs%Iresttime_col(cs%num_col)) ; cs%Iresttime_col = 0.0
207  allocate(cs%col_i(cs%num_col)) ; cs%col_i = 0
208  allocate(cs%col_j(cs%num_col)) ; cs%col_j = 0
209 
210  col = 1
211  do j=g%jsc,g%jec ; do i=g%isc,g%iec
212  if ((iresttime(i,j)>0.0) .and. (g%mask2dT(i,j)>0)) then
213  cs%col_i(col) = i ; cs%col_j(col) = j
214  cs%Iresttime_col(col) = iresttime(i,j)
215  col = col +1
216  endif
217  enddo ; enddo
218 
219  allocate(cs%Ref_eta(cs%nz+1,cs%num_col))
220  do col=1,cs%num_col ; do k=1,cs%nz+1
221  cs%Ref_eta(k,col) = int_height(cs%col_i(col),cs%col_j(col),k)
222  enddo ; enddo
223 
224  endif
225 
226  if (cs%do_i_mean_sponge) then
227  allocate(cs%Iresttime_im(g%jsd:g%jed)) ; cs%Iresttime_im(:) = 0.0
228  allocate(cs%Ref_eta_im(g%jsd:g%jed,g%ke+1)) ; cs%Ref_eta_im(:,:) = 0.0
229 
230  do j=g%jsc,g%jec
231  cs%Iresttime_im(j) = iresttime_i_mean(j)
232  enddo
233  do k=1,cs%nz+1 ; do j=g%jsc,g%jec
234  cs%Ref_eta_im(j,k) = int_height_i_mean(j,k)
235  enddo ; enddo
236  endif
237 
238  total_sponge_cols = cs%num_col
239  call sum_across_pes(total_sponge_cols)
240 
241  call log_param(param_file, mdl, "!Total sponge columns", total_sponge_cols, &
242  "The total number of columns where sponges are applied.")
243 
244 end subroutine initialize_sponge
245 
246 subroutine init_sponge_diags(Time, G, diag, CS)
247  type(time_type), target, intent(in) :: Time
248  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
249  type(diag_ctrl), target, intent(inout) :: diag
250  type(sponge_cs), pointer :: CS
251 
252 ! This subroutine sets up diagnostics for the sponges. It is separate
253 ! from initialize_sponge because it requires fields that are not readily
254 ! availble where initialize_sponge is called.
255 
256 ! Arguments: Time - The current model time.
257 ! (in) G - The ocean's grid structure.
258 ! (in) diag - A structure that is used to regulate diagnostic output.
259 ! (in/out) CS - A pointer to the control structure for this module that is
260 ! set by a previous call to initialize_sponge.
261 
262  if (.not.associated(cs)) return
263 
264  cs%diag => diag
265  cs%id_w_sponge = register_diag_field('ocean_model', 'w_sponge', diag%axesTi, &
266  time, 'The diapycnal motion due to the sponges', 'meter second-1')
267 
268 end subroutine init_sponge_diags
269 
270 subroutine set_up_sponge_field(sp_val, f_ptr, G, nlay, CS, sp_val_i_mean)
271  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
272  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: sp_val
273  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), target, intent(in) :: f_ptr
274  integer, intent(in) :: nlay
275  type(sponge_cs), pointer :: CS
276  real, dimension(SZJ_(G),SZK_(G)), optional, intent(in) :: sp_val_i_mean
277 ! This subroutine stores the reference profile for the variable
278 ! whose address is given by f_ptr. nlay is the number of layers in
279 ! this variable.
280 
281 ! Arguments: sp_val - The reference profiles of the quantity being
282 ! registered.
283 ! (in) f_ptr - a pointer to the field which will be damped.
284 ! (in) nlay - the number of layers in this quantity.
285 ! (in/out) CS - A pointer to the control structure for this module that is
286 ! set by a previous call to initialize_sponge.
287 ! (in,opt) sp_val_i_mean - The i-mean reference value for this field with
288 ! i-mean sponges.
289 
290  integer :: j, k, col
291  character(len=256) :: mesg ! String for error messages
292 
293  if (.not.associated(cs)) return
294 
295  cs%fldno = cs%fldno + 1
296 
297  if (cs%fldno > max_fields_) then
298  write(mesg,'("Increase MAX_FIELDS_ to at least ",I3," in MOM_memory.h or decrease &
299  &the number of fields to be damped in the call to &
300  &initialize_sponge." )') cs%fldno
301  call mom_error(fatal,"set_up_sponge_field: "//mesg)
302  endif
303 
304  allocate(cs%Ref_val(cs%fldno)%p(cs%nz,cs%num_col))
305  cs%Ref_val(cs%fldno)%p(:,:) = 0.0
306  do col=1,cs%num_col
307  do k=1,nlay
308  cs%Ref_val(cs%fldno)%p(k,col) = sp_val(cs%col_i(col),cs%col_j(col),k)
309  enddo
310  do k=nlay+1,cs%nz
311  cs%Ref_val(cs%fldno)%p(k,col) = 0.0
312  enddo
313  enddo
314 
315  cs%var(cs%fldno)%p => f_ptr
316 
317  if (nlay/=cs%nz) then
318  write(mesg,'("Danger: Sponge reference fields require nz (",I3,") layers.&
319  & A field with ",I3," layers was passed to set_up_sponge_field.")') &
320  cs%nz, nlay
321  if (is_root_pe()) call mom_error(warning, "set_up_sponge_field: "//mesg)
322  endif
323 
324  if (cs%do_i_mean_sponge) then
325  if (.not.present(sp_val_i_mean)) call mom_error(fatal, &
326  "set_up_sponge_field: sp_val_i_mean must be present with i-mean sponges.")
327 
328  allocate(cs%Ref_val_im(cs%fldno)%p(cs%jsd:cs%jed,cs%nz))
329  cs%Ref_val(cs%fldno)%p(:,:) = 0.0
330  do k=1,cs%nz ; do j=cs%jsc,cs%jec
331  cs%Ref_val_im(cs%fldno)%p(j,k) = sp_val_i_mean(j,k)
332  enddo ; enddo
333  endif
334 
335 end subroutine set_up_sponge_field
336 
337 
338 subroutine set_up_sponge_ml_density(sp_val, G, CS, sp_val_i_mean)
339  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
340  real, dimension(SZI_(G),SZJ_(G)), intent(in) :: sp_val
341  type(sponge_cs), pointer :: CS
342  real, dimension(SZJ_(G)), optional, intent(in) :: sp_val_i_mean
343 ! This subroutine stores the reference value for mixed layer density. It is
344 ! handled differently from other values because it is only used in determining
345 ! which layers can be inflated.
346 
347 ! Arguments: sp_val - The reference values of the mixed layer density.
348 ! (in/out) CS - A pointer to the control structure for this module that is
349 ! set by a previous call to initialize_sponge.
350 
351  integer :: j, col
352  character(len=256) :: mesg ! String for error messages
353 
354  if (.not.associated(cs)) return
355 
356  if (associated(cs%Rcv_ml_ref)) then
357  call mom_error(fatal, "set_up_sponge_ML_density appears to have been "//&
358  "called twice.")
359  endif
360 
361  cs%bulkmixedlayer = .true.
362  allocate(cs%Rcv_ml_ref(cs%num_col)) ; cs%Rcv_ml_ref(:) = 0.0
363  do col=1,cs%num_col
364  cs%Rcv_ml_ref(col) = sp_val(cs%col_i(col),cs%col_j(col))
365  enddo
366 
367  if (cs%do_i_mean_sponge) then
368  if (.not.present(sp_val_i_mean)) call mom_error(fatal, &
369  "set_up_sponge_field: sp_val_i_mean must be present with i-mean sponges.")
370 
371  allocate(cs%Rcv_ml_ref_im(cs%jsd:cs%jed)) ; cs%Rcv_ml_ref_im(:) = 0.0
372  do j=cs%jsc,cs%jec
373  cs%Rcv_ml_ref_im(j) = sp_val_i_mean(j)
374  enddo
375  endif
376 
377 end subroutine set_up_sponge_ml_density
378 
379 subroutine apply_sponge(h, dt, G, GV, ea, eb, CS, Rcv_ml)
380  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure
381  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure
382  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(inout) :: h !< Layer thicknesses, in H (usually m or kg m-2)
383  real, intent(in) :: dt
384  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(out) :: ea
385  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(out) :: eb
386  type(sponge_cs), pointer :: CS
387  real, dimension(SZI_(G),SZJ_(G)), optional, intent(inout) :: Rcv_ml
388 
389 ! This subroutine applies damping to the layers thicknesses, mixed
390 ! layer buoyancy, and a variety of tracers for every column where
391 ! there is damping.
392 
393 ! Arguments: h - Layer thickness, in m.
394 ! (in) dt - The amount of time covered by this call, in s.
395 ! (in) G - The ocean's grid structure.
396 ! (in) GV - The ocean's vertical grid structure.
397 ! (out) ea - an array to which the amount of fluid entrained
398 ! from the layer above during this call will be
399 ! added, in m.
400 ! (out) eb - an array to which the amount of fluid entrained
401 ! from the layer below during this call will be
402 ! added, in m.
403 ! (in) CS - A pointer to the control structure for this module that is
404 ! set by a previous call to initialize_sponge.
405 ! (inout,opt) Rcv_ml - The coordinate density of the mixed layer.
406 
407  real, dimension(SZI_(G), SZJ_(G), SZK_(G)+1) :: &
408  w_int, & ! Water moved upward across an interface within a timestep,
409  ! in m.
410  e_d ! Interface heights that are dilated to have a value of 0
411  ! at the surface, in m.
412  real, dimension(SZI_(G), SZJ_(G)) :: &
413  eta_anom, & ! Anomalies in the interface height, relative to the i-mean
414  ! target value.
415  fld_anom ! Anomalies in a tracer concentration, relative to the
416  ! i-mean target value.
417  real, dimension(SZJ_(G), SZK_(G)+1) :: &
418  eta_mean_anom ! The i-mean interface height anomalies.
419  real, allocatable, dimension(:,:,:) :: &
420  fld_mean_anom ! THe i-mean tracer concentration anomalies.
421  real, dimension(SZI_(G), SZK_(G)+1) :: &
422  h_above, & ! The total thickness above an interface, in m.
423  h_below ! The total thickness below an interface, in m.
424  real, dimension(SZI_(G)) :: &
425  dilate ! A nondimensional factor by which to dilate layers to
426  ! give 0 at the surface.
427 
428  real :: e(szk_(g)+1) ! The interface heights, in m or kg m-2, usually negative.
429  real :: e0 ! The height of the free surface in m.
430  real :: e_str ! A nondimensional amount by which the reference
431  ! profile must be stretched for the free surfaces
432  ! heights in the two profiles to agree.
433  real :: w ! The thickness of water moving upward through an
434  ! interface within 1 timestep, in m.
435  real :: wm ! wm is w if w is negative and 0 otherwise, in m.
436  real :: wb ! w at the interface below a layer, in m.
437  real :: wpb ! wpb is wb if wb is positive and 0 otherwise, m.
438  real :: ea_k, eb_k
439  real :: damp ! The timestep times the local damping coefficient. ND.
440  real :: I1pdamp ! I1pdamp is 1/(1 + damp). Nondimensional.
441  real :: damp_1pdamp ! damp_1pdamp is damp/(1 + damp). Nondimensional.
442  real :: Idt ! 1.0/dt, in s-1.
443  integer :: c, m, nkmb, i, j, k, is, ie, js, je, nz
444  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
445 
446  if (.not.associated(cs)) return
447  if (cs%bulkmixedlayer) nkmb = gv%nk_rho_varies
448  if (cs%bulkmixedlayer .and. (.not.present(rcv_ml))) &
449  call mom_error(fatal, "Rml must be provided to apply_sponge when using "//&
450  "a bulk mixed layer.")
451 
452  if ((cs%id_w_sponge > 0) .or. cs%do_i_mean_sponge) then
453  do k=1,nz+1 ; do j=js,je ; do i=is,ie
454  w_int(i,j,k) = 0.0
455  enddo ; enddo ; enddo
456  endif
457 
458  if (cs%do_i_mean_sponge) then
459  ! Apply forcing to restore the zonal-mean properties to prescribed values.
460 
461  if (cs%bulkmixedlayer) call mom_error(fatal, "apply_sponge is not yet set up to "//&
462  "work properly with i-mean sponges and a bulk mixed layer.")
463 
464  do j=js,je ; do i=is,ie ; e_d(i,j,nz+1) = -g%bathyT(i,j) ; enddo ; enddo
465  do k=nz,1,-1 ; do j=js,je ; do i=is,ie
466  e_d(i,j,k) = e_d(i,j,k+1) + h(i,j,k)
467  enddo ; enddo ; enddo
468  do j=js,je
469  do i=is,ie
470  dilate(i) = g%bathyT(i,j) / (e_d(i,j,1) + g%bathyT(i,j))
471  enddo
472  do k=1,nz+1 ; do i=is,ie
473  e_d(i,j,k) = dilate(i) * (e_d(i,j,k) + g%bathyT(i,j)) - g%bathyT(i,j)
474  enddo ; enddo
475  enddo
476 
477  do k=2,nz
478  do j=js,je ; do i=is,ie
479  eta_anom(i,j) = e_d(i,j,k) - cs%Ref_eta_im(j,k)
480  if (cs%Ref_eta_im(j,k) < -g%bathyT(i,j)) eta_anom(i,j) = 0.0
481  enddo ; enddo
482  call global_i_mean(eta_anom(:,:), eta_mean_anom(:,k), g)
483  enddo
484 
485  if (cs%fldno > 0) allocate(fld_mean_anom(g%isd:g%ied,nz,cs%fldno))
486  do m=1,cs%fldno
487  do j=js,je ; do i=is,ie
488  fld_anom(i,j) = cs%var(m)%p(i,j,k) - cs%Ref_val_im(m)%p(j,k)
489  enddo ; enddo
490  call global_i_mean(fld_anom(:,:), fld_mean_anom(:,k,m), g, h(:,:,k))
491  enddo
492 
493  do j=js,je ; if (cs%Iresttime_im(j) > 0.0) then
494  damp = dt*cs%Iresttime_im(j) ; damp_1pdamp = damp / (1.0 + damp)
495 
496  do i=is,ie
497  h_above(i,1) = 0.0 ; h_below(i,nz+1) = 0.0
498  enddo
499  do k=nz,1,-1 ; do i=is,ie
500  h_below(i,k) = h_below(i,k+1) + max(h(i,j,k)-gv%Angstrom, 0.0)
501  enddo ; enddo
502  do k=2,nz+1 ; do i=is,ie
503  h_above(i,k) = h_above(i,k-1) + max(h(i,j,k-1)-gv%Angstrom, 0.0)
504  enddo ; enddo
505  do k=2,nz
506  ! w is positive for an upward (lightward) flux of mass, resulting
507  ! in the downward movement of an interface.
508  w = damp_1pdamp * eta_mean_anom(j,k)
509  do i=is,ie
510  if (w > 0.0) then
511  w_int(i,j,k) = min(w, h_below(i,k))
512  eb(i,j,k-1) = eb(i,j,k-1) + w_int(i,j,k)
513  else
514  w_int(i,j,k) = max(w, -h_above(i,k))
515  ea(i,j,k) = ea(i,j,k) - w_int(i,j,k)
516  endif
517  enddo
518  enddo
519  do k=1,nz ; do i=is,ie
520  ea_k = max(0.0, -w_int(i,j,k))
521  eb_k = max(0.0, w_int(i,j,k+1))
522  do m=1,cs%fldno
523  cs%var(m)%p(i,j,k) = (h(i,j,k)*cs%var(m)%p(i,j,k) + &
524  cs%Ref_val_im(m)%p(j,k) * (ea_k + eb_k)) / &
525  (h(i,j,k) + (ea_k + eb_k)) - &
526  damp_1pdamp * fld_mean_anom(j,k,m)
527  enddo
528 
529  h(i,j,k) = max(h(i,j,k) + (w_int(i,j,k+1) - w_int(i,j,k)), &
530  min(h(i,j,k), gv%Angstrom))
531  enddo ; enddo
532  endif ; enddo
533 
534  if (cs%fldno > 0) deallocate(fld_mean_anom)
535 
536  endif
537 
538  do c=1,cs%num_col
539 ! c is an index for the next 3 lines but a multiplier for the rest of the loop
540 ! Therefore we use c as per C code and increment the index where necessary.
541  i = cs%col_i(c) ; j = cs%col_j(c)
542  damp = dt*cs%Iresttime_col(c)
543 
544  e(1) = 0.0 ; e0 = 0.0
545  do k=1,nz
546  e(k+1) = e(k) - h(i,j,k)
547  enddo
548  e_str = e(nz+1) / cs%Ref_eta(nz+1,c)
549 
550  if ( cs%bulkmixedlayer ) then
551  i1pdamp = 1.0 / (1.0 + damp)
552  if (associated(cs%Rcv_ml_ref)) &
553  rcv_ml(i,j) = i1pdamp * (rcv_ml(i,j) + cs%Rcv_ml_ref(c)*damp)
554  do k=1,nkmb
555  do m=1,cs%fldno
556  cs%var(m)%p(i,j,k) = i1pdamp * &
557  (cs%var(m)%p(i,j,k) + cs%Ref_val(m)%p(k,c)*damp)
558  enddo
559  enddo
560 
561  wpb = 0.0; wb = 0.0
562  do k=nz,nkmb+1,-1
563  if (gv%Rlay(k) > rcv_ml(i,j)) then
564  w = min((((e(k)-e0) - e_str*cs%Ref_eta(k,c)) * damp), &
565  ((wb + h(i,j,k)) - gv%Angstrom))
566  wm = 0.5*(w-abs(w))
567  do m=1,cs%fldno
568  cs%var(m)%p(i,j,k) = (h(i,j,k)*cs%var(m)%p(i,j,k) + &
569  cs%Ref_val(m)%p(k,c)*(damp*h(i,j,k) + (wpb - wm))) / &
570  (h(i,j,k)*(1.0 + damp) + (wpb - wm))
571  enddo
572  else
573  do m=1,cs%fldno
574  cs%var(m)%p(i,j,k) = i1pdamp * &
575  (cs%var(m)%p(i,j,k) + cs%Ref_val(m)%p(k,c)*damp)
576  enddo
577  w = wb + (h(i,j,k) - gv%Angstrom)
578  wm = 0.5*(w-abs(w))
579  endif
580  eb(i,j,k) = eb(i,j,k) + wpb
581  ea(i,j,k) = ea(i,j,k) - wm
582  h(i,j,k) = h(i,j,k) + (wb - w)
583  wb = w
584  wpb = w - wm
585  enddo
586 
587  if (wb < 0) then
588  do k=nkmb,1,-1
589  w = min((wb + (h(i,j,k) - gv%Angstrom)),0.0)
590  h(i,j,k) = h(i,j,k) + (wb - w)
591  ea(i,j,k) = ea(i,j,k) - w
592  wb = w
593  enddo
594  else
595  w = wb
596  do k=gv%nkml,nkmb
597  eb(i,j,k) = eb(i,j,k) + w
598  enddo
599 
600  k = gv%nkml
601  h(i,j,k) = h(i,j,k) + w
602  do m=1,cs%fldno
603  cs%var(m)%p(i,j,k) = (cs%var(m)%p(i,j,k)*h(i,j,k) + &
604  cs%Ref_val(m)%p(k,c)*w) / (h(i,j,k) + w)
605  enddo
606  endif
607 
608  do k=1,nkmb
609  do m=1,cs%fldno
610  cs%var(m)%p(i,j,k) = i1pdamp * &
611  (cs%var(m)%p(i,j,k) + cs%Ref_val(m)%p(gv%nkml,c)*damp)
612  enddo
613  enddo
614 
615  else ! not BULKMIXEDLAYER
616 
617  wpb = 0.0
618  wb = 0.0
619  do k=nz,1,-1
620  w = min((((e(k)-e0) - e_str*cs%Ref_eta(k,c)) * damp), &
621  ((wb + h(i,j,k)) - gv%Angstrom))
622  wm = 0.5*(w - abs(w))
623  do m=1,cs%fldno
624  cs%var(m)%p(i,j,k) = (h(i,j,k)*cs%var(m)%p(i,j,k) + &
625  cs%Ref_val(m)%p(k,c) * (damp*h(i,j,k) + (wpb - wm))) / &
626  (h(i,j,k)*(1.0 + damp) + (wpb - wm))
627  enddo
628  eb(i,j,k) = eb(i,j,k) + wpb
629  ea(i,j,k) = ea(i,j,k) - wm
630  h(i,j,k) = h(i,j,k) + (wb - w)
631  wb = w
632  wpb = w - wm
633  enddo
634 
635  endif ! end BULKMIXEDLAYER
636  enddo ! end of c loop
637 
638  if (associated(cs%diag)) then ; if (query_averaging_enabled(cs%diag)) then
639  idt = 1.0 / dt
640  if (cs%id_w_sponge > 0) call post_data(cs%id_w_sponge, idt*w_int, cs%diag)
641  endif ; endif
642 
643 end subroutine apply_sponge
644 
645 subroutine sponge_end(CS)
646  type(sponge_cs), pointer :: CS
647 ! (in) CS - A pointer to the control structure for this module that is
648 ! set by a previous call to initialize_sponge.
649  integer :: m
650 
651  if (.not.associated(cs)) return
652 
653  if (associated(cs%col_i)) deallocate(cs%col_i)
654  if (associated(cs%col_j)) deallocate(cs%col_j)
655 
656  if (associated(cs%Iresttime_col)) deallocate(cs%Iresttime_col)
657  if (associated(cs%Rcv_ml_ref)) deallocate(cs%Rcv_ml_ref)
658  if (associated(cs%Ref_eta)) deallocate(cs%Ref_eta)
659 
660  if (associated(cs%Iresttime_im)) deallocate(cs%Iresttime_im)
661  if (associated(cs%Rcv_ml_ref_im)) deallocate(cs%Rcv_ml_ref_im)
662  if (associated(cs%Ref_eta_im)) deallocate(cs%Ref_eta_im)
663 
664  do m=1,cs%fldno
665  if (associated(cs%Ref_val(cs%fldno)%p)) deallocate(cs%Ref_val(cs%fldno)%p)
666  if (associated(cs%Ref_val_im(cs%fldno)%p)) &
667  deallocate(cs%Ref_val_im(cs%fldno)%p)
668  enddo
669 
670  deallocate(cs)
671 
672 end subroutine sponge_end
673 
674 end module mom_sponge
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:19
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Provides the ocean grid type.
Definition: MOM_grid.F90:2
subroutine, public sponge_end(CS)
Definition: MOM_sponge.F90:646
logical function, public query_averaging_enabled(diag_cs, time_int, time_end)
subroutine, public init_sponge_diags(Time, G, diag, CS)
Definition: MOM_sponge.F90:247
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
subroutine, public global_i_mean(array, i_mean, G, mask)
logical function, public is_root_pe()
subroutine, public apply_sponge(h, dt, G, GV, ea, eb, CS, Rcv_ml)
Definition: MOM_sponge.F90:380
subroutine, public set_up_sponge_ml_density(sp_val, G, CS, sp_val_i_mean)
Definition: MOM_sponge.F90:339
integer function, public register_diag_field(module_name, field_name, axes, init_time, long_name, units, missing_value, range, mask_variant, standard_name, verbose, do_not_log, err_msg, interp_method, tile_count, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name, cell_methods, x_cell_method, y_cell_method, v_cell_method, conversion, v_extensive)
Returns the "diag_mediator" handle for a group (native, CMOR, z-coord, ...) of diagnostics derived fr...
subroutine, public mom_error(level, message, all_print)