MOM6
coord_rho Module Reference

Detailed Description

Regrid columns for the continuous isopycnal (rho) coordinate.

Data Types

type  rho_cs
 Control structure containing required parameters for the rho coordinate. More...
 

Functions/Subroutines

subroutine, public init_coord_rho (CS, nk, ref_pressure, target_density, interp_CS)
 Initialise a rho_CS with pointers to parameters. More...
 
subroutine, public end_coord_rho (CS)
 This subroutine deallocates memory in the control structure for the coord_rho module. More...
 
subroutine, public set_rho_params (CS, min_thickness, integrate_downward_for_e, interp_CS)
 This subroutine can be used to set the parameters for the coord_rho module. More...
 
subroutine, public build_rho_column (CS, nz, depth, h, T, S, eqn_of_state, z_interface, h_neglect, h_neglect_edge)
 Build a rho coordinate column. More...
 
subroutine build_rho_column_iteratively (CS, remapCS, nz, depth, h, T, S, eqn_of_state, zInterface, h_neglect, h_neglect_edge)
 Iteratively build a rho coordinate column. More...
 
subroutine copy_finite_thicknesses (nk, h_in, threshold, nout, h_out, mapping)
 Copy column thicknesses with vanished layers removed. More...
 
subroutine, public old_inflate_layers_1d (min_thickness, nk, h)
 Inflate vanished layers to finite (nonzero) width. More...
 

Variables

integer, parameter nb_regridding_iterations = 1
 Maximum number of regridding iterations.
 
real, parameter deviation_tolerance = 1e-10
 Deviation tolerance between succesive grids in regridding iterations.
 

Function/Subroutine Documentation

◆ build_rho_column()

subroutine, public coord_rho::build_rho_column ( type(rho_cs), intent(in)  CS,
integer, intent(in)  nz,
real, intent(in)  depth,
real, dimension(nz), intent(in)  h,
real, dimension(nz), intent(in)  T,
real, dimension(nz), intent(in)  S,
type(eos_type), pointer  eqn_of_state,
real, dimension(cs%nk+1), intent(inout)  z_interface,
real, intent(in), optional  h_neglect,
real, intent(in), optional  h_neglect_edge 
)

Build a rho coordinate column.

  1. Density profiles are calculated on the source grid.
  2. Positions of target densities (for interfaces) are found by interpolation.
    Parameters
    [in]cscoord_rho control structure
    [in]nzNumber of levels on source grid (i.e. length of h, T, S)
    [in]depthDepth of ocean bottom (positive in m)
    [in]hLayer thicknesses [H ~> m or kg m-2]
    [in]tT for source column
    [in]sS for source column
    eqn_of_stateEquation of state structure
    [in,out]z_interfaceAbsolute positions of interfaces
    [in]h_neglectA negligibly small width for the purpose of cell reconstructions in the same units as h0.
    [in]h_neglect_edgeA negligibly small width for the purpose of edge value calculations in the same units as h0.

Definition at line 96 of file coord_rho.F90.

96  type(rho_CS), intent(in) :: CS !< coord_rho control structure
97  integer, intent(in) :: nz !< Number of levels on source grid (i.e. length of h, T, S)
98  real, intent(in) :: depth !< Depth of ocean bottom (positive in m)
99  real, dimension(nz), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
100  real, dimension(nz), intent(in) :: T !< T for source column
101  real, dimension(nz), intent(in) :: S !< S for source column
102  type(EOS_type), pointer :: eqn_of_state !< Equation of state structure
103  real, dimension(CS%nk+1), &
104  intent(inout) :: z_interface !< Absolute positions of interfaces
105  real, optional, intent(in) :: h_neglect !< A negligibly small width for the
106  !! purpose of cell reconstructions
107  !! in the same units as h0.
108  real, optional, intent(in) :: h_neglect_edge !< A negligibly small width
109  !! for the purpose of edge value calculations
110  !! in the same units as h0.
111  ! Local variables
112  integer :: k, count_nonzero_layers
113  integer, dimension(nz) :: mapping
114  real, dimension(nz) :: p, densities, h_nv
115  real, dimension(nz+1) :: xTmp
116  real, dimension(CS%nk) :: h_new ! New thicknesses
117  real, dimension(CS%nk+1) :: x1
118 
119  ! Construct source column with vanished layers removed (stored in h_nv)
120  call copy_finite_thicknesses(nz, h, cs%min_thickness, count_nonzero_layers, h_nv, mapping)
121 
122  if (count_nonzero_layers > 1) then
123  xtmp(1) = 0.0
124  do k = 1,count_nonzero_layers
125  xtmp(k+1) = xtmp(k) + h_nv(k)
126  enddo
127 
128  ! Compute densities on source column
129  p(:) = cs%ref_pressure
130  call calculate_density(t, s, p, densities, 1, nz, eqn_of_state)
131  do k = 1,count_nonzero_layers
132  densities(k) = densities(mapping(k))
133  enddo
134 
135  ! Based on source column density profile, interpolate to generate a new grid
136  call build_and_interpolate_grid(cs%interp_CS, densities, count_nonzero_layers, &
137  h_nv, xtmp, cs%target_density, cs%nk, h_new, &
138  x1, h_neglect, h_neglect_edge)
139 
140  ! Inflate vanished layers
141  call old_inflate_layers_1d(cs%min_thickness, cs%nk, h_new)
142 
143  ! Comment: The following adjustment of h_new, and re-calculation of h_new via x1 needs to be removed
144  x1(1) = 0.0 ; do k = 1,cs%nk ; x1(k+1) = x1(k) + h_new(k) ; enddo
145  do k = 1,cs%nk
146  h_new(k) = x1(k+1) - x1(k)
147  enddo
148 
149  else ! count_nonzero_layers <= 1
150  if (nz == cs%nk) then
151  h_new(:) = h(:) ! This keeps old behavior
152  else
153  h_new(:) = 0.
154  h_new(1) = h(1)
155  endif
156  endif
157 
158  ! Return interface positions
159  if (cs%integrate_downward_for_e) then
160  ! Remapping is defined integrating from zero
161  z_interface(1) = 0.
162  do k = 1,cs%nk
163  z_interface(k+1) = z_interface(k) - h_new(k)
164  enddo
165  else
166  ! The rest of the model defines grids integrating up from the bottom
167  z_interface(cs%nk+1) = -depth
168  do k = cs%nk,1,-1
169  z_interface(k) = z_interface(k+1) + h_new(k)
170  enddo
171  endif
172 

◆ build_rho_column_iteratively()

subroutine coord_rho::build_rho_column_iteratively ( type(rho_cs), intent(in)  CS,
type(remapping_cs), intent(in)  remapCS,
integer, intent(in)  nz,
real, intent(in)  depth,
real, dimension(nz), intent(in)  h,
real, dimension(nz), intent(in)  T,
real, dimension(nz), intent(in)  S,
type(eos_type), pointer  eqn_of_state,
real, dimension(nz+1), intent(inout)  zInterface,
real, intent(in), optional  h_neglect,
real, intent(in), optional  h_neglect_edge 
)
private

Iteratively build a rho coordinate column.

The algorithm operates as follows within each column:

  1. Given T & S within each layer, the layer densities are computed.
  2. Based on these layer densities, a global density profile is reconstructed (this profile is monotonically increasing and may be discontinuous)
  3. The new grid interfaces are determined based on the target interface densities.
  4. T & S are remapped onto the new grid.
  5. Return to step 1 until convergence or until the maximum number of iterations is reached, whichever comes first.
    Parameters
    [in]csRegridding control structure
    [in]remapcsRemapping parameters and options
    [in]nzNumber of levels
    [in]depthDepth of ocean bottom [Z ~> m]
    [in]hLayer thicknesses in Z coordinates [Z ~> m]
    [in]tT for column [degC]
    [in]sS for column [ppt]
    eqn_of_stateEquation of state structure
    [in,out]zinterfaceAbsolute positions of interfaces
    [in]h_neglectA negligibly small width for the purpose of cell reconstructions in the same units as h [Z ~> m]
    [in]h_neglect_edgeA negligibly small width for the purpose of edge value calculations in the same units as h [Z ~> m]

Definition at line 189 of file coord_rho.F90.

189  type(rho_CS), intent(in) :: CS !< Regridding control structure
190  type(remapping_CS), intent(in) :: remapCS !< Remapping parameters and options
191  integer, intent(in) :: nz !< Number of levels
192  real, intent(in) :: depth !< Depth of ocean bottom [Z ~> m]
193  real, dimension(nz), intent(in) :: h !< Layer thicknesses in Z coordinates [Z ~> m]
194  real, dimension(nz), intent(in) :: T !< T for column [degC]
195  real, dimension(nz), intent(in) :: S !< S for column [ppt]
196  type(EOS_type), pointer :: eqn_of_state !< Equation of state structure
197  real, dimension(nz+1), intent(inout) :: zInterface !< Absolute positions of interfaces
198  real, optional, intent(in) :: h_neglect !< A negligibly small width for the
199  !! purpose of cell reconstructions
200  !! in the same units as h [Z ~> m]
201  real, optional, intent(in) :: h_neglect_edge !< A negligibly small width
202  !! for the purpose of edge value calculations
203  !! in the same units as h [Z ~> m]
204  ! Local variables
205  integer :: k, m
206  integer :: count_nonzero_layers
207  real :: deviation ! When iterating to determine the final
208  ! grid, this is the deviation between two
209  ! successive grids.
210  real :: threshold
211  real, dimension(nz) :: p, densities, T_tmp, S_tmp, Tmp
212  integer, dimension(nz) :: mapping
213  real, dimension(nz) :: h0, h1, hTmp
214  real, dimension(nz+1) :: x0, x1, xTmp
215 
216  threshold = cs%min_thickness
217  p(:) = cs%ref_pressure
218  t_tmp(:) = t(:)
219  s_tmp(:) = s(:)
220  h0(:) = h(:)
221 
222  ! Start iterations to build grid
223  m = 1
224  deviation = 1e10
225  do while ( ( m <= nb_regridding_iterations ) .and. &
226  ( deviation > deviation_tolerance ) )
227 
228  ! Construct column with vanished layers removed
229  call copy_finite_thicknesses(nz, h0, threshold, count_nonzero_layers, htmp, mapping)
230  if ( count_nonzero_layers <= 1 ) then
231  h1(:) = h0(:)
232  exit ! stop iterations here
233  endif
234 
235  xtmp(1) = 0.0
236  do k = 1,count_nonzero_layers
237  xtmp(k+1) = xtmp(k) + htmp(k)
238  enddo
239 
240  ! Compute densities within current water column
241  call calculate_density( t_tmp, s_tmp, p, densities,&
242  1, nz, eqn_of_state )
243 
244  do k = 1,count_nonzero_layers
245  densities(k) = densities(mapping(k))
246  enddo
247 
248  ! One regridding iteration
249  ! Based on global density profile, interpolate to generate a new grid
250  call build_and_interpolate_grid(cs%interp_CS, densities, count_nonzero_layers, &
251  htmp, xtmp, cs%target_density, nz, h1, x1, h_neglect, h_neglect_edge)
252 
253  call old_inflate_layers_1d( cs%min_thickness, nz, h1 )
254  x1(1) = 0.0 ; do k = 1,nz ; x1(k+1) = x1(k) + h1(k) ; enddo
255 
256  ! Remap T and S from previous grid to new grid
257  do k = 1,nz
258  h1(k) = x1(k+1) - x1(k)
259  enddo
260 
261  call remapping_core_h(remapcs, nz, h0, s, nz, h1, tmp, h_neglect, h_neglect_edge)
262  s_tmp(:) = tmp(:)
263 
264  call remapping_core_h(remapcs, nz, h0, t, nz, h1, tmp, h_neglect, h_neglect_edge)
265  t_tmp(:) = tmp(:)
266 
267  ! Compute the deviation between two successive grids
268  deviation = 0.0
269  x0(1) = 0.0
270  x1(1) = 0.0
271  do k = 2,nz
272  x0(k) = x0(k-1) + h0(k-1)
273  x1(k) = x1(k-1) + h1(k-1)
274  deviation = deviation + (x0(k)-x1(k))**2
275  enddo
276  deviation = sqrt( deviation / (nz-1) )
277 
278  m = m + 1
279 
280  ! Copy final grid onto start grid for next iteration
281  h0(:) = h1(:)
282 
283  enddo ! end regridding iterations
284 
285  if (cs%integrate_downward_for_e) then
286  zinterface(1) = 0.
287  do k = 1,nz
288  zinterface(k+1) = zinterface(k) - h1(k)
289  ! Adjust interface position to accommodate inflating layers
290  ! without disturbing the interface above
291  enddo
292  else
293  ! The rest of the model defines grids integrating up from the bottom
294  zinterface(nz+1) = -depth
295  do k = nz,1,-1
296  zinterface(k) = zinterface(k+1) + h1(k)
297  ! Adjust interface position to accommodate inflating layers
298  ! without disturbing the interface above
299  enddo
300  endif
301 

◆ copy_finite_thicknesses()

subroutine coord_rho::copy_finite_thicknesses ( integer, intent(in)  nk,
real, dimension(nk), intent(in)  h_in,
real, intent(in)  threshold,
integer, intent(out)  nout,
real, dimension(nk), intent(out)  h_out,
integer, dimension(nk), intent(out)  mapping 
)
private

Copy column thicknesses with vanished layers removed.

Parameters
[in]nkNumber of layer for h_in, T_in, S_in
[in]h_inThickness of input column
[in]thresholdThickness threshold defining vanished layers
[out]noutNumber of non-vanished layers
[out]h_outThickness of output column
[out]mappingIndex of k-out corresponding to k-in

Definition at line 306 of file coord_rho.F90.

306  integer, intent(in) :: nk !< Number of layer for h_in, T_in, S_in
307  real, dimension(nk), intent(in) :: h_in !< Thickness of input column
308  real, intent(in) :: threshold !< Thickness threshold defining vanished layers
309  integer, intent(out) :: nout !< Number of non-vanished layers
310  real, dimension(nk), intent(out) :: h_out !< Thickness of output column
311  integer, dimension(nk), intent(out) :: mapping !< Index of k-out corresponding to k-in
312  ! Local variables
313  integer :: k, k_thickest
314  real :: thickness_in_vanished, thickest_h_out
315 
316  ! Build up new grid
317  nout = 0
318  thickness_in_vanished = 0.0
319  thickest_h_out = h_in(1)
320  k_thickest = 1
321  do k = 1, nk
322  mapping(k) = nout ! Note k>=nout always
323  h_out(k) = 0. ! Make sure h_out is set everywhere
324  if (h_in(k) > threshold) then
325  ! For non-vanished layers
326  nout = nout + 1
327  mapping(nout) = k
328  h_out(nout) = h_in(k)
329  if (h_out(nout) > thickest_h_out) then
330  thickest_h_out = h_out(nout)
331  k_thickest = nout
332  endif
333  else
334  ! Add up mass in vanished layers
335  thickness_in_vanished = thickness_in_vanished + h_in(k)
336  endif
337  enddo
338 
339  ! No finite layers
340  if (nout <= 1) return
341 
342  ! Adjust for any lost volume in vanished layers
343  h_out(k_thickest) = h_out(k_thickest) + thickness_in_vanished
344 

◆ end_coord_rho()

subroutine, public coord_rho::end_coord_rho ( type(rho_cs), pointer  CS)

This subroutine deallocates memory in the control structure for the coord_rho module.

Parameters
csCoordinate control structure

Definition at line 65 of file coord_rho.F90.

65  type(rho_CS), pointer :: CS !< Coordinate control structure
66 
67  ! nothing to do
68  if (.not. associated(cs)) return
69  deallocate(cs%target_density)
70  deallocate(cs)

◆ init_coord_rho()

subroutine, public coord_rho::init_coord_rho ( type(rho_cs), pointer  CS,
integer, intent(in)  nk,
real, intent(in)  ref_pressure,
real, dimension(:), intent(in)  target_density,
type(interp_cs_type), intent(in)  interp_CS 
)

Initialise a rho_CS with pointers to parameters.

Parameters
csUnassociated pointer to hold the control structure
[in]nkNumber of layers in the grid
[in]ref_pressureCoordinate reference pressure [Pa]
[in]target_densityNominal density of interfaces [kg m-3]
[in]interp_csControls for interpolation

Definition at line 47 of file coord_rho.F90.

47  type(rho_CS), pointer :: CS !< Unassociated pointer to hold the control structure
48  integer, intent(in) :: nk !< Number of layers in the grid
49  real, intent(in) :: ref_pressure !< Coordinate reference pressure [Pa]
50  real, dimension(:), intent(in) :: target_density !< Nominal density of interfaces [kg m-3]
51  type(interp_CS_type), intent(in) :: interp_CS !< Controls for interpolation
52 
53  if (associated(cs)) call mom_error(fatal, "init_coord_rho: CS already associated!")
54  allocate(cs)
55  allocate(cs%target_density(nk+1))
56 
57  cs%nk = nk
58  cs%ref_pressure = ref_pressure
59  cs%target_density(:) = target_density(:)
60  cs%interp_CS = interp_cs

◆ old_inflate_layers_1d()

subroutine, public coord_rho::old_inflate_layers_1d ( real, intent(in)  min_thickness,
integer, intent(in)  nk,
real, dimension(:), intent(inout)  h 
)

Inflate vanished layers to finite (nonzero) width.

Parameters
[in]min_thicknessMinimum allowed thickness [H ~> m or kg m-2]
[in]nkNumber of layers in the grid
[in,out]hLayer thicknesses [H ~> m or kg m-2]

Definition at line 350 of file coord_rho.F90.

350 
351  ! Argument
352  real, intent(in) :: min_thickness !< Minimum allowed thickness [H ~> m or kg m-2]
353  integer, intent(in) :: nk !< Number of layers in the grid
354  real, dimension(:), intent(inout) :: h !< Layer thicknesses [H ~> m or kg m-2]
355 
356  ! Local variable
357  integer :: k
358  integer :: k_found
359  integer :: count_nonzero_layers
360  real :: delta
361  real :: correction
362  real :: maxThickness
363 
364  ! Count number of nonzero layers
365  count_nonzero_layers = 0
366  do k = 1,nk
367  if ( h(k) > min_thickness ) then
368  count_nonzero_layers = count_nonzero_layers + 1
369  endif
370  enddo
371 
372  ! If all layer thicknesses are greater than the threshold, exit routine
373  if ( count_nonzero_layers == nk ) return
374 
375  ! If all thicknesses are zero, inflate them all and exit
376  if ( count_nonzero_layers == 0 ) then
377  do k = 1,nk
378  h(k) = min_thickness
379  enddo
380  return
381  endif
382 
383  ! Inflate zero layers
384  correction = 0.0
385  do k = 1,nk
386  if ( h(k) <= min_thickness ) then
387  delta = min_thickness - h(k)
388  correction = correction + delta
389  h(k) = h(k) + delta
390  endif
391  enddo
392 
393  ! Modify thicknesses of nonzero layers to ensure volume conservation
394  maxthickness = h(1)
395  k_found = 1
396  do k = 1,nk
397  if ( h(k) > maxthickness ) then
398  maxthickness = h(k)
399  k_found = k
400  endif
401  enddo
402 
403  h(k_found) = h(k_found) - correction
404 

◆ set_rho_params()

subroutine, public coord_rho::set_rho_params ( type(rho_cs), pointer  CS,
real, intent(in), optional  min_thickness,
logical, intent(in), optional  integrate_downward_for_e,
type(interp_cs_type), intent(in), optional  interp_CS 
)

This subroutine can be used to set the parameters for the coord_rho module.

Parameters
csCoordinate control structure
[in]min_thicknessMinimum allowed thickness [H ~> m or kg m-2]
[in]integrate_downward_for_eIf true, integrate for interface positions from the top downward. If false, integrate from the bottom upward, as does the rest of the model.
[in]interp_csControls for interpolation

Definition at line 75 of file coord_rho.F90.

75  type(rho_CS), pointer :: CS !< Coordinate control structure
76  real, optional, intent(in) :: min_thickness !< Minimum allowed thickness [H ~> m or kg m-2]
77  logical, optional, intent(in) :: integrate_downward_for_e !< If true, integrate for interface
78  !! positions from the top downward. If false, integrate
79  !! from the bottom upward, as does the rest of the model.
80 
81  type(interp_CS_type), optional, intent(in) :: interp_CS !< Controls for interpolation
82 
83  if (.not. associated(cs)) call mom_error(fatal, "set_rho_params: CS not associated")
84 
85  if (present(min_thickness)) cs%min_thickness = min_thickness
86  if (present(integrate_downward_for_e)) cs%integrate_downward_for_e = integrate_downward_for_e
87  if (present(interp_cs)) cs%interp_CS = interp_cs