12 implicit none ;
private 14 #include <MOM_memory.h> 25 sfc_flux, btm_flux, btm_reservoir, sink_rate, convert_flux_in)
28 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)),
intent(in) :: h_old
29 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)),
intent(in) :: ea
30 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)),
intent(in) :: eb
31 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)),
intent(inout) :: tr
32 real,
intent(in) :: dt
33 real,
dimension(SZI_(G),SZJ_(G)),
optional,
intent(in) :: sfc_flux
34 real,
dimension(SZI_(G),SZJ_(G)),
optional,
intent(in) :: btm_flux
36 real,
dimension(SZI_(G),SZJ_(G)),
optional,
intent(inout) :: btm_reservoir
37 real,
optional,
intent(in) :: sink_rate
38 logical,
optional,
intent(in) :: convert_flux_in
41 real,
dimension(SZI_(G),SZJ_(G)) :: &
46 real,
dimension(SZI_(G)) :: &
49 real :: c1(szi_(g),szk_(gv))
50 real :: h_minus_dsink(szi_(g),szk_(gv))
53 real :: sink(szi_(g),szk_(gv)+1)
61 logical :: convert_flux = .true.
64 integer :: i, j, k, is, ie, js, je, nz
65 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
67 if (
present(convert_flux_in)) convert_flux = convert_flux_in
68 h_neglect = gv%H_subroundoff
70 if (
present(sink_rate)) sink_dist = (dt*sink_rate) * gv%m_to_H
76 do j=js,je;
do i=is,ie ; sfc_src(i,j) = 0.0 ; btm_src(i,j) = 0.0 ; enddo;
enddo 77 if (
present(sfc_flux))
then 80 do j = js, je;
do i = is,ie
81 sfc_src(i,j) = (sfc_flux(i,j)*dt) * gv%kg_m2_to_H
85 do j = js, je;
do i = is,ie
86 sfc_src(i,j) = sfc_flux(i,j)
90 if (
present(btm_flux))
then 93 do j = js, je;
do i = is,ie
94 btm_src(i,j) = (btm_flux(i,j)*dt) * gv%kg_m2_to_H
98 do j = js, je;
do i = is,ie
99 btm_src(i,j) = btm_flux(i,j)
104 if (
present(sink_rate))
then 111 if (
present(btm_reservoir))
then 112 do i=is,ie ; sink(i,nz+1) = sink_dist ;
enddo 113 do k=2,nz ;
do i=is,ie
114 sink(i,k) = sink_dist ; h_minus_dsink(i,k) = h_old(i,j,k)
117 do i=is,ie ; sink(i,nz+1) = 0.0 ;
enddo 119 do k=nz,2,-1 ;
do i=is,ie
120 if (sink(i,k+1) >= sink_dist)
then 121 sink(i,k) = sink_dist
122 h_minus_dsink(i,k) = h_old(i,j,k) + (sink(i,k+1) - sink(i,k))
123 elseif (sink(i,k+1) + h_old(i,j,k) < sink_dist)
then 124 sink(i,k) = sink(i,k+1) + h_old(i,j,k)
125 h_minus_dsink(i,k) = 0.0
127 sink(i,k) = sink_dist
128 h_minus_dsink(i,k) = (h_old(i,j,k) + sink(i,k+1)) - sink(i,k)
133 sink(i,1) = 0.0 ; h_minus_dsink(i,1) = (h_old(i,j,1) + sink(i,2))
137 do i=is,ie ;
if (g%mask2dT(i,j) > 0.5)
then 138 b_denom_1 = h_minus_dsink(i,1) + ea(i,j,1) + h_neglect
139 b1(i) = 1.0 / (b_denom_1 + eb(i,j,1))
140 d1(i) = b_denom_1 * b1(i)
141 h_tr = h_old(i,j,1) + h_neglect
142 tr(i,j,1) = (b1(i)*h_tr)*tr(i,j,1) + sfc_src(i,j)
144 do k=2,nz-1 ;
do i=is,ie ;
if (g%mask2dT(i,j) > 0.5)
then 145 c1(i,k) = eb(i,j,k-1) * b1(i)
146 b_denom_1 = h_minus_dsink(i,k) + d1(i) * (ea(i,j,k) + sink(i,k)) + &
148 b1(i) = 1.0 / (b_denom_1 + eb(i,j,k))
149 d1(i) = b_denom_1 * b1(i)
150 h_tr = h_old(i,j,k) + h_neglect
151 tr(i,j,k) = b1(i) * (h_tr * tr(i,j,k) + &
152 (ea(i,j,k) + sink(i,k)) * tr(i,j,k-1))
153 endif ;
enddo ;
enddo 154 do i=is,ie ;
if (g%mask2dT(i,j) > 0.5)
then 155 c1(i,nz) = eb(i,j,nz-1) * b1(i)
156 b_denom_1 = h_minus_dsink(i,nz) + d1(i) * (ea(i,j,nz) + sink(i,nz)) + &
158 b1(i) = 1.0 / (b_denom_1 + eb(i,j,nz))
159 h_tr = h_old(i,j,nz) + h_neglect
160 tr(i,j,nz) = b1(i) * ((h_tr * tr(i,j,nz) + btm_src(i,j)) + &
161 (ea(i,j,nz) + sink(i,nz)) * tr(i,j,nz-1))
163 if (
present(btm_reservoir))
then ;
do i=is,ie ;
if (g%mask2dT(i,j)>0.5)
then 164 btm_reservoir(i,j) = btm_reservoir(i,j) + &
165 (sink(i,nz+1)*tr(i,j,nz)) * gv%H_to_kg_m2
166 endif ;
enddo ;
endif 168 do k=nz-1,1,-1 ;
do i=is,ie ;
if (g%mask2dT(i,j) > 0.5)
then 169 tr(i,j,k) = tr(i,j,k) + c1(i,k+1)*tr(i,j,k+1)
170 endif ;
enddo ;
enddo 175 do i=is,ie ;
if (g%mask2dT(i,j) > -0.5)
then 176 h_tr = h_old(i,j,1) + h_neglect
177 b_denom_1 = h_tr + ea(i,j,1)
178 b1(i) = 1.0 / (b_denom_1 + eb(i,j,1))
180 tr(i,j,1) = (b1(i)*h_tr)*tr(i,j,1) + sfc_src(i,j)
183 do k=2,nz-1 ;
do i=is,ie ;
if (g%mask2dT(i,j) > -0.5)
then 184 c1(i,k) = eb(i,j,k-1) * b1(i)
185 h_tr = h_old(i,j,k) + h_neglect
186 b_denom_1 = h_tr + d1(i) * ea(i,j,k)
187 b1(i) = 1.0 / (b_denom_1 + eb(i,j,k))
188 d1(i) = b_denom_1 * b1(i)
189 tr(i,j,k) = b1(i) * (h_tr * tr(i,j,k) + ea(i,j,k) * tr(i,j,k-1))
190 endif ;
enddo ;
enddo 191 do i=is,ie ;
if (g%mask2dT(i,j) > -0.5)
then 192 c1(i,nz) = eb(i,j,nz-1) * b1(i)
193 h_tr = h_old(i,j,nz) + h_neglect
194 b_denom_1 = h_tr + d1(i)*ea(i,j,nz)
195 b1(i) = 1.0 / ( b_denom_1 + eb(i,j,nz))
196 tr(i,j,nz) = b1(i) * (( h_tr * tr(i,j,nz) + btm_src(i,j)) + &
197 ea(i,j,nz) * tr(i,j,nz-1))
199 do k=nz-1,1,-1 ;
do i=is,ie ;
if (g%mask2dT(i,j) > -0.5)
then 200 tr(i,j,k) = tr(i,j,k) + c1(i,k+1)*tr(i,j,k+1)
201 endif ;
enddo ;
enddo 213 in_flux_optional, out_flux_optional, update_h_opt)
215 type(ocean_grid_type),
intent(in ) :: G
216 type(verticalgrid_type),
intent(in ) :: GV
217 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: Tr
218 real,
intent(in ) :: dt
219 type(forcing),
intent(in ) :: fluxes
220 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h
221 real,
intent(in ) :: evap_CFL_limit
222 real,
intent(in ) :: minimum_forcing_depth
223 real,
dimension(SZI_(G),SZJ_(G)),
optional,
intent(in ) :: in_flux_optional
225 real,
dimension(SZI_(G),SZJ_(G)),
optional,
intent(in) :: out_flux_optional
228 logical,
optional,
intent(in) :: update_h_opt
230 integer,
parameter :: maxGroundings = 5
231 integer :: numberOfGroundings, iGround(maxgroundings), jGround(maxgroundings)
232 real :: H_limit_fluxes, IforcingDepthScale, Idt
233 real :: dThickness, dTracer
234 real :: fractionOfForcing, hOld, Ithickness
235 real :: RivermixConst
236 real,
dimension(SZI_(G)) :: &
241 real,
dimension(SZI_(G), SZK_(G)) :: h2d, Tr2d
242 real,
dimension(SZI_(G),SZJ_(G)) :: in_flux
244 real,
dimension(SZI_(G),SZJ_(G)) :: out_flux
246 real,
dimension(SZI_(G)) :: in_flux_1d, out_flux_1d
247 real :: hGrounding(maxgroundings)
250 integer :: i, j, is, ie, js, je, k, nz, n, nsw
251 character(len=45) :: mesg
253 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
258 in_flux(:,:) = 0.0 ; out_flux(:,:) = 0.0
259 if(
present(in_flux_optional))
then 260 do j=js,je ;
do i=is,ie
261 in_flux(i,j) = in_flux_optional(i,j)
264 if(
present(out_flux_optional))
then 265 do j=js,je ;
do i=is,ie
266 out_flux(i,j) = out_flux_optional(i,j)
270 if (
present(update_h_opt))
then 271 update_h = update_h_opt
277 numberofgroundings = 0
292 do k=1,nz ;
do i=is,ie
294 tr2d(i,k) = tr(i,j,k)
298 in_flux_1d(i) = in_flux(i,j)
299 out_flux_1d(i) = out_flux(i,j)
311 netmassout(i) = fluxes%netMassOut(i,j)
312 netmassin(i) = fluxes%netMassIn(i,j)
319 if (g%mask2dT(i,j)>0.)
then 325 dthickness = netmassin(i)
330 netmassin(i) = netmassin(i) - dthickness
331 dtracer = dtracer + in_flux_1d(i)
336 h2d(i,k) = h2d(i,k) + dthickness
337 if (h2d(i,k) > 0.0)
then 338 ithickness = 1.0/h2d(i,k)
340 if (dthickness /= 0. .or. dtracer /= 0.) tr2d(i,k) = (hold*tr2d(i,k)+ dtracer)*ithickness
351 iforcingdepthscale = 1. / max(gv%H_subroundoff, minimum_forcing_depth*gv%m_to_H - netmassout(i) )
353 fractionofforcing = min(1.0, h2d(i,k)*iforcingdepthscale)
358 if (-fractionofforcing*netmassout(i) > evap_cfl_limit*h2d(i,k))
then 359 fractionofforcing = -evap_cfl_limit*h2d(i,k)/netmassout(i)
363 dthickness = max( fractionofforcing*netmassout(i), -h2d(i,k) )
365 dtracer = fractionofforcing*out_flux_1d(i)
369 netmassout(i) = netmassout(i) - dthickness
370 out_flux_1d(i) = out_flux_1d(i) - dtracer
374 h2d(i,k) = h2d(i,k) + dthickness
375 if (h2d(i,k) > 0.)
then 376 ithickness = 1.0/h2d(i,k)
377 tr2d(i,k) = (hold*tr2d(i,k) + dtracer)*ithickness
385 if (abs(in_flux_1d(i))+abs(out_flux_1d(i)) /= 0.0)
then 387 numberofgroundings = numberofgroundings +1
388 if (numberofgroundings<=maxgroundings)
then 389 iground(numberofgroundings) = i
390 jground(numberofgroundings) = j
391 hgrounding(numberofgroundings) = abs(in_flux_1d(i))+abs(out_flux_1d(i))
399 do k=1,nz ;
do i=is,ie
400 tr(i,j,k) = tr2d(i,k)
404 do k=1,nz ;
do i=is,ie
411 if (numberofgroundings>0)
then 412 do i = 1, min(numberofgroundings, maxgroundings)
413 write(mesg(1:45),
'(3es15.3)') g%geoLonT( iground(i), jground(i) ), &
414 g%geoLatT( iground(i), jground(i)) , hgrounding(i)
415 call mom_error(warning,
"MOM_tracer_vertical.F90, applyTracerBoundaryFluxesInOut(): "//&
416 "Tracer created. x,y,dh= "//trim(mesg), all_print=.true.)
419 if (numberofgroundings - maxgroundings > 0)
then 420 write(mesg,
'(i4)') numberofgroundings - maxgroundings
421 call mom_error(warning,
"MOM_tracer_vertical.F90, applyTracerBoundaryFluxesInOut(): "//&
422 trim(mesg) //
" groundings remaining")
This module implements boundary forcing for MOM6.
Ocean grid type. See mom_grid for details.
Provides the ocean grid type.
subroutine, public applytracerboundaryfluxesinout(G, GV, Tr, dt, fluxes, h, evap_CFL_limit, minimum_forcing_depth, in_flux_optional, out_flux_optional, update_h_opt)
This routine is modeled after applyBoundaryFluxesInOut in MOM_diabatic_aux.F90 NOTE: Please note that...
This module contains routines that implement physical fluxes of tracers (e.g. due to surface fluxes o...
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
subroutine, public tracer_vertdiff(h_old, ea, eb, dt, tr, G, GV, sfc_flux, btm_flux, btm_reservoir, sink_rate, convert_flux_in)
This subroutine solves a tridiagonal equation for the final tracer concentrations after the dual-entr...
subroutine, public mom_error(level, message, all_print)