MOM6
MOM_tracer_diabatic.F90
1 !> This module contains routines that implement physical fluxes of tracers (e.g. due
2 !! to surface fluxes or mixing). These are intended to be called from call_tracer_column_fns
3 !! in the MOM_tracer_flow_control module.
5 
6 ! This file is part of MOM6. See LICENSE.md for the license.
7 
8 use mom_grid, only : ocean_grid_type
10 use mom_forcing_type, only : forcing
11 use mom_error_handler, only : mom_error, fatal, warning
12 
13 implicit none ; private
14 
15 #include <MOM_memory.h>
16 public tracer_vertdiff
17 public applytracerboundaryfluxesinout
18 
19 contains
20 
21 !> This subroutine solves a tridiagonal equation for the final tracer
22 !! concentrations after the dual-entrainments, and possibly sinking or surface
23 !! and bottom sources, are applied. The sinking is implemented with an
24 !! fully implicit upwind advection scheme.
25 subroutine tracer_vertdiff(h_old, ea, eb, dt, tr, G, GV, &
26  sfc_flux, btm_flux, btm_reservoir, sink_rate, convert_flux_in)
27  type(ocean_grid_type), intent(in) :: g !< ocean grid structure
28  type(verticalgrid_type), intent(in) :: gv !< ocean vertical grid structure
29  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h_old !< layer thickness before entrainment
30  !! [H ~> m or kg m-2]
31  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: ea !< amount of fluid entrained from the layer
32  !! above [H ~> m or kg m-2]
33  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: eb !< amount of fluid entrained from the layer
34  !! below [H ~> m or kg m-2]
35  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: tr !< tracer concentration in concentration units [CU]
36  real, intent(in) :: dt !< amount of time covered by this call [s]
37  real, dimension(SZI_(G),SZJ_(G)), optional,intent(in) :: sfc_flux !< surface flux of the tracer [CU kg m-2 s-1]
38  real, dimension(SZI_(G),SZJ_(G)), optional,intent(in) :: btm_flux !< The (negative upward) bottom flux of the
39  !! tracer [CU kg m-2 s-1]
40  real, dimension(SZI_(G),SZJ_(G)), optional,intent(inout) :: btm_reservoir !< amount of tracer in a bottom reservoir
41  !! [CU kg m-2]; formerly [CU m]
42  real, optional,intent(in) :: sink_rate !< rate at which the tracer sinks [m s-1]
43  logical, optional,intent(in) :: convert_flux_in !< True if the specified sfc_flux needs
44  !! to be integrated in time
45 
46  ! local variables
47  real :: sink_dist !< The distance the tracer sinks in a time step [H ~> m or kg m-2].
48  real, dimension(SZI_(G),SZJ_(G)) :: &
49  sfc_src, & !< The time-integrated surface source of the tracer [CU H ~> CU m or CU kg m-2].
50  btm_src !< The time-integrated bottom source of the tracer [CU H ~> CU m or CU kg m-2].
51  real, dimension(SZI_(G)) :: &
52  b1, & !< b1 is used by the tridiagonal solver [H-1 ~> m-1 or m2 kg-1].
53  d1 !! d1=1-c1 is used by the tridiagonal solver, nondimensional.
54  real :: c1(szi_(g),szk_(gv)) !< c1 is used by the tridiagonal solver [nondim].
55  real :: h_minus_dsink(szi_(g),szk_(gv)) !< The layer thickness minus the
56  !! difference in sinking rates across the layer [H ~> m or kg m-2].
57  !! By construction, 0 <= h_minus_dsink < h_work.
58  real :: sink(szi_(g),szk_(gv)+1) !< The tracer's sinking distances at the
59  !! interfaces, limited to prevent characteristics from
60  !! crossing within a single timestep [H ~> m or kg m-2].
61  real :: b_denom_1 !< The first term in the denominator of b1 [H ~> m or kg m-2].
62  real :: h_tr !< h_tr is h at tracer points with a h_neglect added to
63  !! ensure positive definiteness [H ~> m or kg m-2].
64  real :: h_neglect !< A thickness that is so small it is usually lost
65  !! in roundoff and can be neglected [H ~> m or kg m-2].
66  logical :: convert_flux = .true.
67 
68 
69  integer :: i, j, k, is, ie, js, je, nz
70  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
71 
72  if (nz == 1) then
73  call mom_error(warning, "MOM_tracer_diabatic.F90, tracer_vertdiff called "//&
74  "with only one vertical level")
75  return
76  endif
77 
78  if (present(convert_flux_in)) convert_flux = convert_flux_in
79  h_neglect = gv%H_subroundoff
80  sink_dist = 0.0
81  if (present(sink_rate)) sink_dist = (dt*sink_rate) * gv%m_to_H
82 !$OMP parallel default(none) shared(is,ie,js,je,sfc_src,btm_src,sfc_flux,dt,G,GV,btm_flux, &
83 !$OMP sink_rate,btm_reservoir,nz,sink_dist,ea, &
84 !$OMP h_old,convert_flux,h_neglect,eb,tr) &
85 !$OMP private(sink,h_minus_dsink,b_denom_1,b1,d1,h_tr,c1)
86 !$OMP do
87  do j=js,je; do i=is,ie ; sfc_src(i,j) = 0.0 ; btm_src(i,j) = 0.0 ; enddo ; enddo
88  if (present(sfc_flux)) then
89  if (convert_flux) then
90 !$OMP do
91  do j = js, je; do i = is,ie
92  sfc_src(i,j) = (sfc_flux(i,j)*dt) * gv%kg_m2_to_H
93  enddo ; enddo
94  else
95 !$OMP do
96  do j = js, je; do i = is,ie
97  sfc_src(i,j) = sfc_flux(i,j)
98  enddo ; enddo
99  endif
100  endif
101  if (present(btm_flux)) then
102  if (convert_flux) then
103 !$OMP do
104  do j = js, je; do i = is,ie
105  btm_src(i,j) = (btm_flux(i,j)*dt) * gv%kg_m2_to_H
106  enddo ; enddo
107  else
108 !$OMP do
109  do j = js, je; do i = is,ie
110  btm_src(i,j) = btm_flux(i,j)
111  enddo ; enddo
112  endif
113  endif
114 
115  if (present(sink_rate)) then
116 !$OMP do
117  do j=js,je
118  ! Find the sinking rates at all interfaces, limiting them if necesary
119  ! so that the characteristics do not cross within a timestep.
120  ! If a non-constant sinking rate were used, that would be incorprated
121  ! here.
122  if (present(btm_reservoir)) then
123  do i=is,ie ; sink(i,nz+1) = sink_dist ; enddo
124  do k=2,nz ; do i=is,ie
125  sink(i,k) = sink_dist ; h_minus_dsink(i,k) = h_old(i,j,k)
126  enddo ; enddo
127  else
128  do i=is,ie ; sink(i,nz+1) = 0.0 ; enddo
129  ! Find the limited sinking distance at the interfaces.
130  do k=nz,2,-1 ; do i=is,ie
131  if (sink(i,k+1) >= sink_dist) then
132  sink(i,k) = sink_dist
133  h_minus_dsink(i,k) = h_old(i,j,k) + (sink(i,k+1) - sink(i,k))
134  elseif (sink(i,k+1) + h_old(i,j,k) < sink_dist) then
135  sink(i,k) = sink(i,k+1) + h_old(i,j,k)
136  h_minus_dsink(i,k) = 0.0
137  else
138  sink(i,k) = sink_dist
139  h_minus_dsink(i,k) = (h_old(i,j,k) + sink(i,k+1)) - sink(i,k)
140  endif
141  enddo ; enddo
142  endif
143  do i=is,ie
144  sink(i,1) = 0.0 ; h_minus_dsink(i,1) = (h_old(i,j,1) + sink(i,2))
145  enddo
146 
147  ! Now solve the tridiagonal equation for the tracer concentrations.
148  do i=is,ie ; if (g%mask2dT(i,j) > 0.5) then
149  b_denom_1 = h_minus_dsink(i,1) + ea(i,j,1) + h_neglect
150  b1(i) = 1.0 / (b_denom_1 + eb(i,j,1))
151  d1(i) = b_denom_1 * b1(i)
152  h_tr = h_old(i,j,1) + h_neglect
153  tr(i,j,1) = (b1(i)*h_tr)*tr(i,j,1) + sfc_src(i,j)
154  endif ; enddo
155  do k=2,nz-1 ; do i=is,ie ; if (g%mask2dT(i,j) > 0.5) then
156  c1(i,k) = eb(i,j,k-1) * b1(i)
157  b_denom_1 = h_minus_dsink(i,k) + d1(i) * (ea(i,j,k) + sink(i,k)) + &
158  h_neglect
159  b1(i) = 1.0 / (b_denom_1 + eb(i,j,k))
160  d1(i) = b_denom_1 * b1(i)
161  h_tr = h_old(i,j,k) + h_neglect
162  tr(i,j,k) = b1(i) * (h_tr * tr(i,j,k) + &
163  (ea(i,j,k) + sink(i,k)) * tr(i,j,k-1))
164  endif ; enddo ; enddo
165  do i=is,ie ; if (g%mask2dT(i,j) > 0.5) then
166  c1(i,nz) = eb(i,j,nz-1) * b1(i)
167  b_denom_1 = h_minus_dsink(i,nz) + d1(i) * (ea(i,j,nz) + sink(i,nz)) + &
168  h_neglect
169  b1(i) = 1.0 / (b_denom_1 + eb(i,j,nz))
170  h_tr = h_old(i,j,nz) + h_neglect
171  tr(i,j,nz) = b1(i) * ((h_tr * tr(i,j,nz) + btm_src(i,j)) + &
172  (ea(i,j,nz) + sink(i,nz)) * tr(i,j,nz-1))
173  endif ; enddo
174  if (present(btm_reservoir)) then ; do i=is,ie ; if (g%mask2dT(i,j)>0.5) then
175  btm_reservoir(i,j) = btm_reservoir(i,j) + &
176  (sink(i,nz+1)*tr(i,j,nz)) * gv%H_to_kg_m2
177  endif ; enddo ; endif
178 
179  do k=nz-1,1,-1 ; do i=is,ie ; if (g%mask2dT(i,j) > 0.5) then
180  tr(i,j,k) = tr(i,j,k) + c1(i,k+1)*tr(i,j,k+1)
181  endif ; enddo ; enddo
182  enddo
183  else
184 !$OMP do
185  do j=js,je
186  do i=is,ie ; if (g%mask2dT(i,j) > -0.5) then
187  h_tr = h_old(i,j,1) + h_neglect
188  b_denom_1 = h_tr + ea(i,j,1)
189  b1(i) = 1.0 / (b_denom_1 + eb(i,j,1))
190  d1(i) = h_tr * b1(i)
191  tr(i,j,1) = (b1(i)*h_tr)*tr(i,j,1) + sfc_src(i,j)
192  endif
193  enddo
194  do k=2,nz-1 ; do i=is,ie ; if (g%mask2dT(i,j) > -0.5) then
195  c1(i,k) = eb(i,j,k-1) * b1(i)
196  h_tr = h_old(i,j,k) + h_neglect
197  b_denom_1 = h_tr + d1(i) * ea(i,j,k)
198  b1(i) = 1.0 / (b_denom_1 + eb(i,j,k))
199  d1(i) = b_denom_1 * b1(i)
200  tr(i,j,k) = b1(i) * (h_tr * tr(i,j,k) + ea(i,j,k) * tr(i,j,k-1))
201  endif ; enddo ; enddo
202  do i=is,ie ; if (g%mask2dT(i,j) > -0.5) then
203  c1(i,nz) = eb(i,j,nz-1) * b1(i)
204  h_tr = h_old(i,j,nz) + h_neglect
205  b_denom_1 = h_tr + d1(i)*ea(i,j,nz)
206  b1(i) = 1.0 / ( b_denom_1 + eb(i,j,nz))
207  tr(i,j,nz) = b1(i) * (( h_tr * tr(i,j,nz) + btm_src(i,j)) + &
208  ea(i,j,nz) * tr(i,j,nz-1))
209  endif ; enddo
210  do k=nz-1,1,-1 ; do i=is,ie ; if (g%mask2dT(i,j) > -0.5) then
211  tr(i,j,k) = tr(i,j,k) + c1(i,k+1)*tr(i,j,k+1)
212  endif ; enddo ; enddo
213  enddo
214  endif
215 
216 !$OMP end parallel
217 
218 end subroutine tracer_vertdiff
219 
220 !> This routine is modeled after applyBoundaryFluxesInOut in MOM_diabatic_aux.F90
221 !! NOTE: Please note that in this routine sfc_flux gets set to zero to ensure that the surface
222 !! flux of the tracer does not get applied again during a subsequent call to tracer_vertdif
223 subroutine applytracerboundaryfluxesinout(G, GV, Tr, dt, fluxes, h, evap_CFL_limit, minimum_forcing_depth, &
224  in_flux_optional, out_flux_optional, update_h_opt)
225 
226  type(ocean_grid_type), intent(in ) :: g !< Grid structure
227  type(verticalgrid_type), intent(in ) :: gv !< ocean vertical grid structure
228  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(inout) :: tr !< Tracer concentration on T-cell
229  real, intent(in ) :: dt !< Time-step over which forcing is applied [s]
230  type(forcing), intent(in ) :: fluxes !< Surface fluxes container
231  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(inout) :: h !< Layer thickness [H ~> m or kg m-2]
232  real, intent(in ) :: evap_cfl_limit !< Limit on the fraction of the
233  !! water that can be fluxed out of the top
234  !! layer in a timestep [nondim]
235  real, intent(in ) :: minimum_forcing_depth !< The smallest depth over
236  !! which fluxes can be applied [m]
237  real, dimension(SZI_(G),SZJ_(G)), optional, intent(in ) :: in_flux_optional !< The total time-integrated
238  !! amount of tracer that enters with freshwater
239  real, dimension(SZI_(G),SZJ_(G)), optional, intent(in) :: out_flux_optional !< The total time-integrated
240  !! amount of tracer that leaves with freshwater
241  logical, optional, intent(in) :: update_h_opt !< Optional flag to determine whether
242  !! h should be updated
243 
244  integer, parameter :: maxgroundings = 5
245  integer :: numberofgroundings, iground(maxgroundings), jground(maxgroundings)
246  real :: h_limit_fluxes, iforcingdepthscale, idt
247  real :: dthickness, dtracer
248  real :: fractionofforcing, hold, ithickness
249  real :: rivermixconst ! A constant used in implementing river mixing [Pa s].
250  real, dimension(SZI_(G)) :: &
251  netmassinout, & ! surface water fluxes [H ~> m or kg m-2] over time step
252  netmassin, & ! mass entering ocean surface [H ~> m or kg m-2] over a time step
253  netmassout ! mass leaving ocean surface [H ~> m or kg m-2] over a time step
254 
255  real, dimension(SZI_(G), SZK_(G)) :: h2d, tr2d
256  real, dimension(SZI_(G),SZJ_(G)) :: in_flux ! The total time-integrated amount of tracer!
257  ! that enters with freshwater
258  real, dimension(SZI_(G),SZJ_(G)) :: out_flux ! The total time-integrated amount of tracer!
259  ! that leaves with freshwater
260  real, dimension(SZI_(G)) :: in_flux_1d, out_flux_1d
261  real :: hgrounding(maxgroundings)
262  real :: tr_in
263  logical :: update_h
264  integer :: i, j, is, ie, js, je, k, nz, n, nsw
265  character(len=45) :: mesg
266 
267  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
268 
269  ! If no freshwater fluxes, nothing needs to be done in this routine
270  if ( (.not. associated(fluxes%netMassIn)) .or. (.not. associated(fluxes%netMassOut)) ) return
271 
272  in_flux(:,:) = 0.0 ; out_flux(:,:) = 0.0
273  if (present(in_flux_optional)) then
274  do j=js,je ; do i=is,ie
275  in_flux(i,j) = in_flux_optional(i,j)
276  enddo ; enddo
277  endif
278  if (present(out_flux_optional)) then
279  do j=js,je ; do i=is,ie
280  out_flux(i,j) = out_flux_optional(i,j)
281  enddo ; enddo
282  endif
283 
284  if (present(update_h_opt)) then
285  update_h = update_h_opt
286  else
287  update_h = .true.
288  endif
289 
290  idt = 1.0/dt
291  numberofgroundings = 0
292 
293 !$OMP parallel do default(none) shared(is,ie,js,je,nz,h,Tr,G,GV,fluxes,dt, &
294 !$OMP IforcingDepthScale,minimum_forcing_depth, &
295 !$OMP numberOfGroundings,iGround,jGround,update_h, &
296 !$OMP in_flux,out_flux,hGrounding,Idt,evap_CFL_limit) &
297 !$OMP private(h2d,Tr2d,netMassInOut,netMassOut, &
298 !$OMP in_flux_1d,out_flux_1d,fractionOfForcing, &
299 !$OMP dThickness,dTracer,hOld,Ithickness, &
300 !$OMP netMassIn, Tr_in)
301 
302  ! Work in vertical slices for efficiency
303  do j=js,je
304 
305  ! Copy state into 2D-slice arrays
306  do k=1,nz ; do i=is,ie
307  h2d(i,k) = h(i,j,k)
308  tr2d(i,k) = tr(i,j,k)
309  enddo ; enddo
310 
311  do i = is,ie
312  in_flux_1d(i) = in_flux(i,j)
313  out_flux_1d(i) = out_flux(i,j)
314  enddo
315  ! The surface forcing is contained in the fluxes type.
316  ! We aggregate the thermodynamic forcing for a time step into the following:
317  ! These should have been set and stored during a call to applyBoundaryFluxesInOut
318  ! netMassIn = net mass entering at ocean surface over a timestep
319  ! netMassOut = net mass leaving ocean surface [H ~> m or kg m-2] over a time step.
320  ! netMassOut < 0 means mass leaves ocean.
321 
322  ! Note here that the aggregateFW flag has already been taken care of in the call to
323  ! applyBoundaryFluxesInOut
324  do i=is,ie
325  netmassout(i) = fluxes%netMassOut(i,j)
326  netmassin(i) = fluxes%netMassIn(i,j)
327  enddo
328 
329  ! Apply the surface boundary fluxes in three steps:
330  ! A/ update concentration from mass entering the ocean
331  ! B/ update concentration from mass leaving ocean.
332  do i=is,ie
333  if (g%mask2dT(i,j)>0.) then
334 
335  ! A/ Update tracer due to incoming mass flux.
336  do k=1,1
337 
338  ! Change in state due to forcing
339  dthickness = netmassin(i) ! Since we are adding mass, we can use all of it
340  dtracer = 0.
341 
342  ! Update the forcing by the part to be consumed within the present k-layer.
343  ! If fractionOfForcing = 1, then updated netMassIn, netHeat, and netSalt vanish.
344  netmassin(i) = netmassin(i) - dthickness
345  dtracer = dtracer + in_flux_1d(i)
346  in_flux_1d(i) = 0.0
347 
348  ! Update state
349  hold = h2d(i,k) ! Keep original thickness in hand
350  h2d(i,k) = h2d(i,k) + dthickness ! New thickness
351  if (h2d(i,k) > 0.0) then
352  ithickness = 1.0/h2d(i,k) ! Inverse new thickness
353  ! The "if"s below avoid changing T/S by roundoff unnecessarily
354  if (dthickness /= 0. .or. dtracer /= 0.) tr2d(i,k) = (hold*tr2d(i,k)+ dtracer)*ithickness
355  endif
356 
357  enddo ! k=1,1
358 
359  ! B/ Update tracer from mass leaving ocean
360  do k=1,nz
361 
362  ! Place forcing into this layer if this layer has nontrivial thickness.
363  ! For layers thin relative to 1/IforcingDepthScale, then distribute
364  ! forcing into deeper layers.
365  iforcingdepthscale = 1. / max(gv%H_subroundoff, minimum_forcing_depth*gv%m_to_H - netmassout(i) )
366  ! fractionOfForcing = 1.0, unless h2d is less than IforcingDepthScale.
367  fractionofforcing = min(1.0, h2d(i,k)*iforcingdepthscale)
368 
369  ! In the case with (-1)*netMassOut*fractionOfForcing greater than cfl*h, we
370  ! limit the forcing applied to this cell, leaving the remaining forcing to
371  ! be distributed downwards.
372  if (-fractionofforcing*netmassout(i) > evap_cfl_limit*h2d(i,k)) then
373  fractionofforcing = -evap_cfl_limit*h2d(i,k)/netmassout(i)
374  endif
375 
376  ! Change in state due to forcing
377  dthickness = max( fractionofforcing*netmassout(i), -h2d(i,k) )
378  ! Note this is slightly different to how salt is currently treated
379  dtracer = fractionofforcing*out_flux_1d(i)
380 
381  ! Update the forcing by the part to be consumed within the present k-layer.
382  ! If fractionOfForcing = 1, then new netMassOut vanishes.
383  netmassout(i) = netmassout(i) - dthickness
384  out_flux_1d(i) = out_flux_1d(i) - dtracer
385 
386  ! Update state by the appropriate increment.
387  hold = h2d(i,k) ! Keep original thickness in hand
388  h2d(i,k) = h2d(i,k) + dthickness ! New thickness
389  if (h2d(i,k) > 0.) then
390  ithickness = 1.0/h2d(i,k) ! Inverse of new thickness
391  tr2d(i,k) = (hold*tr2d(i,k) + dtracer)*ithickness
392  endif
393 
394  enddo ! k
395 
396  endif
397 
398  ! If anything remains after the k-loop, then we have grounded out, which is a problem.
399  if (abs(in_flux_1d(i))+abs(out_flux_1d(i)) /= 0.0) then
400 !$OMP critical
401  numberofgroundings = numberofgroundings +1
402  if (numberofgroundings<=maxgroundings) then
403  iground(numberofgroundings) = i ! Record i,j location of event for
404  jground(numberofgroundings) = j ! warning message
405  hgrounding(numberofgroundings) = abs(in_flux_1d(i))+abs(out_flux_1d(i))
406  endif
407 !$OMP end critical
408  endif
409 
410  enddo ! i
411 
412  ! Step C/ copy updated tracer concentration from the 2d slice now back into model state.
413  do k=1,nz ; do i=is,ie
414  tr(i,j,k) = tr2d(i,k)
415  enddo ; enddo
416 
417  if (update_h) then
418  do k=1,nz ; do i=is,ie
419  h(i,j,k) = h2d(i,k)
420  enddo ; enddo
421  endif
422 
423  enddo ! j-loop finish
424 
425  if (numberofgroundings>0) then
426  do i = 1, min(numberofgroundings, maxgroundings)
427  write(mesg(1:45),'(3es15.3)') g%geoLonT( iground(i), jground(i) ), &
428  g%geoLatT( iground(i), jground(i)) , hgrounding(i)
429  call mom_error(warning, "MOM_tracer_diabatic.F90, applyTracerBoundaryFluxesInOut(): "//&
430  "Tracer created. x,y,dh= "//trim(mesg), all_print=.true.)
431  enddo
432 
433  if (numberofgroundings - maxgroundings > 0) then
434  write(mesg, '(i4)') numberofgroundings - maxgroundings
435  call mom_error(warning, "MOM_tracer_vertical.F90, applyTracerBoundaryFluxesInOut(): "//&
436  trim(mesg) // " groundings remaining")
437  endif
438  endif
439 
440 end subroutine applytracerboundaryfluxesinout
441 end module mom_tracer_diabatic
mom_verticalgrid
Provides a transparent vertical ocean grid type and supporting routines.
Definition: MOM_verticalGrid.F90:2
mom_tracer_diabatic
This module contains routines that implement physical fluxes of tracers (e.g. due to surface fluxes o...
Definition: MOM_tracer_diabatic.F90:4
mom_forcing_type
This module implements boundary forcing for MOM6.
Definition: MOM_forcing_type.F90:2
mom_verticalgrid::verticalgrid_type
Describes the vertical ocean grid, including unit conversion factors.
Definition: MOM_verticalGrid.F90:24
mom_grid
Provides the ocean grid type.
Definition: MOM_grid.F90:2
mom_forcing_type::forcing
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
Definition: MOM_forcing_type.F90:49
mom_error_handler
Routines for error handling and I/O management.
Definition: MOM_error_handler.F90:2
mom_grid::ocean_grid_type
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:25