MOM_boundary_update.F90
1! This file is part of MOM6, the Modular Ocean Model version 6.
2! See the LICENSE file for licensing information.
3! SPDX-License-Identifier: Apache-2.0
4
5!> Controls where open boundary conditions are applied
6module mom_boundary_update
7
8use mom_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end, clock_routine
9use mom_diag_mediator, only : time_type
10use mom_error_handler, only : mom_mesg, mom_error, fatal, warning
11use mom_file_parser, only : get_param, log_version, param_file_type, log_param
12use mom_grid, only : ocean_grid_type
13use mom_dyn_horgrid, only : dyn_horgrid_type
14use mom_open_boundary, only : ocean_obc_type, update_obc_segment_data, chksum_obc_segments
15use mom_open_boundary, only : read_obc_segment_data
16use mom_open_boundary, only : obc_registry_type, file_obc_cs
17use mom_open_boundary, only : register_file_obc, file_obc_end
18use mom_unit_scaling, only : unit_scale_type
19use mom_tracer_registry, only : tracer_registry_type
20use mom_variables, only : thermo_var_ptrs
21use mom_verticalgrid, only : verticalgrid_type
22use dome_initialization, only : register_dome_obc
23use tidal_bay_initialization, only : tidal_bay_set_obc_data, register_tidal_bay_obc
24use tidal_bay_initialization, only : tidal_bay_obc_cs
25use kelvin_initialization, only : kelvin_set_obc_data, register_kelvin_obc
26use kelvin_initialization, only : kelvin_obc_end, kelvin_obc_cs
27use shelfwave_initialization, only : shelfwave_set_obc_data, register_shelfwave_obc
28use shelfwave_initialization, only : shelfwave_obc_end, shelfwave_obc_cs
30use dyed_channel_initialization, only : dyed_channel_obc_end, dyed_channel_obc_cs
31
32implicit none ; private
33
34#include <MOM_memory.h>
35
36public call_obc_register, obc_register_end
37public update_obc_data
38
39!> The control structure for the MOM_boundary_update module
40type, public :: update_obc_cs ; private
41 logical :: use_files = .false. !< If true, use external files for the open boundary.
42 logical :: use_kelvin = .false. !< If true, use the Kelvin wave open boundary.
43 logical :: use_tidal_bay = .false. !< If true, use the tidal_bay open boundary.
44 logical :: use_shelfwave = .false. !< If true, use the shelfwave open boundary.
45 logical :: use_dyed_channel = .false. !< If true, use the dyed channel open boundary.
46 logical :: debug_obcs = .false. !< If true, write verbose OBC values for debugging purposes.
47 logical :: value_update_bug = .true. !< If true, recover a bug that OBC segment data does not
48 !! update if all segments use 'value' and none uses 'file'.
49 integer :: nk_obc_debug = 0 !< The number of layers of OBC segment data to write out
50 !! in full when DEBUG_OBCS is true.
51 !>@{ Pointers to the control structures for named OBC specifications
52 type(file_obc_cs), pointer :: file_obc_csp => null()
53 type(kelvin_obc_cs), pointer :: kelvin_obc_csp => null()
54 type(tidal_bay_obc_cs) :: tidal_bay_obc
55 type(shelfwave_obc_cs), pointer :: shelfwave_obc_csp => null()
56 type(dyed_channel_obc_cs), pointer :: dyed_channel_obc_csp => null()
57 !>@}
58end type update_obc_cs
59
60integer :: id_clock_pass !< A CPU time clock ID
61
62! character(len=40) :: mdl = "MOM_boundary_update" ! This module's name.
63
64contains
65
66!> The following subroutines and associated definitions provide the
67!! machinery to register and call the subroutines that initialize
68!! open boundary conditions.
69subroutine call_obc_register(G, GV, US, param_file, CS, OBC, tr_Reg)
70 type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
71 type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
72 type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
73 type(param_file_type), intent(in) :: param_file !< Parameter file to parse
74 type(update_obc_cs), pointer :: cs !< Control structure for OBCs
75 type(ocean_obc_type), pointer :: obc !< Open boundary structure
76 type(tracer_registry_type), pointer :: tr_reg !< Tracer registry.
77
78 ! Local variables
79 logical :: debug
80 character(len=200) :: config
81 character(len=40) :: mdl = "MOM_boundary_update" ! This module's name.
82 ! This include declares and sets the variable "version".
83# include "version_variable.h"
84 if (associated(cs)) then
85 call mom_error(warning, "call_OBC_register called with an associated "// &
86 "control structure.")
87 return
88 else ; allocate(cs) ; endif
89
90 call log_version(param_file, mdl, version, "")
91
92 call get_param(param_file, mdl, "OBC_VALUE_UPDATE_BUG", cs%value_update_bug, &
93 "If true, recover a bug that OBC segment data does not update if all segments "//&
94 "use 'value' and none uses 'file'.", default=.true.)
95 call get_param(param_file, mdl, "USE_FILE_OBC", cs%use_files, &
96 "If true, use external files for the open boundary.", &
97 default=.false.)
98 call get_param(param_file, mdl, "USE_TIDAL_BAY_OBC", cs%use_tidal_bay, &
99 "If true, use the tidal_bay open boundary.", &
100 default=.false.)
101 call get_param(param_file, mdl, "USE_KELVIN_WAVE_OBC", cs%use_Kelvin, &
102 "If true, use the Kelvin wave open boundary.", &
103 default=.false.)
104 call get_param(param_file, mdl, "USE_SHELFWAVE_OBC", cs%use_shelfwave, &
105 "If true, use the shelfwave open boundary.", &
106 default=.false.)
107 call get_param(param_file, mdl, "USE_DYED_CHANNEL_OBC", cs%use_dyed_channel, &
108 "If true, use the dyed channel open boundary.", &
109 default=.false.)
110 call get_param(param_file, mdl, "OBC_USER_CONFIG", config, &
111 "A string that sets how the user code is invoked to set open boundary data: \n"//&
112 " DOME - specified inflow on northern boundary\n"//&
113 " dyed_channel - supercritical with dye on the inflow boundary\n"//&
114 " dyed_obcs - circle_obcs with dyes on the open boundaries\n"//&
115 " Kelvin - barotropic Kelvin wave forcing on the western boundary\n"//&
116 " shelfwave - Flather with shelf wave forcing on western boundary\n"//&
117 " supercritical - now only needed here for the allocations\n"//&
118 " tidal_bay - Flather with tidal forcing on eastern boundary\n"//&
119 " USER - user specified", default="none", do_not_log=.true.)
120 call get_param(param_file, mdl, "DEBUG", debug, &
121 "If true, write out verbose debugging data.", &
122 default=.false., debuggingparam=.true.)
123 call get_param(param_file, mdl, "DEBUG_OBCS", cs%debug_OBCs, &
124 "If true, write out verbose debugging data about OBCs.", &
125 default=.false., debuggingparam=.true.)
126 call get_param(param_file, mdl, "NK_OBC_DEBUG", cs%nk_OBC_debug, &
127 "The number of layers of OBC segment data to write out in full "//&
128 "when DEBUG_OBCS is true.", &
129 default=0, debuggingparam=.true., do_not_log=.not.cs%debug_OBCs)
130
131 if (cs%use_files) cs%use_files = &
132 register_file_obc(param_file, cs%file_OBC_CSp, us, &
133 obc%OBC_Reg)
134
135 if (trim(config) == "DOME") then
136 call register_dome_obc(param_file, us, obc, tr_reg)
137! elseif (trim(config) == "tidal_bay") then
138! elseif (trim(config) == "Kelvin") then
139! elseif (trim(config) == "shelfwave") then
140! elseif (trim(config) == "dyed_channel") then
141 endif
142
143 if (cs%use_tidal_bay) cs%use_tidal_bay = &
144 register_tidal_bay_obc(param_file, cs%tidal_bay_OBC, us, &
145 obc%OBC_Reg)
146 if (cs%use_Kelvin) cs%use_Kelvin = &
147 register_kelvin_obc(param_file, cs%Kelvin_OBC_CSp, us, &
148 obc%OBC_Reg)
149 if (cs%use_shelfwave) cs%use_shelfwave = &
150 register_shelfwave_obc(param_file, cs%shelfwave_OBC_CSp, g, us, &
151 obc%OBC_Reg)
152 if (cs%use_dyed_channel) cs%use_dyed_channel = &
153 register_dyed_channel_obc(param_file, cs%dyed_channel_OBC_CSp, us, &
154 obc%OBC_Reg)
155
156end subroutine call_obc_register
157
158!> Calls appropriate routine to update the open boundary conditions.
159subroutine update_obc_data(OBC, G, GV, US, tv, h, CS, Time)
160 type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
161 type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
162 type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
163 type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamics structure
164 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: h !< layer thicknesses [H ~> m or kg m-2]
165 type(ocean_obc_type), pointer :: obc !< Open boundary structure
166 type(update_obc_cs), pointer :: cs !< Control structure for OBCs
167 type(time_type), intent(in) :: time !< Model time
168
169 if (cs%use_tidal_bay) &
170 call tidal_bay_set_obc_data(obc, cs%tidal_bay_OBC, g, gv, us, h, time)
171 if (cs%use_Kelvin) &
172 call kelvin_set_obc_data(obc, cs%Kelvin_OBC_CSp, g, gv, us, h, time)
173 if (cs%use_shelfwave) &
174 call shelfwave_set_obc_data(obc, cs%shelfwave_OBC_CSp, g, gv, us, h, time)
175 if (cs%use_dyed_channel) &
176 call dyed_channel_update_flow(obc, cs%dyed_channel_OBC_CSp, g, gv, us, h, time)
177
178 if (.not. obc%user_BCs_set_globally) then
179 if (obc%any_needs_IO_for_data) call read_obc_segment_data(g, gv, us, obc, tv, h, time)
180 if ((.not.cs%value_update_bug) .or. (obc%any_needs_IO_for_data .or. obc%add_tide_constituents)) &
181 call update_obc_segment_data(g, gv, us, obc, h, time)
182 endif
183
184 if (cs%debug_OBCs) call chksum_obc_segments(obc, g, gv, us, cs%nk_OBC_debug)
185
186end subroutine update_obc_data
187
188!> Clean up the OBC registry.
189subroutine obc_register_end(CS)
190 type(update_obc_cs), pointer :: cs !< Control structure for OBCs
191
192 if (cs%use_files) call file_obc_end(cs%file_OBC_CSp)
193 if (cs%use_Kelvin) call kelvin_obc_end(cs%Kelvin_OBC_CSp)
194
195 if (associated(cs)) deallocate(cs)
196end subroutine obc_register_end
197
198!> \namespace mom_boundary_update
199!! This module updates the open boundary arrays when time-varying.
200!! It caused a circular dependency with the tidal_bay and other setups when in
201!! MOM_open_boundary.
202!!
203!! A small fragment of the grid is shown below:
204!!
205!! j+1 x ^ x ^ x At x: q, CoriolisBu
206!! j+1 > o > o > At ^: v, tauy
207!! j x ^ x ^ x At >: u, taux
208!! j > o > o > At o: h, bathyT, buoy, tr, T, S, Rml, ustar
209!! j-1 x ^ x ^ x
210!! i-1 i i+1 At x & ^:
211!! i i+1 At > & o:
212!!
213!! The boundaries always run through q grid points (x).
214
215end module mom_boundary_update