MOM6
MOM_ALE.F90
1 !> This module contains the main regridding routines.
2 !!
3 !! Regridding comprises two steps:
4 !! 1. Interpolation and creation of a new grid based on target interface
5 !! densities (or any other criterion).
6 !! 2. Remapping of quantities between old grid and new grid.
7 !!
8 !! Original module written by Laurent White, 2008.06.09
9 module mom_ale
10 
11 ! This file is part of MOM6. See LICENSE.md for the license.
12 
13 use mom_debugging, only : check_column_integrals
14 use mom_diag_mediator, only : register_diag_field, post_data, diag_ctrl
15 use mom_diag_mediator, only : time_type, diag_update_remap_grids
16 use mom_diag_vkernels, only : interpolate_column, reintegrate_column
17 use mom_domains, only : create_group_pass, do_group_pass, group_pass_type
18 use mom_eos, only : calculate_density
19 use mom_domains, only : create_group_pass, do_group_pass, group_pass_type
20 use mom_error_handler, only : mom_error, fatal, warning
21 use mom_error_handler, only : calltree_showquery
22 use mom_error_handler, only : calltree_enter, calltree_leave, calltree_waypoint
24 use mom_io, only : vardesc, var_desc, fieldtype, single_file
25 use mom_io, only : create_file, write_field, close_file
27 use mom_open_boundary, only : ocean_obc_type, obc_direction_e, obc_direction_w
28 use mom_open_boundary, only : obc_direction_n, obc_direction_s
29 use mom_regridding, only : initialize_regridding, regridding_main, end_regridding
30 use mom_regridding, only : uniformresolution
31 use mom_regridding, only : inflate_vanished_layers_old
32 use mom_regridding, only : set_target_densities_from_gv, set_target_densities
33 use mom_regridding, only : regriddingcoordinatemodedoc, default_coordinate_mode
34 use mom_regridding, only : regriddinginterpschemedoc, regriddingdefaultinterpscheme
35 use mom_regridding, only : regriddingdefaultboundaryextrapolation
36 use mom_regridding, only : regriddingdefaultminthickness
37 use mom_regridding, only : regridding_cs, set_regrid_params
38 use mom_regridding, only : getcoordinateinterfaces, getcoordinateresolution
39 use mom_regridding, only : getcoordinateunits, getcoordinateshortname
40 use mom_regridding, only : getstaticthickness
41 use mom_remapping, only : initialize_remapping, end_remapping
42 use mom_remapping, only : remapping_core_h, remapping_core_w
43 use mom_remapping, only : remappingschemesdoc, remappingdefaultscheme
44 use mom_remapping, only : remapping_cs, dzfromh1h2
45 use mom_string_functions, only : uppercase, extractword, extract_integer
46 use mom_tracer_registry, only : tracer_registry_type, tracer_type, mom_tracer_chkinv
48 use mom_variables, only : ocean_grid_type, thermo_var_ptrs
49 use mom_verticalgrid, only : get_thickness_units, verticalgrid_type
50 
51 !use regrid_consts, only : coordinateMode, DEFAULT_COORDINATE_MODE
52 use regrid_consts, only : coordinateunits, coordinatemode, state_dependent
53 use regrid_edge_values, only : edge_values_implicit_h4
54 use plm_functions, only : plm_reconstruction, plm_boundary_extrapolation
55 use plm_functions, only : plm_extrapolate_slope, plm_monotonized_slope, plm_slope_wa
56 use ppm_functions, only : ppm_reconstruction, ppm_boundary_extrapolation
57 
58 implicit none ; private
59 #include <MOM_memory.h>
60 
61 
62 !> ALE control structure
63 type, public :: ale_cs ; private
64  logical :: remap_uv_using_old_alg !< If true, uses the old "remapping via a delta z"
65  !! method. If False, uses the new method that
66  !! remaps between grids described by h.
67 
68  real :: regrid_time_scale !< The time-scale used in blending between the current (old) grid
69  !! and the target (new) grid [T ~> s]
70 
71  type(regridding_cs) :: regridcs !< Regridding parameters and work arrays
72  type(remapping_cs) :: remapcs !< Remapping parameters and work arrays
73 
74  integer :: nk !< Used only for queries, not directly by this module
75 
76  logical :: remap_after_initialization !< Indicates whether to regrid/remap after initializing the state.
77 
78  logical :: answers_2018 !< If true, use the order of arithmetic and expressions for remapping
79  !! that recover the answers from the end of 2018. Otherwise, use more
80  !! robust and accurate forms of mathematically equivalent expressions.
81 
82  logical :: show_call_tree !< For debugging
83 
84  ! for diagnostics
85  type(diag_ctrl), pointer :: diag !< structure to regulate output
86  integer, dimension(:), allocatable :: id_tracer_remap_tendency !< diagnostic id
87  integer, dimension(:), allocatable :: id_htracer_remap_tendency !< diagnostic id
88  integer, dimension(:), allocatable :: id_htracer_remap_tendency_2d !< diagnostic id
89  logical, dimension(:), allocatable :: do_tendency_diag !< flag for doing diagnostics
90  integer :: id_dzregrid = -1 !< diagnostic id
91 
92  ! diagnostic for fields prior to applying ALE remapping
93  integer :: id_u_preale = -1 !< diagnostic id for zonal velocity before ALE.
94  integer :: id_v_preale = -1 !< diagnostic id for meridional velocity before ALE.
95  integer :: id_h_preale = -1 !< diagnostic id for layer thicknesses before ALE.
96  integer :: id_t_preale = -1 !< diagnostic id for temperatures before ALE.
97  integer :: id_s_preale = -1 !< diagnostic id for salinities before ALE.
98  integer :: id_e_preale = -1 !< diagnostic id for interface heights before ALE.
99  integer :: id_vert_remap_h = -1 !< diagnostic id for layer thicknesses used for remapping
100  integer :: id_vert_remap_h_tendency = -1 !< diagnostic id for layer thickness tendency due to ALE
101 
102 end type
103 
104 ! Publicly available functions
105 public ale_init
106 public ale_end
107 public ale_main
108 public ale_main_offline
109 public ale_offline_inputs
110 public ale_offline_tracer_final
111 public ale_build_grid
112 public ale_regrid_accelerated
113 public ale_remap_scalar
114 public ale_plm_edge_values
115 public ts_plm_edge_values
116 public ts_ppm_edge_values
117 public adjustgridforintegrity
118 public ale_initregridding
119 public ale_getcoordinate
120 public ale_getcoordinateunits
121 public ale_writecoordinatefile
122 public ale_updateverticalgridtype
123 public ale_initthicknesstocoord
124 public ale_update_regrid_weights
125 public ale_remap_init_conds
126 public ale_register_diags
127 
128 ! A note on unit descriptions in comments: MOM6 uses units that can be rescaled for dimensional
129 ! consistency testing. These are noted in comments with units like Z, H, L, and T, along with
130 ! their mks counterparts with notation like "a velocity [Z T-1 ~> m s-1]". If the units
131 ! vary with the Boussinesq approximation, the Boussinesq variant is given first.
132 
133 contains
134 
135 !> This routine is typically called (from initialize_MOM in file MOM.F90)
136 !! before the main time integration loop to initialize the regridding stuff.
137 !! We read the MOM_input file to register the values of different
138 !! regridding/remapping parameters.
139 subroutine ale_init( param_file, GV, US, max_depth, CS)
140  type(param_file_type), intent(in) :: param_file !< Parameter file
141  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
142  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
143  real, intent(in) :: max_depth !< The maximum depth of the ocean [Z ~> m].
144  type(ale_cs), pointer :: cs !< Module control structure
145 
146  ! Local variables
147  real, dimension(:), allocatable :: dz
148  character(len=40) :: mdl = "MOM_ALE" ! This module's name.
149  character(len=80) :: string ! Temporary strings
150  real :: filter_shallow_depth, filter_deep_depth
151  logical :: default_2018_answers
152  logical :: check_reconstruction
153  logical :: check_remapping
154  logical :: force_bounds_in_subcell
155  logical :: local_logical
156  logical :: remap_boundary_extrap
157 
158  if (associated(cs)) then
159  call mom_error(warning, "ALE_init called with an associated "// &
160  "control structure.")
161  return
162  endif
163  allocate(cs)
164 
165  cs%show_call_tree = calltree_showquery()
166  if (cs%show_call_tree) call calltree_enter("ALE_init(), MOM_ALE.F90")
167 
168  call get_param(param_file, mdl, "REMAP_UV_USING_OLD_ALG", cs%remap_uv_using_old_alg, &
169  "If true, uses the old remapping-via-a-delta-z method for "//&
170  "remapping u and v. If false, uses the new method that remaps "//&
171  "between grids described by an old and new thickness.", &
172  default=.false.)
173 
174  ! Initialize and configure regridding
175  call ale_initregridding(gv, us, max_depth, param_file, mdl, cs%regridCS)
176 
177  ! Initialize and configure remapping
178  call get_param(param_file, mdl, "REMAPPING_SCHEME", string, &
179  "This sets the reconstruction scheme used "//&
180  "for vertical remapping for all variables. "//&
181  "It can be one of the following schemes: "//&
182  trim(remappingschemesdoc), default=remappingdefaultscheme)
183  call get_param(param_file, mdl, "FATAL_CHECK_RECONSTRUCTIONS", check_reconstruction, &
184  "If true, cell-by-cell reconstructions are checked for "//&
185  "consistency and if non-monotonicity or an inconsistency is "//&
186  "detected then a FATAL error is issued.", default=.false.)
187  call get_param(param_file, mdl, "FATAL_CHECK_REMAPPING", check_remapping, &
188  "If true, the results of remapping are checked for "//&
189  "conservation and new extrema and if an inconsistency is "//&
190  "detected then a FATAL error is issued.", default=.false.)
191  call get_param(param_file, mdl, "REMAP_BOUND_INTERMEDIATE_VALUES", force_bounds_in_subcell, &
192  "If true, the values on the intermediate grid used for remapping "//&
193  "are forced to be bounded, which might not be the case due to "//&
194  "round off.", default=.false.)
195  call get_param(param_file, mdl, "REMAP_BOUNDARY_EXTRAP", remap_boundary_extrap, &
196  "If true, values at the interfaces of boundary cells are "//&
197  "extrapolated instead of piecewise constant", default=.false.)
198  call get_param(param_file, mdl, "DEFAULT_2018_ANSWERS", default_2018_answers, &
199  "This sets the default value for the various _2018_ANSWERS parameters.", &
200  default=.false.)
201  call get_param(param_file, mdl, "REMAPPING_2018_ANSWERS", cs%answers_2018, &
202  "If true, use the order of arithmetic and expressions that recover the "//&
203  "answers from the end of 2018. Otherwise, use updated and more robust "//&
204  "forms of the same expressions.", default=default_2018_answers)
205  call initialize_remapping( cs%remapCS, string, &
206  boundary_extrapolation=remap_boundary_extrap, &
207  check_reconstruction=check_reconstruction, &
208  check_remapping=check_remapping, &
209  force_bounds_in_subcell=force_bounds_in_subcell, &
210  answers_2018=cs%answers_2018)
211 
212  call get_param(param_file, mdl, "REMAP_AFTER_INITIALIZATION", cs%remap_after_initialization, &
213  "If true, applies regridding and remapping immediately after "//&
214  "initialization so that the state is ALE consistent. This is a "//&
215  "legacy step and should not be needed if the initialization is "//&
216  "consistent with the coordinate mode.", default=.true.)
217 
218  call get_param(param_file, mdl, "REGRID_TIME_SCALE", cs%regrid_time_scale, &
219  "The time-scale used in blending between the current (old) grid "//&
220  "and the target (new) grid. A short time-scale favors the target "//&
221  "grid (0. or anything less than DT_THERM) has no memory of the old "//&
222  "grid. A very long time-scale makes the model more Lagrangian.", &
223  units="s", default=0., scale=us%s_to_T)
224  call get_param(param_file, mdl, "REGRID_FILTER_SHALLOW_DEPTH", filter_shallow_depth, &
225  "The depth above which no time-filtering is applied. Above this depth "//&
226  "final grid exactly matches the target (new) grid.", &
227  units="m", default=0., scale=gv%m_to_H)
228  call get_param(param_file, mdl, "REGRID_FILTER_DEEP_DEPTH", filter_deep_depth, &
229  "The depth below which full time-filtering is applied with time-scale "//&
230  "REGRID_TIME_SCALE. Between depths REGRID_FILTER_SHALLOW_DEPTH and "//&
231  "REGRID_FILTER_SHALLOW_DEPTH the filter weights adopt a cubic profile.", &
232  units="m", default=0., scale=gv%m_to_H)
233  call set_regrid_params(cs%regridCS, depth_of_time_filter_shallow=filter_shallow_depth, &
234  depth_of_time_filter_deep=filter_deep_depth)
235  call get_param(param_file, mdl, "REGRID_USE_OLD_DIRECTION", local_logical, &
236  "If true, the regridding ntegrates upwards from the bottom for "//&
237  "interface positions, much as the main model does. If false "//&
238  "regridding integrates downward, consistant with the remapping "//&
239  "code.", default=.true., do_not_log=.true.)
240  call set_regrid_params(cs%regridCS, integrate_downward_for_e=.not.local_logical)
241 
242  ! Keep a record of values for subsequent queries
243  cs%nk = gv%ke
244 
245  if (cs%show_call_tree) call calltree_leave("ALE_init()")
246 end subroutine ale_init
247 
248 !> Initialize diagnostics for the ALE module.
249 subroutine ale_register_diags(Time, G, GV, US, diag, CS)
250  type(time_type),target, intent(in) :: time !< Time structure
251  type(ocean_grid_type), intent(in) :: g !< Grid structure
252  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
253  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
254  type(diag_ctrl), target, intent(in) :: diag !< Diagnostics control structure
255  type(ale_cs), pointer :: cs !< Module control structure
256 
257  cs%diag => diag
258 
259  ! These diagnostics of the state variables before ALE are useful for
260  ! debugging the ALE code.
261  cs%id_u_preale = register_diag_field('ocean_model', 'u_preale', diag%axesCuL, time, &
262  'Zonal velocity before remapping', 'm s-1', conversion=us%L_T_to_m_s)
263  cs%id_v_preale = register_diag_field('ocean_model', 'v_preale', diag%axesCvL, time, &
264  'Meridional velocity before remapping', 'm s-1', conversion=us%L_T_to_m_s)
265  cs%id_h_preale = register_diag_field('ocean_model', 'h_preale', diag%axesTL, time, &
266  'Layer Thickness before remapping', get_thickness_units(gv), &
267  conversion=gv%H_to_MKS, v_extensive=.true.)
268  cs%id_T_preale = register_diag_field('ocean_model', 'T_preale', diag%axesTL, time, &
269  'Temperature before remapping', 'degC')
270  cs%id_S_preale = register_diag_field('ocean_model', 'S_preale', diag%axesTL, time, &
271  'Salinity before remapping', 'PSU')
272  cs%id_e_preale = register_diag_field('ocean_model', 'e_preale', diag%axesTi, time, &
273  'Interface Heights before remapping', 'm', conversion=us%Z_to_m)
274 
275  cs%id_dzRegrid = register_diag_field('ocean_model','dzRegrid',diag%axesTi,time, &
276  'Change in interface height due to ALE regridding', 'm', &
277  conversion=gv%H_to_m)
278  cs%id_vert_remap_h = register_diag_field('ocean_model', 'vert_remap_h', &
279  diag%axestl, time, 'layer thicknesses after ALE regridding and remapping', 'm', &
280  conversion=gv%H_to_m, v_extensive=.true.)
281  cs%id_vert_remap_h_tendency = register_diag_field('ocean_model','vert_remap_h_tendency',diag%axestl,time, &
282  'Layer thicknesses tendency due to ALE regridding and remapping', 'm', &
283  conversion=gv%H_to_m*us%s_to_T, v_extensive = .true.)
284 
285 end subroutine ale_register_diags
286 
287 !> Crudely adjust (initial) grid for integrity.
288 !! This routine is typically called (from initialize_MOM in file MOM.F90)
289 !! before the main time integration loop to initialize the regridding stuff.
290 !! We read the MOM_input file to register the values of different
291 !! regridding/remapping parameters.
292 subroutine adjustgridforintegrity( CS, G, GV, h )
293  type(ale_cs), pointer :: cs !< Regridding parameters and options
294  type(ocean_grid_type), intent(in) :: g !< Ocean grid informations
295  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
296  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: h !< Current 3D grid thickness that
297  !! are to be adjusted [H ~> m or kg-2]
298  call inflate_vanished_layers_old( cs%regridCS, g, gv, h(:,:,:) )
299 
300 end subroutine adjustgridforintegrity
301 
302 
303 !> End of regridding (memory deallocation).
304 !! This routine is typically called (from MOM_end in file MOM.F90)
305 !! after the main time integration loop to deallocate the regridding stuff.
306 subroutine ale_end(CS)
307  type(ale_cs), pointer :: cs !< module control structure
308 
309  ! Deallocate memory used for the regridding
310  call end_remapping( cs%remapCS )
311  call end_regridding( cs%regridCS )
312 
313  deallocate(cs)
314 
315 end subroutine ale_end
316 
317 !> Takes care of (1) building a new grid and (2) remapping all variables between
318 !! the old grid and the new grid. The creation of the new grid can be based
319 !! on z coordinates, target interface densities, sigma coordinates or any
320 !! arbitrary coordinate system.
321 subroutine ale_main( G, GV, US, h, u, v, tv, Reg, CS, OBC, dt, frac_shelf_h)
322  type(ocean_grid_type), intent(in) :: g !< Ocean grid informations
323  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
324  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
325  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: h !< Current 3D grid obtained after the
326  !! last time step [H ~> m or kg m-2]
327  real, dimension(SZIB_(G),SZJ_(G),SZK_(GV)), intent(inout) :: u !< Zonal velocity field [L T-1 ~> m s-1]
328  real, dimension(SZI_(G),SZJB_(G),SZK_(GV)), intent(inout) :: v !< Meridional velocity field [L T-1 ~> m s-1]
329  type(thermo_var_ptrs), intent(inout) :: tv !< Thermodynamic variable structure
330  type(tracer_registry_type), pointer :: reg !< Tracer registry structure
331  type(ale_cs), pointer :: cs !< Regridding parameters and options
332  type(ocean_obc_type), pointer :: obc !< Open boundary structure
333  real, optional, intent(in) :: dt !< Time step between calls to ALE_main [T ~> s]
334  real, dimension(:,:), optional, pointer :: frac_shelf_h !< Fractional ice shelf coverage
335  ! Local variables
336  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1) :: dzregrid ! The change in grid interface positions
337  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1) :: eta_preale
338  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: h_new ! New 3D grid obtained after last time step [H ~> m or kg-2]
339  integer :: nk, i, j, k, isc, iec, jsc, jec
340  logical :: ice_shelf
341 
342  nk = gv%ke; isc = g%isc; iec = g%iec; jsc = g%jsc; jec = g%jec
343 
344  ice_shelf = .false.
345  if (present(frac_shelf_h)) then
346  if (associated(frac_shelf_h)) ice_shelf = .true.
347  endif
348 
349  if (cs%show_call_tree) call calltree_enter("ALE_main(), MOM_ALE.F90")
350 
351  ! These diagnostics of the state before ALE is applied are mostly used for debugging.
352  if (cs%id_u_preale > 0) call post_data(cs%id_u_preale, u, cs%diag)
353  if (cs%id_v_preale > 0) call post_data(cs%id_v_preale, v, cs%diag)
354  if (cs%id_h_preale > 0) call post_data(cs%id_h_preale, h, cs%diag)
355  if (cs%id_T_preale > 0) call post_data(cs%id_T_preale, tv%T, cs%diag)
356  if (cs%id_S_preale > 0) call post_data(cs%id_S_preale, tv%S, cs%diag)
357  if (cs%id_e_preale > 0) then
358  call find_eta(h, tv, g, gv, us, eta_preale)
359  call post_data(cs%id_e_preale, eta_preale, cs%diag)
360  endif
361 
362  if (present(dt)) then
363  call ale_update_regrid_weights( dt, cs )
364  endif
365  dzregrid(:,:,:) = 0.0
366 
367  ! Build new grid. The new grid is stored in h_new. The old grid is h.
368  ! Both are needed for the subsequent remapping of variables.
369  if (ice_shelf) then
370  call regridding_main( cs%remapCS, cs%regridCS, g, gv, h, tv, h_new, dzregrid, frac_shelf_h)
371  else
372  call regridding_main( cs%remapCS, cs%regridCS, g, gv, h, tv, h_new, dzregrid)
373  endif
374 
375  call check_grid( g, gv, h, 0. )
376 
377  if (cs%show_call_tree) call calltree_waypoint("new grid generated (ALE_main)")
378 
379  ! The presence of dt is used for expediency to distinguish whether ALE_main is being called during init
380  ! or in the main loop. Tendency diagnostics in remap_all_state_vars also rely on this logic.
381  if (present(dt)) then
382  call diag_update_remap_grids(cs%diag)
383  endif
384  ! Remap all variables from old grid h onto new grid h_new
385  call remap_all_state_vars( cs%remapCS, cs, g, gv, h, h_new, reg, obc, -dzregrid, &
386  u, v, cs%show_call_tree, dt )
387 
388  if (cs%show_call_tree) call calltree_waypoint("state remapped (ALE_main)")
389 
390  ! Override old grid with new one. The new grid 'h_new' is built in
391  ! one of the 'build_...' routines above.
392  !$OMP parallel do default(shared)
393  do k = 1,nk ; do j = jsc-1,jec+1 ; do i = isc-1,iec+1
394  h(i,j,k) = h_new(i,j,k)
395  enddo ; enddo ; enddo
396 
397  if (cs%show_call_tree) call calltree_leave("ALE_main()")
398 
399  if (cs%id_dzRegrid>0 .and. present(dt)) call post_data(cs%id_dzRegrid, dzregrid, cs%diag)
400 
401 
402 end subroutine ale_main
403 
404 !> Takes care of (1) building a new grid and (2) remapping all variables between
405 !! the old grid and the new grid. The creation of the new grid can be based
406 !! on z coordinates, target interface densities, sigma coordinates or any
407 !! arbitrary coordinate system.
408 subroutine ale_main_offline( G, GV, h, tv, Reg, CS, OBC, dt)
409  type(ocean_grid_type), intent(in) :: g !< Ocean grid informations
410  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
411  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: h !< Current 3D grid obtained after the
412  !! last time step [H ~> m or kg-2]
413  type(thermo_var_ptrs), intent(inout) :: tv !< Thermodynamic variable structure
414  type(tracer_registry_type), pointer :: reg !< Tracer registry structure
415  type(ale_cs), pointer :: cs !< Regridding parameters and options
416  type(ocean_obc_type), pointer :: obc !< Open boundary structure
417  real, optional, intent(in) :: dt !< Time step between calls to ALE_main [T ~> s]
418  ! Local variables
419  real, dimension(SZI_(G), SZJ_(G), SZK_(GV)+1) :: dzregrid ! The change in grid interface positions
420  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: h_new ! New 3D grid obtained after last time step [H ~> m or kg-2]
421  integer :: nk, i, j, k, isc, iec, jsc, jec
422 
423  nk = gv%ke; isc = g%isc; iec = g%iec; jsc = g%jsc; jec = g%jec
424 
425  if (cs%show_call_tree) call calltree_enter("ALE_main_offline(), MOM_ALE.F90")
426 
427  if (present(dt)) then
428  call ale_update_regrid_weights( dt, cs )
429  endif
430  dzregrid(:,:,:) = 0.0
431 
432  ! Build new grid. The new grid is stored in h_new. The old grid is h.
433  ! Both are needed for the subsequent remapping of variables.
434  call regridding_main( cs%remapCS, cs%regridCS, g, gv, h, tv, h_new, dzregrid )
435 
436  call check_grid( g, gv, h, 0. )
437 
438  if (cs%show_call_tree) call calltree_waypoint("new grid generated (ALE_main)")
439 
440  ! Remap all variables from old grid h onto new grid h_new
441 
442  call remap_all_state_vars(cs%remapCS, cs, g, gv, h, h_new, reg, obc, &
443  debug=cs%show_call_tree, dt=dt )
444 
445  if (cs%show_call_tree) call calltree_waypoint("state remapped (ALE_main)")
446 
447  ! Override old grid with new one. The new grid 'h_new' is built in
448  ! one of the 'build_...' routines above.
449  !$OMP parallel do default(shared)
450  do k = 1,nk ; do j = jsc-1,jec+1 ; do i = isc-1,iec+1
451  h(i,j,k) = h_new(i,j,k)
452  enddo ; enddo ; enddo
453 
454  if (cs%show_call_tree) call calltree_leave("ALE_main()")
455  if (cs%id_dzRegrid>0 .and. present(dt)) call post_data(cs%id_dzRegrid, dzregrid, cs%diag)
456 
457 end subroutine ale_main_offline
458 
459 !> Regrid/remap stored fields used for offline tracer integrations. These input fields are assumed to have
460 !! the same layer thicknesses at the end of the last offline interval (which should be a Zstar grid). This
461 !! routine builds a grid on the runtime specified vertical coordinate
462 subroutine ale_offline_inputs(CS, G, GV, h, tv, Reg, uhtr, vhtr, Kd, debug, OBC)
463  type(ale_cs), pointer :: cs !< Regridding parameters and options
464  type(ocean_grid_type), intent(in ) :: g !< Ocean grid informations
465  type(verticalgrid_type), intent(in ) :: gv !< Ocean vertical grid structure
466  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: h !< Layer thicknesses
467  type(thermo_var_ptrs), intent(inout) :: tv !< Thermodynamic variable structure
468  type(tracer_registry_type), pointer :: reg !< Tracer registry structure
469  real, dimension(SZIB_(G),SZJ_(G),SZK_(GV)), intent(inout) :: uhtr !< Zonal mass fluxes
470  real, dimension(SZI_(G),SZJB_(G),SZK_(GV)), intent(inout) :: vhtr !< Meridional mass fluxes
471  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), intent(inout) :: kd !< Input diffusivites
472  logical, intent(in ) :: debug !< If true, then turn checksums
473  type(ocean_obc_type), pointer :: obc !< Open boundary structure
474  ! Local variables
475  integer :: nk, i, j, k, isc, iec, jsc, jec
476  real, dimension(SZI_(G), SZJ_(G), SZK_(GV)) :: h_new ! Layer thicknesses after regridding
477  real, dimension(SZI_(G), SZJ_(G), SZK_(GV)+1) :: dzregrid ! The change in grid interface positions
478  real, dimension(SZK_(GV)) :: h_src
479  real, dimension(SZK_(GV)) :: h_dest, uh_dest
480  real, dimension(SZK_(GV)) :: temp_vec
481 
482  nk = gv%ke; isc = g%isc; iec = g%iec; jsc = g%jsc; jec = g%jec
483  dzregrid(:,:,:) = 0.0
484  h_new(:,:,:) = 0.0
485 
486  if (debug) call mom_tracer_chkinv("Before ALE_offline_inputs", g, h, reg%Tr, reg%ntr)
487 
488  ! Build new grid from the Zstar state onto the requested vertical coordinate. The new grid is stored
489  ! in h_new. The old grid is h. Both are needed for the subsequent remapping of variables. Convective
490  ! adjustment right now is not used because it is unclear what to do with vanished layers
491  call regridding_main( cs%remapCS, cs%regridCS, g, gv, h, tv, h_new, dzregrid, conv_adjust = .false. )
492  call check_grid( g, gv, h_new, 0. )
493  if (cs%show_call_tree) call calltree_waypoint("new grid generated (ALE_offline_inputs)")
494 
495  ! Remap all variables from old grid h onto new grid h_new
496  call remap_all_state_vars( cs%remapCS, cs, g, gv, h, h_new, reg, obc, debug=cs%show_call_tree )
497  if (cs%show_call_tree) call calltree_waypoint("state remapped (ALE_inputs)")
498 
499  ! Reintegrate mass transports from Zstar to the offline vertical coordinate
500  do j=jsc,jec ; do i=g%iscB,g%iecB
501  if (g%mask2dCu(i,j)>0.) then
502  h_src(:) = 0.5 * (h(i,j,:) + h(i+1,j,:))
503  h_dest(:) = 0.5 * (h_new(i,j,:) + h_new(i+1,j,:))
504  call reintegrate_column(nk, h_src, uhtr(i,j,:), nk, h_dest, 0., temp_vec)
505  uhtr(i,j,:) = temp_vec
506  endif
507  enddo ; enddo
508  do j=g%jscB,g%jecB ; do i=isc,iec
509  if (g%mask2dCv(i,j)>0.) then
510  h_src(:) = 0.5 * (h(i,j,:) + h(i,j+1,:))
511  h_dest(:) = 0.5 * (h_new(i,j,:) + h_new(i,j+1,:))
512  call reintegrate_column(nk, h_src, vhtr(i,j,:), nk, h_dest, 0., temp_vec)
513  vhtr(i,j,:) = temp_vec
514  endif
515  enddo ; enddo
516 
517  do j = jsc,jec ; do i=isc,iec
518  if (g%mask2dT(i,j)>0.) then
519  if (check_column_integrals(nk, h_src, nk, h_dest)) then
520  call mom_error(fatal, "ALE_offline_inputs: Kd interpolation columns do not match")
521  endif
522  call interpolate_column(nk, h(i,j,:), kd(i,j,:), nk, h_new(i,j,:), 0., kd(i,j,:))
523  endif
524  enddo ; enddo
525 
526  call ale_remap_scalar(cs%remapCS, g, gv, nk, h, tv%T, h_new, tv%T, answers_2018=cs%answers_2018)
527  call ale_remap_scalar(cs%remapCS, g, gv, nk, h, tv%S, h_new, tv%S, answers_2018=cs%answers_2018)
528 
529  if (debug) call mom_tracer_chkinv("After ALE_offline_inputs", g, h_new, reg%Tr, reg%ntr)
530 
531  ! Copy over the new layer thicknesses
532  do k = 1,nk ; do j = jsc-1,jec+1 ; do i = isc-1,iec+1
533  h(i,j,k) = h_new(i,j,k)
534  enddo ; enddo ; enddo
535 
536  if (cs%show_call_tree) call calltree_leave("ALE_offline_inputs()")
537 end subroutine ale_offline_inputs
538 
539 
540 !> Remaps all tracers from h onto h_target. This is intended to be called when tracers
541 !! are done offline. In the case where transports don't quite conserve, we still want to
542 !! make sure that layer thicknesses offline do not drift too far away from the online model
543 subroutine ale_offline_tracer_final( G, GV, h, tv, h_target, Reg, CS, OBC)
544  type(ocean_grid_type), intent(in) :: g !< Ocean grid informations
545  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
546  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: h !< Current 3D grid obtained after the
547  !! last time step [H ~> m or kg-2]
548  type(thermo_var_ptrs), intent(inout) :: tv !< Thermodynamic variable structure
549  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: h_target !< Current 3D grid obtained after
550  !! last time step [H ~> m or kg-2]
551  type(tracer_registry_type), pointer :: reg !< Tracer registry structure
552  type(ale_cs), pointer :: cs !< Regridding parameters and options
553  type(ocean_obc_type), pointer :: obc !< Open boundary structure
554  ! Local variables
555 
556  real, dimension(SZI_(G), SZJ_(G), SZK_(GV)+1) :: dzregrid !< The change in grid interface positions
557  real, dimension(SZI_(G), SZJ_(G), SZK_(GV)) :: h_new !< Regridded target thicknesses
558  integer :: nk, i, j, k, isc, iec, jsc, jec
559 
560  nk = gv%ke; isc = g%isc; iec = g%iec; jsc = g%jsc; jec = g%jec
561 
562  if (cs%show_call_tree) call calltree_enter("ALE_offline_tracer_final(), MOM_ALE.F90")
563  ! Need to make sure that h_target is consistent with the current offline ALE confiuration
564  call regridding_main( cs%remapCS, cs%regridCS, g, gv, h_target, tv, h_new, dzregrid )
565  call check_grid( g, gv, h_target, 0. )
566 
567 
568  if (cs%show_call_tree) call calltree_waypoint("Source and target grids checked (ALE_offline_tracer_final)")
569 
570  ! Remap all variables from old grid h onto new grid h_new
571 
572  call remap_all_state_vars( cs%remapCS, cs, g, gv, h, h_new, reg, obc, debug=cs%show_call_tree )
573 
574  if (cs%show_call_tree) call calltree_waypoint("state remapped (ALE_offline_tracer_final)")
575 
576  ! Override old grid with new one. The new grid 'h_new' is built in
577  ! one of the 'build_...' routines above.
578  !$OMP parallel do default(shared)
579  do k = 1,nk
580  do j = jsc-1,jec+1 ; do i = isc-1,iec+1
581  h(i,j,k) = h_new(i,j,k)
582  enddo ; enddo
583  enddo
584  if (cs%show_call_tree) call calltree_leave("ALE_offline_tracer_final()")
585 end subroutine ale_offline_tracer_final
586 
587 !> Check grid for negative thicknesses
588 subroutine check_grid( G, GV, h, threshold )
589  type(ocean_grid_type), intent(in) :: G !< Ocean grid structure
590  type(verticalgrid_type), intent(in) :: GV !< Ocean vertical grid structure
591  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Current 3D grid obtained after the
592  !! last time step [H ~> m or kg m-2]
593  real, intent(in) :: threshold !< Value below which to flag issues,
594  !! [H ~> m or kg m-2]
595  ! Local variables
596  integer :: i, j
597 
598  do j = g%jsc,g%jec ; do i = g%isc,g%iec
599  if (g%mask2dT(i,j)>0.) then
600  if (minval(h(i,j,:)) < threshold) then
601  write(0,*) 'check_grid: i,j=',i,j,'h(i,j,:)=',h(i,j,:)
602  if (threshold <= 0.) then
603  call mom_error(fatal,"MOM_ALE, check_grid: negative thickness encountered.")
604  else
605  call mom_error(fatal,"MOM_ALE, check_grid: too tiny thickness encountered.")
606  endif
607  endif
608  endif
609  enddo ; enddo
610 
611 
612 end subroutine check_grid
613 
614 !> Generates new grid
615 subroutine ale_build_grid( G, GV, regridCS, remapCS, h, tv, debug, frac_shelf_h )
616  type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
617  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
618  type(regridding_cs), intent(in) :: regridcs !< Regridding parameters and options
619  type(remapping_cs), intent(in) :: remapcs !< Remapping parameters and options
620  type(thermo_var_ptrs), intent(inout) :: tv !< Thermodynamical variable structure
621  real, dimension(SZI_(G),SZJ_(G), SZK_(GV)), intent(inout) :: h !< Current 3D grid obtained after the
622  !! last time step [H ~> m or kg-2]
623  logical, optional, intent(in) :: debug !< If true, show the call tree
624  real, dimension(:,:), optional, pointer :: frac_shelf_h !< Fractional ice shelf coverage
625  ! Local variables
626  integer :: nk, i, j, k
627  real, dimension(SZI_(G), SZJ_(G), SZK_(GV)+1) :: dzregrid ! The change in grid interface positions
628  real, dimension(SZI_(G), SZJ_(G), SZK_(GV)) :: h_new ! The new grid thicknesses
629  logical :: show_call_tree, use_ice_shelf
630 
631  show_call_tree = .false.
632  if (present(debug)) show_call_tree = debug
633  if (show_call_tree) call calltree_enter("ALE_build_grid(), MOM_ALE.F90")
634  use_ice_shelf = .false.
635  if (present(frac_shelf_h)) then
636  if (associated(frac_shelf_h)) use_ice_shelf = .true.
637  endif
638 
639  ! Build new grid. The new grid is stored in h_new. The old grid is h.
640  ! Both are needed for the subsequent remapping of variables.
641  if (use_ice_shelf) then
642  call regridding_main( remapcs, regridcs, g, gv, h, tv, h_new, dzregrid, frac_shelf_h )
643  else
644  call regridding_main( remapcs, regridcs, g, gv, h, tv, h_new, dzregrid )
645  endif
646 
647  ! Override old grid with new one. The new grid 'h_new' is built in
648  ! one of the 'build_...' routines above.
649 !$OMP parallel do default(none) shared(G,h,h_new)
650  do j = g%jsc,g%jec ; do i = g%isc,g%iec
651  if (g%mask2dT(i,j)>0.) h(i,j,:) = h_new(i,j,:)
652  enddo ; enddo
653 
654  if (show_call_tree) call calltree_leave("ALE_build_grid()")
655 end subroutine ale_build_grid
656 
657 !> For a state-based coordinate, accelerate the process of regridding by
658 !! repeatedly applying the grid calculation algorithm
659 subroutine ale_regrid_accelerated(CS, G, GV, h, tv, n, u, v, OBC, Reg, dt, dzRegrid, initial)
660  type(ale_cs), pointer :: cs !< ALE control structure
661  type(ocean_grid_type), intent(inout) :: g !< Ocean grid
662  type(verticalgrid_type), intent(in) :: gv !< Vertical grid
663  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
664  intent(inout) :: h !< Original thicknesses [H ~> m or kg-2]
665  type(thermo_var_ptrs), intent(inout) :: tv !< Thermo vars (T/S/EOS)
666  integer, intent(in) :: n !< Number of times to regrid
667  real, dimension(SZIB_(G),SZJ_(G),SZK_(GV)), &
668  intent(inout) :: u !< Zonal velocity [L T-1 ~> m s-1]
669  real, dimension(SZI_(G),SZJB_(G),SZK_(GV)), &
670  intent(inout) :: v !< Meridional velocity [L T-1 ~> m s-1]
671  type(ocean_obc_type), pointer :: obc !< Open boundary structure
672  type(tracer_registry_type), &
673  optional, pointer :: reg !< Tracer registry to remap onto new grid
674  real, optional, intent(in) :: dt !< Model timestep to provide a timescale for regridding [T ~> s]
675  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), &
676  optional, intent(inout) :: dzregrid !< Final change in interface positions
677  logical, optional, intent(in) :: initial !< Whether we're being called from an initialization
678  !! routine (and expect diagnostics to work)
679 
680  ! Local variables
681  integer :: i, j, k, nz
682  type(thermo_var_ptrs) :: tv_local ! local/intermediate temp/salt
683  type(group_pass_type) :: pass_t_s_h ! group pass if the coordinate has a stencil
684  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: h_loc, h_orig ! A working copy of layer thicknesses
685  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), target :: t, s ! local temporary state
686  ! we have to keep track of the total dzInterface if for some reason
687  ! we're using the old remapping algorithm for u/v
688  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1) :: dzinterface, dzinttotal
689 
690  nz = gv%ke
691 
692  ! initial total interface displacement due to successive regridding
693  dzinttotal(:,:,:) = 0.
694 
695  call create_group_pass(pass_t_s_h, t, g%domain)
696  call create_group_pass(pass_t_s_h, s, g%domain)
697  call create_group_pass(pass_t_s_h, h_loc, g%domain)
698 
699  ! copy original temp/salt and set our local tv_pointers to them
700  tv_local = tv
701  t(:,:,:) = tv%T(:,:,:)
702  s(:,:,:) = tv%S(:,:,:)
703  tv_local%T => t
704  tv_local%S => s
705 
706  ! get local copy of thickness and save original state for remapping
707  h_loc(:,:,:) = h(:,:,:)
708  h_orig(:,:,:) = h(:,:,:)
709 
710  ! Apply timescale to regridding (for e.g. filtered_grid_motion)
711  if (present(dt)) &
712  call ale_update_regrid_weights(dt, cs)
713 
714  do k = 1, n
715  call do_group_pass(pass_t_s_h, g%domain)
716 
717  ! generate new grid
718  call regridding_main(cs%remapCS, cs%regridCS, g, gv, h_loc, tv_local, h, dzinterface)
719  dzinttotal(:,:,:) = dzinttotal(:,:,:) + dzinterface(:,:,:)
720 
721  ! remap from original grid onto new grid
722  do j = g%jsc-1,g%jec+1 ; do i = g%isc-1,g%iec+1
723  call remapping_core_h(cs%remapCS, nz, h_orig(i,j,:), tv%S(i,j,:), nz, h(i,j,:), tv_local%S(i,j,:))
724  call remapping_core_h(cs%remapCS, nz, h_orig(i,j,:), tv%T(i,j,:), nz, h(i,j,:), tv_local%T(i,j,:))
725  enddo ; enddo
726 
727  ! starting grid for next iteration
728  h_loc(:,:,:) = h(:,:,:)
729  enddo
730 
731  ! remap all state variables (including those that weren't needed for regridding)
732  call remap_all_state_vars(cs%remapCS, cs, g, gv, h_orig, h, reg, obc, dzinttotal, u, v)
733 
734  ! save total dzregrid for diags if needed?
735  if (present(dzregrid)) dzregrid(:,:,:) = dzinttotal(:,:,:)
736 end subroutine ale_regrid_accelerated
737 
738 !> This routine takes care of remapping all variable between the old and the
739 !! new grids. When velocity components need to be remapped, thicknesses at
740 !! velocity points are taken to be arithmetic averages of tracer thicknesses.
741 !! This routine is called during initialization of the model at time=0, to
742 !! remap initiali conditions to the model grid. It is also called during a
743 !! time step to update the state.
744 subroutine remap_all_state_vars(CS_remapping, CS_ALE, G, GV, h_old, h_new, Reg, OBC, &
745  dxInterface, u, v, debug, dt)
746  type(remapping_cs), intent(in) :: CS_remapping !< Remapping control structure
747  type(ale_cs), intent(in) :: CS_ALE !< ALE control structure
748  type(ocean_grid_type), intent(in) :: G !< Ocean grid structure
749  type(verticalgrid_type), intent(in) :: GV !< Ocean vertical grid structure
750  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h_old !< Thickness of source grid
751  !! [H ~> m or kg-2]
752  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h_new !< Thickness of destination grid
753  !! [H ~> m or kg-2]
754  type(tracer_registry_type), pointer :: Reg !< Tracer registry structure
755  type(ocean_obc_type), pointer :: OBC !< Open boundary structure
756  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), &
757  optional, intent(in) :: dxInterface !< Change in interface position
758  !! [H ~> m or kg-2]
759  real, dimension(SZIB_(G),SZJ_(G),SZK_(GV)), &
760  optional, intent(inout) :: u !< Zonal velocity [L T-1 ~> m s-1]
761  real, dimension(SZI_(G),SZJB_(G),SZK_(GV)), &
762  optional, intent(inout) :: v !< Meridional velocity [L T-1 ~> m s-1]
763  logical, optional, intent(in) :: debug !< If true, show the call tree
764  real, optional, intent(in) :: dt !< time step for diagnostics [T ~> s]
765  ! Local variables
766  integer :: i, j, k, m
767  integer :: nz, ntr
768  real, dimension(GV%ke+1) :: dx
769  real, dimension(GV%ke) :: h1, u_column
770  real, dimension(SZI_(G), SZJ_(G), SZK_(GV)) :: work_conc
771  real, dimension(SZI_(G), SZJ_(G), SZK_(GV)) :: work_cont
772  real, dimension(SZI_(G), SZJ_(G)) :: work_2d
773  real :: Idt ! The inverse of the timestep [T-1 ~> s-1]
774  real :: ppt2mks
775  real, dimension(GV%ke) :: h2
776  real :: h_neglect, h_neglect_edge
777  logical :: show_call_tree
778  type(tracer_type), pointer :: Tr => null()
779 
780  show_call_tree = .false.
781  if (present(debug)) show_call_tree = debug
782  if (show_call_tree) call calltree_enter("remap_all_state_vars(), MOM_ALE.F90")
783 
784  ! If remap_uv_using_old_alg is .true. and u or v is requested, then we must have dxInterface. Otherwise,
785  ! u and v can be remapped without dxInterface
786  if ( .not. present(dxinterface) .and. (cs_ale%remap_uv_using_old_alg .and. (present(u) .or. present(v))) ) then
787  call mom_error(fatal, "remap_all_state_vars: dxInterface must be present if using old algorithm "// &
788  "and u/v are to be remapped")
789  endif
790 
791  if (.not.cs_ale%answers_2018) then
792  h_neglect = gv%H_subroundoff ; h_neglect_edge = gv%H_subroundoff
793  elseif (gv%Boussinesq) then
794  h_neglect = gv%m_to_H*1.0e-30 ; h_neglect_edge = gv%m_to_H*1.0e-10
795  else
796  h_neglect = gv%kg_m2_to_H*1.0e-30 ; h_neglect_edge = gv%kg_m2_to_H*1.0e-10
797  endif
798 
799  nz = gv%ke
800  ppt2mks = 0.001
801 
802  ntr = 0 ; if (associated(reg)) ntr = reg%ntr
803 
804  if (present(dt)) then
805  idt = 1.0/dt
806  work_conc(:,:,:) = 0.0
807  work_cont(:,:,:) = 0.0
808  endif
809 
810  ! Remap tracer
811  if (ntr>0) then
812  if (show_call_tree) call calltree_waypoint("remapping tracers (remap_all_state_vars)")
813  !$OMP parallel do default(shared) private(h1,h2,u_column,Tr)
814  do m=1,ntr ! For each tracer
815  tr => reg%Tr(m)
816  do j = g%jsc,g%jec ; do i = g%isc,g%iec ; if (g%mask2dT(i,j)>0.) then
817  ! Build the start and final grids
818  h1(:) = h_old(i,j,:)
819  h2(:) = h_new(i,j,:)
820  call remapping_core_h(cs_remapping, nz, h1, tr%t(i,j,:), nz, h2, &
821  u_column, h_neglect, h_neglect_edge)
822 
823  ! Intermediate steps for tendency of tracer concentration and tracer content.
824  if (present(dt)) then
825  if (tr%id_remap_conc > 0) then
826  do k=1,gv%ke
827  work_conc(i,j,k) = (u_column(k) - tr%t(i,j,k)) * idt
828  enddo
829  endif
830  if (tr%id_remap_cont > 0 .or. tr%id_remap_cont_2d > 0) then
831  do k=1,gv%ke
832  work_cont(i,j,k) = (u_column(k)*h2(k) - tr%t(i,j,k)*h1(k)) * idt
833  enddo
834  endif
835  endif
836  ! update tracer concentration
837  tr%t(i,j,:) = u_column(:)
838  endif ; enddo ; enddo
839 
840  ! tendency diagnostics.
841  if (present(dt)) then
842  if (tr%id_remap_conc > 0) then
843  call post_data(tr%id_remap_conc, work_conc, cs_ale%diag)
844  endif
845  if (tr%id_remap_cont > 0) then
846  call post_data(tr%id_remap_cont, work_cont, cs_ale%diag)
847  endif
848  if (tr%id_remap_cont_2d > 0) then
849  do j = g%jsc,g%jec ; do i = g%isc,g%iec
850  work_2d(i,j) = 0.0
851  do k = 1,gv%ke
852  work_2d(i,j) = work_2d(i,j) + work_cont(i,j,k)
853  enddo
854  enddo ; enddo
855  call post_data(tr%id_remap_cont_2d, work_2d, cs_ale%diag)
856  endif
857  endif
858  enddo ! m=1,ntr
859 
860  endif ! endif for ntr > 0
861 
862  if (show_call_tree) call calltree_waypoint("tracers remapped (remap_all_state_vars)")
863 
864  ! Remap u velocity component
865  if ( present(u) ) then
866  !$OMP parallel do default(shared) private(h1,h2,dx,u_column)
867  do j = g%jsc,g%jec ; do i = g%iscB,g%iecB ; if (g%mask2dCu(i,j)>0.) then
868  ! Build the start and final grids
869  h1(:) = 0.5 * ( h_old(i,j,:) + h_old(i+1,j,:) )
870  if (cs_ale%remap_uv_using_old_alg) then
871  dx(:) = 0.5 * ( dxinterface(i,j,:) + dxinterface(i+1,j,:) )
872  do k = 1, nz
873  h2(k) = max( 0., h1(k) + ( dx(k+1) - dx(k) ) )
874  enddo
875  else
876  h2(:) = 0.5 * ( h_new(i,j,:) + h_new(i+1,j,:) )
877  endif
878  if (associated(obc)) then
879  if (obc%segnum_u(i,j) .ne. 0) then
880  if (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_e) then
881  h1(:) = h_old(i,j,:)
882  h2(:) = h_new(i,j,:)
883  else ! (OBC%segment(n)%direction == OBC_DIRECTION_W)
884  h1(:) = h_old(i+1,j,:)
885  h2(:) = h_new(i+1,j,:)
886  endif
887  endif
888  endif
889  call remapping_core_h(cs_remapping, nz, h1, u(i,j,:), nz, h2, &
890  u_column, h_neglect, h_neglect_edge)
891  u(i,j,:) = u_column(:)
892  endif ; enddo ; enddo
893  endif
894 
895  if (show_call_tree) call calltree_waypoint("u remapped (remap_all_state_vars)")
896 
897  ! Remap v velocity component
898  if ( present(v) ) then
899  !$OMP parallel do default(shared) private(h1,h2,dx,u_column)
900  do j = g%jscB,g%jecB ; do i = g%isc,g%iec ; if (g%mask2dCv(i,j)>0.) then
901  ! Build the start and final grids
902  h1(:) = 0.5 * ( h_old(i,j,:) + h_old(i,j+1,:) )
903  if (cs_ale%remap_uv_using_old_alg) then
904  dx(:) = 0.5 * ( dxinterface(i,j,:) + dxinterface(i,j+1,:) )
905  do k = 1, nz
906  h2(k) = max( 0., h1(k) + ( dx(k+1) - dx(k) ) )
907  enddo
908  else
909  h2(:) = 0.5 * ( h_new(i,j,:) + h_new(i,j+1,:) )
910  endif
911  if (associated(obc)) then
912  if (obc%segnum_v(i,j) .ne. 0) then
913  if (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_n) then
914  h1(:) = h_old(i,j,:)
915  h2(:) = h_new(i,j,:)
916  else ! (OBC%segment(n)%direction == OBC_DIRECTION_S)
917  h1(:) = h_old(i,j+1,:)
918  h2(:) = h_new(i,j+1,:)
919  endif
920  endif
921  endif
922  call remapping_core_h(cs_remapping, nz, h1, v(i,j,:), nz, h2, &
923  u_column, h_neglect, h_neglect_edge)
924  v(i,j,:) = u_column(:)
925  endif ; enddo ; enddo
926  endif
927 
928  if (cs_ale%id_vert_remap_h > 0) call post_data(cs_ale%id_vert_remap_h, h_old, cs_ale%diag)
929  if ((cs_ale%id_vert_remap_h_tendency > 0) .and. present(dt)) then
930  do k = 1, nz ; do j = g%jsc,g%jec ; do i = g%isc,g%iec
931  work_cont(i,j,k) = (h_new(i,j,k) - h_old(i,j,k))*idt
932  enddo ; enddo ; enddo
933  call post_data(cs_ale%id_vert_remap_h_tendency, work_cont, cs_ale%diag)
934  endif
935  if (show_call_tree) call calltree_waypoint("v remapped (remap_all_state_vars)")
936  if (show_call_tree) call calltree_leave("remap_all_state_vars()")
937 
938 end subroutine remap_all_state_vars
939 
940 
941 !> Remaps a single scalar between grids described by thicknesses h_src and h_dst.
942 !! h_dst must be dimensioned as a model array with GV%ke layers while h_src can
943 !! have an arbitrary number of layers specified by nk_src.
944 subroutine ale_remap_scalar(CS, G, GV, nk_src, h_src, s_src, h_dst, s_dst, all_cells, old_remap, answers_2018 )
945  type(remapping_cs), intent(in) :: cs !< Remapping control structure
946  type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
947  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
948  integer, intent(in) :: nk_src !< Number of levels on source grid
949  real, dimension(SZI_(G),SZJ_(G),nk_src), intent(in) :: h_src !< Level thickness of source grid
950  !! [H ~> m or kg-2]
951  real, dimension(SZI_(G),SZJ_(G),nk_src), intent(in) :: s_src !< Scalar on source grid
952  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)),intent(in) :: h_dst !< Level thickness of destination grid
953  !! [H ~> m or kg-2]
954  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)),intent(inout) :: s_dst !< Scalar on destination grid
955  logical, optional, intent(in) :: all_cells !< If false, only reconstruct for
956  !! non-vanished cells. Use all vanished
957  !! layers otherwise (default).
958  logical, optional, intent(in) :: old_remap !< If true, use the old "remapping_core_w"
959  !! method, otherwise use "remapping_core_h".
960  logical, optional, intent(in) :: answers_2018 !< If true, use the order of arithmetic
961  !! and expressions that recover the answers for
962  !! remapping from the end of 2018. Otherwise,
963  !! use more robust forms of the same expressions.
964  ! Local variables
965  integer :: i, j, k, n_points
966  real :: dx(gv%ke+1)
967  real :: h_neglect, h_neglect_edge
968  logical :: ignore_vanished_layers, use_remapping_core_w, use_2018_remap
969 
970  ignore_vanished_layers = .false.
971  if (present(all_cells)) ignore_vanished_layers = .not. all_cells
972  use_remapping_core_w = .false.
973  if (present(old_remap)) use_remapping_core_w = old_remap
974  n_points = nk_src
975  use_2018_remap = .true. ; if (present(answers_2018)) use_2018_remap = answers_2018
976 
977  if (.not.use_2018_remap) then
978  h_neglect = gv%H_subroundoff ; h_neglect_edge = gv%H_subroundoff
979  elseif (gv%Boussinesq) then
980  h_neglect = gv%m_to_H*1.0e-30 ; h_neglect_edge = gv%m_to_H*1.0e-10
981  else
982  h_neglect = gv%kg_m2_to_H*1.0e-30 ; h_neglect_edge = gv%kg_m2_to_H*1.0e-10
983  endif
984 
985  !$OMP parallel do default(shared) firstprivate(n_points,dx)
986  do j = g%jsc,g%jec ; do i = g%isc,g%iec
987  if (g%mask2dT(i,j) > 0.) then
988  if (ignore_vanished_layers) then
989  n_points = 0
990  do k = 1, nk_src
991  if (h_src(i,j,k)>0.) n_points = n_points + 1
992  enddo
993  s_dst(i,j,:) = 0.
994  endif
995  if (use_remapping_core_w) then
996  call dzfromh1h2( n_points, h_src(i,j,1:n_points), gv%ke, h_dst(i,j,:), dx )
997  call remapping_core_w(cs, n_points, h_src(i,j,1:n_points), s_src(i,j,1:n_points), &
998  gv%ke, dx, s_dst(i,j,:), h_neglect, h_neglect_edge)
999  else
1000  call remapping_core_h(cs, n_points, h_src(i,j,1:n_points), s_src(i,j,1:n_points), &
1001  gv%ke, h_dst(i,j,:), s_dst(i,j,:), h_neglect, h_neglect_edge)
1002  endif
1003  else
1004  s_dst(i,j,:) = 0.
1005  endif
1006  enddo ; enddo
1007 
1008 end subroutine ale_remap_scalar
1009 
1010 
1011 !> Calculate edge values (top and bottom of layer) for T and S consistent with a PLM reconstruction
1012 !! in the vertical direction. Boundary reconstructions are PCM unless bdry_extrap is true.
1013 subroutine ts_plm_edge_values( CS, S_t, S_b, T_t, T_b, G, GV, tv, h, bdry_extrap )
1014  type(ocean_grid_type), intent(in) :: g !< ocean grid structure
1015  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
1016  type(ale_cs), intent(inout) :: cs !< module control structure
1017  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1018  intent(inout) :: s_t !< Salinity at the top edge of each layer
1019  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1020  intent(inout) :: s_b !< Salinity at the bottom edge of each layer
1021  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1022  intent(inout) :: t_t !< Temperature at the top edge of each layer
1023  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1024  intent(inout) :: t_b !< Temperature at the bottom edge of each layer
1025  type(thermo_var_ptrs), intent(in) :: tv !< thermodynamics structure
1026  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1027  intent(in) :: h !< layer thickness [H ~> m or kg m-2]
1028  logical, intent(in) :: bdry_extrap !< If true, use high-order boundary
1029  !! extrapolation within boundary cells
1030 
1031  call ale_plm_edge_values( cs, g, gv, h, tv%S, bdry_extrap, s_t, s_b )
1032  call ale_plm_edge_values( cs, g, gv, h, tv%T, bdry_extrap, t_t, t_b )
1033 
1034 end subroutine ts_plm_edge_values
1035 
1036 !> Calculate edge values (top and bottom of layer) 3d scalar array.
1037 !! Boundary reconstructions are PCM unless bdry_extrap is true.
1038 subroutine ale_plm_edge_values( CS, G, GV, h, Q, bdry_extrap, Q_t, Q_b )
1039  type(ale_cs), intent(in) :: cs !< module control structure
1040  type(ocean_grid_type), intent(in) :: g !< ocean grid structure
1041  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
1042  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1043  intent(in) :: h !< layer thickness [H ~> m or kg m-2]
1044  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1045  intent(in) :: q !< 3d scalar array
1046  logical, intent(in) :: bdry_extrap !< If true, use high-order boundary
1047  !! extrapolation within boundary cells
1048  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1049  intent(inout) :: q_t !< Scalar at the top edge of each layer
1050  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1051  intent(inout) :: q_b !< Scalar at the bottom edge of each layer
1052  ! Local variables
1053  integer :: i, j, k
1054  real :: slp(gv%ke)
1055  real :: mslp
1056  real :: h_neglect
1057 
1058  if (.not.cs%answers_2018) then
1059  h_neglect = gv%H_subroundoff
1060  elseif (gv%Boussinesq) then
1061  h_neglect = gv%m_to_H*1.0e-30
1062  else
1063  h_neglect = gv%kg_m2_to_H*1.0e-30
1064  endif
1065 
1066  !$OMP parallel do default(shared) private(slp,mslp)
1067  do j = g%jsc-1,g%jec+1 ; do i = g%isc-1,g%iec+1
1068  slp(1) = 0.
1069  do k = 2, gv%ke-1
1070  slp(k) = plm_slope_wa(h(i,j,k-1), h(i,j,k), h(i,j,k+1), h_neglect, q(i,j,k-1), q(i,j,k), q(i,j,k+1))
1071  enddo
1072  slp(gv%ke) = 0.
1073 
1074  do k = 2, gv%ke-1
1075  mslp = plm_monotonized_slope(q(i,j,k-1), q(i,j,k), q(i,j,k+1), slp(k-1), slp(k), slp(k+1))
1076  q_t(i,j,k) = q(i,j,k) - 0.5 * mslp
1077  q_b(i,j,k) = q(i,j,k) + 0.5 * mslp
1078  enddo
1079  if (bdry_extrap) then
1080  mslp = - plm_extrapolate_slope(h(i,j,2), h(i,j,1), h_neglect, q(i,j,2), q(i,j,1))
1081  q_t(i,j,1) = q(i,j,1) - 0.5 * mslp
1082  q_b(i,j,1) = q(i,j,1) + 0.5 * mslp
1083  mslp = plm_extrapolate_slope(h(i,j,gv%ke-1), h(i,j,gv%ke), h_neglect, q(i,j,gv%ke-1), q(i,j,gv%ke))
1084  q_t(i,j,gv%ke) = q(i,j,gv%ke) - 0.5 * mslp
1085  q_b(i,j,gv%ke) = q(i,j,gv%ke) + 0.5 * mslp
1086  else
1087  q_t(i,j,1) = q(i,j,1)
1088  q_b(i,j,1) = q(i,j,1)
1089  q_t(i,j,gv%ke) = q(i,j,gv%ke)
1090  q_b(i,j,gv%ke) = q(i,j,gv%ke)
1091  endif
1092 
1093  enddo ; enddo
1094 
1095 end subroutine ale_plm_edge_values
1096 
1097 !> Calculate edge values (top and bottom of layer) for T and S consistent with a PPM reconstruction
1098 !! in the vertical direction. Boundary reconstructions are PCM unless bdry_extrap is true.
1099 subroutine ts_ppm_edge_values( CS, S_t, S_b, T_t, T_b, G, GV, tv, h, bdry_extrap )
1100  type(ocean_grid_type), intent(in) :: g !< ocean grid structure
1101  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
1102  type(ale_cs), intent(inout) :: cs !< module control structure
1103  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1104  intent(inout) :: s_t !< Salinity at the top edge of each layer
1105  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1106  intent(inout) :: s_b !< Salinity at the bottom edge of each layer
1107  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1108  intent(inout) :: t_t !< Temperature at the top edge of each layer
1109  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1110  intent(inout) :: t_b !< Temperature at the bottom edge of each layer
1111  type(thermo_var_ptrs), intent(in) :: tv !< thermodynamics structure
1112  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1113  intent(in) :: h !< layer thicknesses [H ~> m or kg m-2]
1114  logical, intent(in) :: bdry_extrap !< If true, use high-order boundary
1115  !! extrapolation within boundary cells
1116 
1117  ! Local variables
1118  integer :: i, j, k
1119  real :: htmp(gv%ke) ! A 1-d copy of h [H ~> m or kg m-2]
1120  real :: tmp(gv%ke) ! A 1-d copy of a column of temperature [degC] or salinity [ppt]
1121  real, dimension(CS%nk,2) :: &
1122  ppol_e ! Edge value of polynomial in [degC] or [ppt]
1123  real, dimension(CS%nk,3) :: &
1124  ppol_coefs ! Coefficients of polynomial, all in [degC] or [ppt]
1125  real :: h_neglect, h_neglect_edge ! Tiny thicknesses [H ~> m or kg m-2]
1126 
1127  if (.not.cs%answers_2018) then
1128  h_neglect = gv%H_subroundoff ; h_neglect_edge = gv%H_subroundoff
1129  elseif (gv%Boussinesq) then
1130  h_neglect = gv%m_to_H*1.0e-30 ; h_neglect_edge = gv%m_to_H*1.0e-10
1131  else
1132  h_neglect = gv%kg_m2_to_H*1.0e-30 ; h_neglect_edge = gv%kg_m2_to_H*1.0e-10
1133  endif
1134 
1135  ! Determine reconstruction within each column
1136  !$OMP parallel do default(shared) private(hTmp,tmp,ppol_E,ppol_coefs)
1137  do j = g%jsc-1,g%jec+1 ; do i = g%isc-1,g%iec+1
1138 
1139  ! Build current grid
1140  htmp(:) = h(i,j,:)
1141  tmp(:) = tv%S(i,j,:)
1142 
1143  ! Reconstruct salinity profile
1144  ppol_e(:,:) = 0.0
1145  ppol_coefs(:,:) = 0.0
1146  call edge_values_implicit_h4( gv%ke, htmp, tmp, ppol_e, h_neglect=h_neglect_edge, &
1147  answers_2018=cs%answers_2018 )
1148  call ppm_reconstruction( gv%ke, htmp, tmp, ppol_e, ppol_coefs, h_neglect, &
1149  answers_2018=cs%answers_2018 )
1150  if (bdry_extrap) &
1151  call ppm_boundary_extrapolation( gv%ke, htmp, tmp, ppol_e, ppol_coefs, h_neglect )
1152 
1153  do k = 1,gv%ke
1154  s_t(i,j,k) = ppol_e(k,1)
1155  s_b(i,j,k) = ppol_e(k,2)
1156  enddo
1157 
1158  ! Reconstruct temperature profile
1159  ppol_e(:,:) = 0.0
1160  ppol_coefs(:,:) = 0.0
1161  tmp(:) = tv%T(i,j,:)
1162  if (cs%answers_2018) then
1163  call edge_values_implicit_h4( gv%ke, htmp, tmp, ppol_e, h_neglect=1.0e-10*gv%m_to_H, &
1164  answers_2018=cs%answers_2018 )
1165  else
1166  call edge_values_implicit_h4( gv%ke, htmp, tmp, ppol_e, h_neglect=gv%H_subroundoff, &
1167  answers_2018=cs%answers_2018 )
1168  endif
1169  call ppm_reconstruction( gv%ke, htmp, tmp, ppol_e, ppol_coefs, h_neglect, &
1170  answers_2018=cs%answers_2018 )
1171  if (bdry_extrap) &
1172  call ppm_boundary_extrapolation(gv%ke, htmp, tmp, ppol_e, ppol_coefs, h_neglect )
1173 
1174  do k = 1,gv%ke
1175  t_t(i,j,k) = ppol_e(k,1)
1176  t_b(i,j,k) = ppol_e(k,2)
1177  enddo
1178 
1179  enddo ; enddo
1180 
1181 end subroutine ts_ppm_edge_values
1182 
1183 
1184 !> Initializes regridding for the main ALE algorithm
1185 subroutine ale_initregridding(GV, US, max_depth, param_file, mdl, regridCS)
1186  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
1187  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
1188  real, intent(in) :: max_depth !< The maximum depth of the ocean [Z ~> m].
1189  type(param_file_type), intent(in) :: param_file !< parameter file
1190  character(len=*), intent(in) :: mdl !< Name of calling module
1191  type(regridding_cs), intent(out) :: regridcs !< Regridding parameters and work arrays
1192  ! Local variables
1193  character(len=30) :: coord_mode
1194 
1195  call get_param(param_file, mdl, "REGRIDDING_COORDINATE_MODE", coord_mode, &
1196  "Coordinate mode for vertical regridding. "//&
1197  "Choose among the following possibilities: "//&
1198  trim(regriddingcoordinatemodedoc), &
1199  default=default_coordinate_mode, fail_if_missing=.true.)
1200 
1201  call initialize_regridding(regridcs, gv, us, max_depth, param_file, mdl, coord_mode, '', '')
1202 
1203 end subroutine ale_initregridding
1204 
1205 !> Query the target coordinate interfaces positions
1206 function ale_getcoordinate( CS )
1207  type(ale_cs), pointer :: cs !< module control structure
1208 
1209  real, dimension(CS%nk+1) :: ale_getcoordinate
1210  ale_getcoordinate(:) = getcoordinateinterfaces( cs%regridCS, undo_scaling=.true. )
1211 
1212 end function ale_getcoordinate
1213 
1214 
1215 !> Query the target coordinate units
1216 function ale_getcoordinateunits( CS )
1217  type(ale_cs), pointer :: cs !< module control structure
1218 
1219  character(len=20) :: ale_getcoordinateunits
1220 
1221  ale_getcoordinateunits = getcoordinateunits( cs%regridCS )
1222 
1223 end function ale_getcoordinateunits
1224 
1225 
1226 !> Returns true if initial conditions should be regridded and remapped
1227 logical function ale_remap_init_conds( CS )
1228  type(ale_cs), pointer :: cs !< module control structure
1229 
1230  ale_remap_init_conds = .false.
1231  if (associated(cs)) ale_remap_init_conds = cs%remap_after_initialization
1232 end function ale_remap_init_conds
1233 
1234 !> Updates the weights for time filtering the new grid generated in regridding
1235 subroutine ale_update_regrid_weights( dt, CS )
1236  real, intent(in) :: dt !< Time-step used between ALE calls [T ~> s]
1237  type(ale_cs), pointer :: cs !< ALE control structure
1238  ! Local variables
1239  real :: w ! An implicit weighting estimate.
1240 
1241  if (associated(cs)) then
1242  w = 0.0
1243  if (cs%regrid_time_scale > 0.0) then
1244  w = cs%regrid_time_scale / (cs%regrid_time_scale + dt)
1245  endif
1246  call set_regrid_params(cs%regridCS, old_grid_weight=w)
1247  endif
1248 
1249 end subroutine ale_update_regrid_weights
1250 
1251 !> Update the vertical grid type with ALE information.
1252 !! This subroutine sets information in the verticalGrid_type to be
1253 !! consistent with the use of ALE mode.
1254 subroutine ale_updateverticalgridtype(CS, GV)
1255  type(ale_cs), pointer :: cs !< ALE control structure
1256  type(verticalgrid_type), pointer :: gv !< vertical grid information
1257 
1258  integer :: nk
1259 
1260  nk = gv%ke
1261  gv%sInterface(1:nk+1) = getcoordinateinterfaces( cs%regridCS, undo_scaling=.true. )
1262  gv%sLayer(1:nk) = 0.5*( gv%sInterface(1:nk) + gv%sInterface(2:nk+1) )
1263  gv%zAxisUnits = getcoordinateunits( cs%regridCS )
1264  gv%zAxisLongName = getcoordinateshortname( cs%regridCS )
1265  gv%direction = -1 ! Because of ferret in z* mode. Need method to set
1266  ! as function of coordinae mode.
1267 
1268 end subroutine ale_updateverticalgridtype
1269 
1270 
1271 !> Write the vertical coordinate information into a file.
1272 !! This subroutine writes out a file containing any available data related
1273 !! to the vertical grid used by the MOM ocean model when in ALE mode.
1274 subroutine ale_writecoordinatefile( CS, GV, directory )
1275  type(ale_cs), pointer :: cs !< module control structure
1276  type(verticalgrid_type), intent(in) :: gv !< ocean vertical grid structure
1277  character(len=*), intent(in) :: directory !< directory for writing grid info
1278 
1279  character(len=240) :: filepath
1280  type(vardesc) :: vars(2)
1281  type(fieldtype) :: fields(2)
1282  integer :: unit
1283  real :: ds(gv%ke), dsi(gv%ke+1)
1284 
1285  filepath = trim(directory) // trim("Vertical_coordinate")
1286  ds(:) = getcoordinateresolution( cs%regridCS, undo_scaling=.true. )
1287  dsi(1) = 0.5*ds(1)
1288  dsi(2:gv%ke) = 0.5*( ds(1:gv%ke-1) + ds(2:gv%ke) )
1289  dsi(gv%ke+1) = 0.5*ds(gv%ke)
1290 
1291  vars(1) = var_desc('ds', getcoordinateunits( cs%regridCS ), &
1292  'Layer Coordinate Thickness','1','L','1')
1293  vars(2) = var_desc('ds_interface', getcoordinateunits( cs%regridCS ), &
1294  'Layer Center Coordinate Separation','1','i','1')
1295 
1296  call create_file(unit, trim(filepath), vars, 2, fields, single_file, gv=gv)
1297  call write_field(unit, fields(1), ds)
1298  call write_field(unit, fields(2), dsi)
1299  call close_file(unit)
1300 
1301 end subroutine ale_writecoordinatefile
1302 
1303 
1304 !> Set h to coordinate values for fixed coordinate systems
1305 subroutine ale_initthicknesstocoord( CS, G, GV, h )
1306  type(ale_cs), intent(inout) :: cs !< module control structure
1307  type(ocean_grid_type), intent(in) :: g !< module grid structure
1308  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
1309  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: h !< layer thickness [H ~> m or kg m-2]
1310 
1311  ! Local variables
1312  integer :: i, j, k
1313 
1314  do j = g%jsd,g%jed ; do i = g%isd,g%ied
1315  h(i,j,:) = gv%Z_to_H * getstaticthickness( cs%regridCS, 0., g%bathyT(i,j) )
1316  enddo ; enddo
1317 
1318 end subroutine ale_initthicknesstocoord
1319 
1320 end module mom_ale
ppm_functions
Provides functions used with the Piecewise-Parabolic-Method in the vertical ALE algorithm.
Definition: PPM_functions.F90:2
mom_diag_vkernels
Provides kernels for single-column interpolation, re-integration (re-mapping of integrated quantities...
Definition: MOM_diag_vkernels.F90:3
mom_regridding::regridding_cs
Regridding control structure.
Definition: MOM_regridding.F90:45
mom_verticalgrid
Provides a transparent vertical ocean grid type and supporting routines.
Definition: MOM_verticalGrid.F90:2
regrid_consts::state_dependent
Returns true if the coordinate is dependent on the state density, returns false otherwise.
Definition: regrid_consts.F90:44
mom_tracer_registry::tracer_type
The tracer type.
Definition: MOM_tracer_registry.F90:38
mom_diag_mediator
The subroutines here provide convenient wrappers to the fms diag_manager interfaces with additional d...
Definition: MOM_diag_mediator.F90:3
mom_variables::thermo_var_ptrs
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Definition: MOM_variables.F90:80
mom_string_functions
Handy functions for manipulating strings.
Definition: MOM_string_functions.F90:2
regrid_consts::coordinateunits
Returns a string with the coordinate units associated with the coordinate mode.
Definition: regrid_consts.F90:38
mom_eos
Provides subroutines for quantities specific to the equation of state.
Definition: MOM_EOS.F90:2
mom_remapping::remapping_cs
Container for remapping parameters.
Definition: MOM_remapping.F90:24
mom_tracer_registry
This module contains the tracer_registry_type and the subroutines that handle registration of tracers...
Definition: MOM_tracer_registry.F90:5
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
regrid_edge_values
Edge value estimation for high-order resconstruction.
Definition: regrid_edge_values.F90:2
mom_io
This module contains I/O framework code.
Definition: MOM_io.F90:2
mom_unit_scaling::unit_scale_type
Describes various unit conversion factors.
Definition: MOM_unit_scaling.F90:14
regrid_consts
Contains constants for interpreting input parameters that control regridding.
Definition: regrid_consts.F90:2
mom_remapping
Provides column-wise vertical remapping functions.
Definition: MOM_remapping.F90:2
mom_diag_mediator::post_data
Make a diagnostic available for averaging or output.
Definition: MOM_diag_mediator.F90:70
mom_verticalgrid::verticalgrid_type
Describes the vertical ocean grid, including unit conversion factors.
Definition: MOM_verticalGrid.F90:24
mom_domains
Describes the decomposed MOM domain and has routines for communications across PEs.
Definition: MOM_domains.F90:2
mom_ale
This module contains the main regridding routines.
Definition: MOM_ALE.F90:9
mom_variables
Provides transparent structures with groups of MOM6 variables and supporting routines.
Definition: MOM_variables.F90:2
mom_open_boundary
Controls where open boundary conditions are applied.
Definition: MOM_open_boundary.F90:2
mom_file_parser
The MOM6 facility to parse input files for runtime parameters.
Definition: MOM_file_parser.F90:2
mom_ale::ale_cs
ALE control structure.
Definition: MOM_ALE.F90:63
mom_tracer_registry::tracer_registry_type
Type to carry basic tracer information.
Definition: MOM_tracer_registry.F90:138
mom_interface_heights::find_eta
Calculates the heights of sruface or all interfaces from layer thicknesses.
Definition: MOM_interface_heights.F90:21
mom_open_boundary::ocean_obc_type
Open-boundary data.
Definition: MOM_open_boundary.F90:218
mom_unit_scaling
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Definition: MOM_unit_scaling.F90:2
mom_debugging
Provides checksumming functions for debugging.
Definition: MOM_debugging.F90:7
mom_io::vardesc
Type for describing a variable, typically a tracer.
Definition: MOM_io.F90:53
mom_regridding
Generates vertical grids as part of the ALE algorithm.
Definition: MOM_regridding.F90:2
mom_file_parser::log_param
An overloaded interface to log the values of various types of parameters.
Definition: MOM_file_parser.F90:96
mom_domains::create_group_pass
Set up a group of halo updates.
Definition: MOM_domains.F90:84
mom_error_handler
Routines for error handling and I/O management.
Definition: MOM_error_handler.F90:2
mom_interface_heights
Functions for calculating interface heights, including free surface height.
Definition: MOM_interface_heights.F90:2
plm_functions
Piecewise linear reconstruction functions.
Definition: PLM_functions.F90:2
mom_diag_mediator::diag_ctrl
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Definition: MOM_diag_mediator.F90:240
mom_eos::calculate_density
Calculates density of sea water from T, S and P.
Definition: MOM_EOS.F90:68