Update the thickness, temperature, and salinity due to thermodynamic boundary forcing (contained in fluxes type) applied to h, tvT and tvS, and calculate the TKE implications of this heating.
814 type(diabatic_aux_cs),
pointer :: cs
815 type(ocean_grid_type),
intent(in) :: g
816 type(verticalgrid_type),
intent(in) :: gv
817 real,
intent(in) :: dt
818 type(forcing),
intent(inout) :: fluxes
819 type(optics_type),
pointer :: optics
820 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h
821 type(thermo_var_ptrs),
intent(inout) :: tv
823 logical,
intent(in) :: aggregate_fw_forcing
825 real,
intent(in) :: evap_cfl_limit
827 real,
intent(in) :: minimum_forcing_depth
829 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
optional,
intent(out) :: ctke
831 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
optional,
intent(out) :: dsv_dt
833 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
optional,
intent(out) :: dsv_ds
835 real,
dimension(SZI_(G),SZJ_(G)),
optional,
intent(out) :: skinbuoyflux
838 integer,
parameter :: maxgroundings = 5
839 integer :: numberofgroundings, iground(maxgroundings), jground(maxgroundings)
840 real :: h_limit_fluxes, iforcingdepthscale, idt
841 real :: dthickness, dtemp, dsalt
842 real :: fractionofforcing, hold, ithickness
843 real :: rivermixconst
844 real,
dimension(SZI_(G)) :: &
861 real,
dimension(SZI_(G), SZK_(G)) :: h2d, t2d
862 real,
dimension(SZI_(G), SZK_(G)) :: pen_tke_2d, dsv_dt_2d
863 real,
dimension(SZI_(G),SZK_(G)+1) :: netpen
864 real,
dimension(max(optics%nbands,1),SZI_(G)) :: pen_sw_bnd, pen_sw_bnd_rate
866 real,
dimension(max(optics%nbands,1),SZI_(G),SZK_(G)) :: opacityband
867 real :: hgrounding(maxgroundings)
868 real :: temp_in, salin_in
869 real :: i_g_earth, g_hconv2
871 logical :: calculate_energetics
872 logical :: calculate_buoyancy
873 integer :: i, j, is, ie, js, je, k, nz, n, nsw
874 integer :: start, npts
875 character(len=45) :: mesg
877 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
880 if (.not.
ASSOCIATED(fluxes%sw))
return 886 calculate_energetics = (
present(ctke) .and.
present(dsv_dt) .and.
present(dsv_ds))
887 calculate_buoyancy =
present(skinbuoyflux)
888 if (calculate_buoyancy) skinbuoyflux(:,:) = 0.0
889 i_g_earth = 1.0 / gv%g_Earth
890 g_hconv2 = gv%g_Earth * gv%H_to_kg_m2**2
892 if (
present(ctke)) ctke(:,:,:) = 0.0
893 if (calculate_buoyancy)
then 894 surfpressure(:) = 0.0
895 gorho = gv%g_Earth / gv%Rho0
896 start = 1 + g%isc - g%isd
897 npts = 1 + g%iec - g%isc
905 h_limit_fluxes = max(gv%Angstrom, 1.e-30*gv%m_to_H)
908 if (cs%id_createdH>0) cs%createdH(:,:) = 0.
909 numberofgroundings = 0
931 do k=1,nz ;
do i=is,ie
933 t2d(i,k) = tv%T(i,j,k)
935 opacityband(n,i,k) = (1.0 / gv%m_to_H)*optics%opacity_band(n,i,j,k)
939 if (calculate_energetics)
then 943 do i=is,ie ; pres(i) = 0.0 ;
enddo 946 d_pres(i) = gv%g_Earth * gv%H_to_kg_m2 * h2d(i,k)
947 p_lay(i) = pres(i) + 0.5*d_pres(i)
948 pres(i) = pres(i) + d_pres(i)
950 call calculate_specific_vol_derivs(t2d(:,k), tv%S(:,j,k), p_lay(:),&
951 dsv_dt(:,j,k), dsv_ds(:,j,k), is, ie-is+1, tv%eqn_of_state)
952 do i=is,ie ; dsv_dt_2d(i,k) = dsv_dt(i,j,k) ;
enddo 958 pen_tke_2d(:,:) = 0.0
1004 if (calculate_buoyancy)
then 1005 call extractfluxes1d(g, gv, fluxes, optics, nsw, j, dt, &
1006 h_limit_fluxes, cs%use_river_heat_content, cs%use_calving_heat_content, &
1007 h2d, t2d, netmassinout, netmassout, netheat, netsalt, &
1008 pen_sw_bnd, tv, aggregate_fw_forcing, nonpensw=nonpensw, &
1009 net_heat_rate=netheat_rate,net_salt_rate=netsalt_rate, &
1010 netmassinout_rate=netmassinout_rate,pen_sw_bnd_rate=pen_sw_bnd_rate)
1012 call extractfluxes1d(g, gv, fluxes, optics, nsw, j, dt, &
1013 h_limit_fluxes, cs%use_river_heat_content, cs%use_calving_heat_content, &
1014 h2d, t2d, netmassinout, netmassout, netheat, netsalt, &
1015 pen_sw_bnd, tv, aggregate_fw_forcing, nonpensw=nonpensw)
1020 if (aggregate_fw_forcing)
then 1021 netmassout(i) = netmassinout(i)
1024 netmassin(i) = netmassinout(i) - netmassout(i)
1026 if (g%mask2dT(i,j)>0.0)
then 1027 fluxes%netMassOut(i,j) = netmassout(i)
1028 fluxes%netMassIn(i,j) = netmassin(i)
1030 fluxes%netMassOut(i,j) = 0.0
1031 fluxes%netMassIn(i,j) = 0.0
1041 if (g%mask2dT(i,j)>0.)
then 1047 dthickness = netmassin(i)
1053 netmassin(i) = netmassin(i) - dthickness
1057 dtemp = dtemp + dthickness*temp_in
1060 if (
ASSOCIATED(fluxes%heat_content_massin)) &
1061 fluxes%heat_content_massin(i,j) = fluxes%heat_content_massin(i,j) + &
1062 t2d(i,k) * max(0.,dthickness) * gv%H_to_kg_m2 * fluxes%C_p * idt
1063 if (
ASSOCIATED(fluxes%heat_content_massout)) &
1064 fluxes%heat_content_massout(i,j) = fluxes%heat_content_massout(i,j) + &
1065 t2d(i,k) * min(0.,dthickness) * gv%H_to_kg_m2 * fluxes%C_p * idt
1066 if (
ASSOCIATED(tv%TempxPmE)) tv%TempxPmE(i,j) = tv%TempxPmE(i,j) + &
1067 t2d(i,k) * dthickness * gv%H_to_kg_m2
1070 if (calculate_energetics .and.
associated(fluxes%lrunoff) .and. cs%do_rivermix)
then 1081 rivermixconst = -0.5*(cs%rivermix_depth*dt)*gv%m_to_H*gv%H_to_Pa
1083 ctke(i,j,k) = ctke(i,j,k) + max(0.0, rivermixconst*dsv_ds(i,j,1) * &
1084 (fluxes%lrunoff(i,j) + fluxes%frunoff(i,j)) * tv%S(i,j,1))
1089 h2d(i,k) = h2d(i,k) + dthickness
1090 if (h2d(i,k) > 0.0)
then 1091 if (calculate_energetics .and. (dthickness > 0.))
then 1094 ctke(i,j,k) = ctke(i,j,k) + 0.5*g_hconv2*(hold*dthickness) * &
1095 ((t2d(i,k) - temp_in) * dsv_dt(i,j,k) + (tv%S(i,j,k) - salin_in) * dsv_ds(i,j,k))
1097 ithickness = 1.0/h2d(i,k)
1099 if (dthickness /= 0. .or. dtemp /= 0.) t2d(i,k) = (hold*t2d(i,k) + dtemp)*ithickness
1100 if (dthickness /= 0. .or. dsalt /= 0.) tv%S(i,j,k) = (hold*tv%S(i,j,k) + dsalt)*ithickness
1112 iforcingdepthscale = 1. / max(gv%H_subroundoff, minimum_forcing_depth*gv%m_to_H - netmassout(i) )
1114 fractionofforcing = min(1.0, h2d(i,k)*iforcingdepthscale)
1119 if (-fractionofforcing*netmassout(i) > evap_cfl_limit*h2d(i,k))
then 1120 fractionofforcing = -evap_cfl_limit*h2d(i,k)/netmassout(i)
1125 dthickness = max( fractionofforcing*netmassout(i), -h2d(i,k) )
1126 dtemp = fractionofforcing*netheat(i)
1128 dsalt = max( fractionofforcing*netsalt(i), -0.9999*h2d(i,k)*tv%S(i,j,k))
1132 netmassout(i) = netmassout(i) - dthickness
1133 netheat(i) = netheat(i) - dtemp
1134 netsalt(i) = netsalt(i) - dsalt
1137 dtemp = dtemp + dthickness*t2d(i,k)
1140 if (
ASSOCIATED(fluxes%heat_content_massin)) &
1141 fluxes%heat_content_massin(i,j) = fluxes%heat_content_massin(i,j) + &
1142 tv%T(i,j,k) * max(0.,dthickness) * gv%H_to_kg_m2 * fluxes%C_p * idt
1143 if (
ASSOCIATED(fluxes%heat_content_massout)) &
1144 fluxes%heat_content_massout(i,j) = fluxes%heat_content_massout(i,j) + &
1145 tv%T(i,j,k) * min(0.,dthickness) * gv%H_to_kg_m2 * fluxes%C_p * idt
1146 if (
ASSOCIATED(tv%TempxPmE)) tv%TempxPmE(i,j) = tv%TempxPmE(i,j) + &
1147 tv%T(i,j,k) * dthickness * gv%H_to_kg_m2
1152 h2d(i,k) = h2d(i,k) + dthickness
1154 if (h2d(i,k) > 0.)
then 1155 if (calculate_energetics)
then 1161 ctke(i,j,k) = ctke(i,j,k) - (0.5*h2d(i,k)*g_hconv2) * &
1162 ((dtemp - dthickness*t2d(i,k)) * dsv_dt(i,j,k) + &
1163 (dsalt - dthickness*tv%S(i,j,k)) * dsv_ds(i,j,k))
1165 ithickness = 1.0/h2d(i,k)
1166 t2d(i,k) = (hold*t2d(i,k) + dtemp)*ithickness
1167 tv%S(i,j,k) = (hold*tv%S(i,j,k) + dsalt)*ithickness
1168 elseif (h2d(i,k) < 0.0)
then 1169 call forcing_singlepointprint(fluxes,g,i,j,
'applyBoundaryFluxesInOut (h<0)')
1170 write(0,*)
'applyBoundaryFluxesInOut(): lon,lat=',g%geoLonT(i,j),g%geoLatT(i,j)
1171 write(0,*)
'applyBoundaryFluxesInOut(): netT,netS,netH=',netheat(i),netsalt(i),netmassinout(i)
1172 write(0,*)
'applyBoundaryFluxesInOut(): dT,dS,dH=',dtemp,dsalt,dthickness
1173 write(0,*)
'applyBoundaryFluxesInOut(): h(n),h(n+1),k=',hold,h2d(i,k),k
1174 call mom_error(fatal,
"MOM_diabatic_driver.F90, applyBoundaryFluxesInOut(): "//&
1175 "Complete mass loss in column!")
1181 elseif((abs(netheat(i))+abs(netsalt(i))+abs(netmassin(i))+abs(netmassout(i)))>0.)
then 1183 if (.not. cs%ignore_fluxes_over_land)
then 1184 call forcing_singlepointprint(fluxes,g,i,j,
'applyBoundaryFluxesInOut (land)')
1185 write(0,*)
'applyBoundaryFluxesInOut(): lon,lat=',g%geoLonT(i,j),g%geoLatT(i,j)
1186 write(0,*)
'applyBoundaryFluxesInOut(): netHeat,netSalt,netMassIn,netMassOut=',&
1187 netheat(i),netsalt(i),netmassin(i),netmassout(i)
1189 call mom_error(fatal,
"MOM_diabatic_driver.F90, applyBoundaryFluxesInOut(): "//&
1190 "Mass loss over land?")
1196 if (netmassin(i)+netmassout(i) /= 0.0)
then 1198 numberofgroundings = numberofgroundings +1
1199 if (numberofgroundings<=maxgroundings)
then 1200 iground(numberofgroundings) = i
1201 jground(numberofgroundings) = j
1202 hgrounding(numberofgroundings) = netmassin(i)+netmassout(i)
1205 if (cs%id_createdH>0) cs%createdH(i,j) = cs%createdH(i,j) - (netmassin(i)+netmassout(i))/dt
1216 if(cs%id_penSW_diag > 0 .or. cs%id_penSWflux_diag > 0)
then 1217 do k=1,nz ;
do i=is,ie
1218 cs%penSW_diag(i,j,k) = t2d(i,k)
1219 cs%penSWflux_diag(i,j,k) = 0.0
1222 cs%penSWflux_diag(i,j,k) = 0.0
1226 if (calculate_energetics)
then 1227 call absorbremainingsw(g, gv, h2d, opacityband, nsw, j, dt, h_limit_fluxes, &
1228 .false., .true., t2d, pen_sw_bnd, tke=pen_tke_2d, dsv_dt=dsv_dt_2d)
1230 do k=1,nz ;
do i=is,ie
1231 ctke(i,j,k) = ctke(i,j,k) + pen_tke_2d(i,k)
1234 call absorbremainingsw(g, gv, h2d, opacityband, nsw, j, dt, h_limit_fluxes, &
1235 .false., .true., t2d, pen_sw_bnd)
1241 do k=1,nz ;
do i=is,ie
1243 tv%T(i,j,k) = t2d(i,k)
1248 if(cs%id_penSW_diag > 0 .or. cs%id_penSWflux_diag > 0)
then 1251 do k=1,nz ;
do i=is,ie
1252 cs%penSW_diag(i,j,k) = (t2d(i,k)-cs%penSW_diag(i,j,k))*h(i,j,k) * idt * tv%C_p * gv%H_to_kg_m2
1261 if(cs%id_penSWflux_diag > 0)
then 1262 do k=nz,1,-1 ;
do i=is,ie
1263 cs%penSWflux_diag(i,j,k) = cs%penSW_diag(i,j,k) + cs%penSWflux_diag(i,j,k+1)
1270 if(cs%id_nonpenSW_diag > 0)
then 1272 cs%nonpenSW_diag(i,j) = nonpensw(i)
1281 if (calculate_buoyancy)
then 1287 call sumswoverbands(g, gv, h2d(:,:), optics%opacity_band(:,:,j,:), nsw, j, dt, &
1288 h_limit_fluxes, .true., pen_sw_bnd_rate, netpen)
1290 call calculate_density_derivs(t2d(:,1), tv%S(:,j,1), surfpressure, &
1291 drhodt, drhods, start, npts, tv%eqn_of_state)
1297 skinbuoyflux(g%isc:g%iec,j) = - gorho * ( drhods(g%isc:g%iec) * (netsalt_rate(g%isc:g%iec) &
1298 - tv%S(g%isc:g%iec,j,1) * netmassinout_rate(g%isc:g%iec)* gv%H_to_m )&
1299 + drhodt(g%isc:g%iec) * ( netheat_rate(g%isc:g%iec) + &
1300 netpen(g%isc:g%iec,1))) * gv%H_to_m
1306 if (cs%id_createdH > 0)
call post_data(cs%id_createdH , cs%createdH , cs%diag)
1307 if (cs%id_penSW_diag > 0)
call post_data(cs%id_penSW_diag , cs%penSW_diag , cs%diag)
1308 if (cs%id_penSWflux_diag > 0)
call post_data(cs%id_penSWflux_diag, cs%penSWflux_diag, cs%diag)
1309 if (cs%id_nonpenSW_diag > 0)
call post_data(cs%id_nonpenSW_diag , cs%nonpenSW_diag , cs%diag)
1312 if (numberofgroundings>0 .and. .not. cs%ignore_fluxes_over_land)
then 1313 do i = 1, min(numberofgroundings, maxgroundings)
1314 call forcing_singlepointprint(fluxes,g,iground(i),jground(i),
'applyBoundaryFluxesInOut (grounding)')
1315 write(mesg(1:45),
'(3es15.3)') g%geoLonT( iground(i), jground(i) ), &
1316 g%geoLatT( iground(i), jground(i)) , hgrounding(i)
1317 call mom_error(warning,
"MOM_diabatic_driver.F90, applyBoundaryFluxesInOut(): "//&
1318 "Mass created. x,y,dh= "//trim(mesg), all_print=.true.)
1321 if (numberofgroundings - maxgroundings > 0)
then 1322 write(mesg,
'(i4)') numberofgroundings - maxgroundings
1323 call mom_error(warning,
"MOM_diabatic_driver:F90, applyBoundaryFluxesInOut(): "//&
1324 trim(mesg) //
" groundings remaining")