← Back to Documentation Home
CCPP SciDoc v8.0.0  v8.0.0
Common Community Physics Package Developed at DTC
 
Loading...
Searching...
No Matches
module_nst_model.f90
1
4
9
13 !
14 ! the module of diurnal thermocline layer model
15 !
16 use machine , only : kind_phys
17 use module_nst_parameters , only : z_w_max, z_w_min, z_w_ini, eps_z_w, eps_conv
18 use module_nst_parameters , only : eps_sfs, niter_z_w, niter_conv, niter_sfs, ri_c
19 use module_nst_parameters , only : ri_g, omg_m, omg_sh, kw => tc_w, visw, t0k, cp_w
20 use module_nst_parameters , only : z_c_max, z_c_ini, ustar_a_min, delz, exp_const
21 use module_nst_parameters , only : rad2deg, const_rot, tw_max, sst_max
22 use module_nst_parameters , only : zero, one
24
25 implicit none
26
27 private
28
31
32contains
33
36 subroutine dtm_1p(kdt,timestep,rich,tox,toy,i0,q,sss,sep,q_ts,hl_ts,rho, &
37 alpha,beta,alon,sinlat,soltim,grav,le,d_conv, &
38 xt,xs,xu,xv,xz,xzts,xtts)
39
40 integer, intent(in) :: kdt
41 real(kind=kind_phys), intent(in) :: timestep,rich,tox,toy,i0,q,sss,sep,q_ts,&
42 hl_ts,rho,alpha,beta,alon,sinlat,soltim,&
43 grav,le,d_conv
44 real(kind=kind_phys), intent(inout) :: xt,xs,xu,xv,xz,xzts,xtts
45 ! local variables
46
47 !
48 ! input variables
49 !
50 ! timestep: integration time step in seconds
51 ! rich : critical ri (flow dependent)
52 ! tox : x wind stress (n*m^-2 or kg/m/s^2)
53 ! toy : y wind stress (n*m^-2 or kg/m/s^2)
54 ! i0 : solar radiation flux at the surface (wm^-2)
55 ! q : non-solar heat flux at the surface (wm^-2)
56 ! sss : salinity (ppt)
57 ! sep : sr(e-p) (ppt*m/s)
58 ! q_ts : d(q)/d(ts) : q = the sum of non-solar heat fluxes
59 ! hl_ts : d(hl)/d(ts)
60 ! rho : sea water density (kg*m^-3)
61 ! alpha : thermal expansion coefficient (1/k)
62 ! beta : saline contraction coefficient (1/ppt)
63 ! sinlat : sine (lat)
64 ! grav : gravity accelleration
65 ! le : le=(2.501-.00237*tsea)*1e6
66 ! d-conv : fcl thickness
67 !
68 ! inout variables
69 !
70 ! xt : dtl heat content (m*k)
71 ! xs : dtl salinity content (m*ppt)
72 ! xu : dtl x current content (m*m/s)
73 ! xv : dtl y current content (m*m/s)
74 ! xz : dtl thickness (m)
75 ! xzts : d(xz)/d(ts) (m/k )
76 ! xtts : d(xt)/d(ts) (m)
77 !
78 ! logical lprnt
79
80 ! if (lprnt) print *,' first xt=',xt
81 if ( xt <= zero ) then ! dtl doesn't exist yet
82 call dtm_onset(kdt,timestep,rich,tox,toy,i0,q,sss,sep,q_ts,hl_ts,rho,alpha, &
83 beta,alon,sinlat,soltim,grav,le,xt,xs,xu,xv,xz,xzts,xtts)
84 elseif ( xt > zero ) then ! dtl already exists
85 !
86 ! forward the system one time step
87 !
88 call eulerm(kdt,timestep,rich,tox,toy,i0,q,sss,sep,q_ts,hl_ts,rho,alpha, &
89 beta,alon,sinlat,soltim,grav,le,d_conv, &
90 xt,xs,xu,xv,xz,xzts,xtts)
91 endif ! if ( xt == 0 ) then
92
93 end subroutine dtm_1p
94
97 subroutine eulerm(kdt,timestep,rich,tox,toy,i0,q,sss,sep,q_ts,hl_ts,rho,alpha, &
98 beta,alon,sinlat,soltim,grav,le,d_conv, &
99 xt,xs,xu,xv,xz,xzts,xtts)
100
101 !
102 ! subroutine eulerm: integrate one time step with modified euler method
103 !
104 integer, intent(in) :: kdt
105 real(kind=kind_phys), intent(in) :: timestep,rich,tox,toy,i0,q,sss,sep,q_ts, &
106 hl_ts,rho,alpha,beta,alon,sinlat,soltim, &
107 grav,le,d_conv
108 real(kind=kind_phys), intent(inout) :: xt,xs,xu,xv,xz,xzts,xtts
109 ! local variables
110 real(kind=kind_phys) :: xt0,xs0,xu0,xv0,xz0,xzts0,xtts0
111 real(kind=kind_phys) :: fw,aw,q_warm
112 real(kind=kind_phys) :: xt1,xs1,xu1,xv1,xz1,xzts1,xtts1
113 real(kind=kind_phys) :: xt2,xs2,xu2,xv2,xz2,xzts2,xtts2
114 real(kind=kind_phys) :: dzw,drho,fc
115 real(kind=kind_phys) :: alat,speed
116 ! logical lprnt
117
118 !
119 ! input variables
120 !
121 ! timestep: integration time step in seconds
122 ! rich : critial ri (flow/mass dependent)
123 ! tox : x wind stress (n*m^-2 or kg/m/s^2)
124 ! toy : y wind stress (n*m^-2 or kg/m/s^2)
125 ! i0 : solar radiation flux at the surface (wm^-2)
126 ! q : non-solar heat flux at the surface (wm^-2)
127 ! sss : salinity (ppt)
128 ! sep : sr(e-p) (ppt*m/s)
129 ! q_ts : d(q)/d(ts) : q = the sum of non-solar heat fluxes
130 ! hl_ts : d(hl)/d(ts)
131 ! rho : sea water density (kg*m^-3)
132 ! alpha : thermal expansion coefficient (1/k)
133 ! beta : saline contraction coefficient (1/ppt)
134 ! alon : longitude (deg)
135 ! sinlat : sine (lat)
136 ! soltim : solar time
137 ! grav : gravity accelleration
138 ! le : le=(2.501-.00237*tsea)*1e6
139 ! d_conv : fcl thickness (m)
140 !
141 ! inout variables
142 !
143 ! xt : dtl heat content (m*k)
144 ! xs : dtl salinity content (m*ppt)
145 ! xu : dtl x current content (m*m/s)
146 ! xv : dtl y current content (m*m/s)
147 ! xz : dtl thickness (m)
148 ! xzts : d(xz)/d(ts) (m/k )
149 ! xtts : d(xt)/d(ts) (m)
150
151 xt0 = xt
152 xs0 = xs
153 xu0 = xu
154 xv0 = xv
155 xz0 = xz
156 xtts0 = xtts
157 xzts0 = xzts
158 speed = max(1.0e-8, xu0*xu0+xv0*xv0)
159
160 alat = asin(sinlat)*rad2deg
161
162 fc = const_rot*sinlat
163
164 call sw_ps_9b(xz0,fw)
165
166 q_warm = fw*i0-q !total heat abs in warm layer
167
168 call sw_ps_9b_aw(xz0,aw)
169
170 drho = -alpha*q_warm/(rho*cp_w) + omg_m*beta*sep
171
172 ! dzw = xz0*(tox*xu0+toy*xv0) / (rho*(xu0*xu0+xv0*xv0)) &
173 ! + xz0*xz0*xz0*drho*grav / (4.0*rich*(xu0*xu0+xv0*xv0))
174 dzw = xz0 * ((tox*xu0+toy*xv0) / (rho*speed) &
175 + xz0*xz0*drho*grav / (4.0*rich*speed))
176
177 xt1 = xt0 + timestep*q_warm/(rho*cp_w)
178 xs1 = xs0 + timestep*sep
179 xu1 = xu0 + timestep*(fc*xv0+tox/rho)
180 xv1 = xv0 + timestep*(-fc*xu0+toy/rho)
181 xz1 = xz0 + timestep*dzw
182
183 ! if (lprnt) print *,' xt1=',xt1,' xz1=',xz1,' xz0=',xz0,' dzw=',dzw, &
184 ! 'timestep=',timestep,tox,toy,xu0,xv0,rho,drho,grav,rich
185
186 if ( xt1 <= zero .or. xz1 <= zero .or. xz1 > z_w_max ) then
187 call dtl_reset(xt,xs,xu,xv,xz,xzts,xtts)
188 return
189 endif
190
191 ! call dtm_1p_zwa(kdt,timestep,i0,q,rho,d_conv,xt1,xs1,xu1,xv1,xz1,tr_mda,tr_fca,tr_tla,tr_mwa)
192
193 xzts1 = xzts0 + timestep*((1.0/(xu0*xu0+xv0*xv0)) * &
194 ( (alpha*q_ts/cp_w+omg_m*beta*sss*hl_ts/le)*grav*xz0**3/(4.0*rich*rho) &
195 +( (tox*xu0+toy*xv0)/rho+(3.0*drho-alpha*i0*aw*xz0/(rho*cp_w)) &
196 *grav*xz0*xz0/(4.0*rich) )*xzts0 ))
197 xtts1 = xtts0 + timestep*(i0*aw*xzts0-q_ts)/(rho*cp_w)
198
199 ! if ( 2.0*xt1/xz1 > 0.001 ) then
200 ! write(*,'(a,i5,2f8.3,4f8.2,f10.6,10f8.4)') 'eulerm_01 : ',kdt,alat,alon,soltim/3600.,i0,q,q_warm,sep,&
201 ! 2.0*xt1/xz1,2.0*xs1/xz1,2.0*xu1/xz1,2.0*xv1/xz1,xz1,xtts1,xzts1,d_conv,t_fcl,te
202 ! endif
203
204 call sw_ps_9b(xz1,fw)
205 q_warm = fw*i0-q !total heat abs in warm layer
206 call sw_ps_9b_aw(xz1,aw)
207 drho = -alpha*q_warm/(rho*cp_w) + omg_m*beta*sep
208 dzw = xz1*(tox*xu1+toy*xv1) / (rho*(xu1*xu1+xv1*xv1)) &
209 + xz1*xz1*xz1*drho*grav / (4.0*rich*(xu1*xu1+xv1*xv1))
210
211 xt2 = xt0 + timestep*q_warm/(rho*cp_w)
212 xs2 = xs0 + timestep*sep
213 xu2 = xu0 + timestep*(fc*xv1+tox/rho)
214 xv2 = xv0 + timestep*(-fc*xu1+toy/rho)
215 xz2 = xz0 + timestep*dzw
216
217 ! if (lprnt) print *,' xt2=',xt2,' xz2=',xz2
218
219 if ( xt2 <= zero .or. xz2 <= zero .or. xz2 > z_w_max ) then
220 call dtl_reset(xt,xs,xu,xv,xz,xzts,xtts)
221 return
222 endif
223
224 xzts2 = xzts0 + timestep*((1.0/(xu1*xu1+xv1*xv1)) * &
225 ( (alpha*q_ts/cp_w+omg_m*beta*sss*hl_ts/le)*grav*xz1**3/(4.0*rich*rho) &
226 +( (tox*xu1+toy*xv1)/rho+(3.0*drho-alpha*i0*aw*xz1/(rho*cp_w))* &
227 grav*xz1*xz1/(4.0*rich) )*xzts1 ))
228 xtts2 = xtts0 + timestep*(i0*aw*xzts1-q_ts)/(rho*cp_w)
229
230 xt = 0.5*(xt1 + xt2)
231 xs = 0.5*(xs1 + xs2)
232 xu = 0.5*(xu1 + xu2)
233 xv = 0.5*(xv1 + xv2)
234 xz = 0.5*(xz1 + xz2)
235 xzts = 0.5*(xzts1 + xzts2)
236 xtts = 0.5*(xtts1 + xtts2)
237
238 if ( xt <= zero .or. xz < zero .or. xz > z_w_max ) then
239 call dtl_reset(xt,xs,xu,xv,xz,xzts,xtts)
240 endif
241
242 ! if (lprnt) print *,' xt=',xt,' xz=',xz
243 ! if ( 2.0*xt/xz > 0.001 ) then
244 ! write(*,'(a,i5,2f8.3,4f8.2,f10.6,10f8.4)') 'eulerm_02 : ',kdt,alat,alon,soltim/3600.,i0,q,q_warm,sep,&
245 ! 2.0*xt/xz,2.0*xs/xz,2.0*xu/xz,2.0*xv/xz,xz,xtts,xzts,d_conv,t_fcl,te
246 ! endif
247 return
248
249 end subroutine eulerm
250
253 subroutine dtm_1p_zwa(kdt,timestep,i0,q,rho,d_conv,xt,xs,xu,xv,xz,tr_mda,tr_fca,tr_tla,tr_mwa)
254 ! apply xz adjustment: minimum depth adjustment (mda)
255 ! free convection adjustment (fca);
256 ! top layer adjustment (tla);
257 ! maximum warming adjustment (mwa)
258 !
259 integer, intent(in) :: kdt
260 real(kind=kind_phys), intent(in) :: timestep,i0,q,rho,d_conv
261 real(kind=kind_phys), intent(inout) :: xt,xs,xu,xv,xz
262 real(kind=kind_phys), intent(out) :: tr_mda,tr_fca,tr_tla,tr_mwa
263 ! local variables
264 real(kind=kind_phys) :: dz,t0,ttop0,ttop,fw,q_warm
265 ! TODO: xz_mwa is unset but used below in max function
266 real(kind=kind_phys) :: xz_fca,xz_tla,xz_mwa
267 !
268 real(kind=kind_phys) :: xz_mda
269
270 tr_mda = zero; tr_fca = zero; tr_tla = zero; tr_mwa = zero
271
272 ! apply mda
273 if ( z_w_min > xz ) then
274 xz_mda = z_w_min
275 endif
276 ! apply fca
277 if ( d_conv > zero ) then
278 xz_fca = 2.0*xt/((2.0*xt/xz)*(1.0-d_conv/(2.0*xz)))
279 tr_fca = 1.0
280 if ( xz_fca >= z_w_max ) then
281 call dtl_reset_cv(xt,xs,xu,xv,xz)
282 return
283 endif
284 endif
285 ! apply tla
286 dz = min(xz,max(d_conv,delz))
287 call sw_ps_9b(dz,fw)
288 q_warm=fw*i0-q !total heat abs in warm layer
289
290 if ( q_warm > zero ) then
291 call cal_ttop(kdt,timestep,q_warm,rho,dz,xt,xz,ttop0)
292 ! ttop = (2.0*xt/xz)*(1.0-dz/(2.0*xz))
293 ttop = ((xt+xt)/xz)*(1.0-dz/(xz+xz))
294 if ( ttop > ttop0 ) then
295 xz_tla = (xt+sqrt(xt*(xt-delz*ttop0)))/ttop0
296 tr_tla = 1.0
297 if ( xz_tla >= z_w_max ) then
298 call dtl_reset_cv(xt,xs,xu,xv,xz)
299 return
300 endif
301 endif
302 endif
303
304 ! apply mwa
305 t0 = 2.0*xt/xz
306 if ( t0 > tw_max ) then
307 if ( xz >= z_w_max ) then
308 call dtl_reset_cv(xt,xs,xu,xv,xz)
309 return
310 endif
311 endif
312
313 xz = max(xz_mda,xz_fca,xz_tla,xz_mwa)
314
315 end subroutine dtm_1p_zwa
316
319 subroutine dtm_1p_fca(d_conv,xt,xtts,xz,xzts)
320
321 ! apply xz adjustment: free convection adjustment (fca);
322 !
323 real(kind=kind_phys), intent(in) :: d_conv,xt,xtts
324 real(kind=kind_phys), intent(inout) :: xz,xzts
325 ! local variables
326 real(kind=kind_phys) :: t_fcl,t0
327 !
328 t0 = 2.0*xt/xz
329 t_fcl = t0*(1.0-d_conv/(2.0*xz))
330 xz = 2.0*xt/t_fcl
331 ! xzts = 2.0*xtts/t_fcl
332
333 end subroutine dtm_1p_fca
334
337 subroutine dtm_1p_tla(dz,te,xt,xtts,xz,xzts)
338
339 ! apply xz adjustment: top layer adjustment (tla);
340 !
341 real(kind=kind_phys), intent(in) :: dz,te,xt,xtts
342 real(kind=kind_phys), intent(inout) :: xz,xzts
343 ! local variables
344 real(kind=kind_phys) :: tem
345 !
346 tem = xt*(xt-dz*te)
347 if (tem > zero) then
348 xz = (xt+sqrt(xt*(xt-dz*te)))/te
349 else
350 xz = z_w_max
351 endif
352 ! xzts = xtts*(1.0+0.5*(2.0*xt-dz*te)/sqrt(xt*(xt-dz*te)))/te
353 end subroutine dtm_1p_tla
354
357 subroutine dtm_1p_mwa(xt,xtts,xz,xzts)
358
359 ! apply xz adjustment: maximum warming adjustment (mwa)
360 !
361 real(kind=kind_phys), intent(in) :: xt,xtts
362 real(kind=kind_phys), intent(inout) :: xz,xzts
363 ! local variables
364 !
365 xz = 2.0*xt/tw_max
366 ! xzts = 2.0*xtts/tw_max
367 end subroutine dtm_1p_mwa
368
371 subroutine dtm_1p_mda(xt,xtts,xz,xzts)
372
373 ! apply xz adjustment: minimum depth adjustment (mda)
374 !
375 real(kind=kind_phys), intent(in) :: xt,xtts
376 real(kind=kind_phys), intent(inout) :: xz,xzts
377 ! local variables
378 real(kind=kind_phys) :: ta
379 !
380 xz = max(z_w_min,xz)
381 ta = 2.0*xt/xz
382 ! xzts = 2.0*xtts/ta
383
384 end subroutine dtm_1p_mda
385
388 subroutine dtm_1p_mta(dta,xt,xtts,xz,xzts)
389
390 ! apply xz adjustment: maximum temperature adjustment (mta)
391 !
392 real(kind=kind_phys), intent(in) :: dta,xt,xtts
393 real(kind=kind_phys), intent(inout) :: xz,xzts
394 ! local variables
395 real(kind=kind_phys) :: ta
396 !
397 ta = max(zero,2.0*xt/xz-dta)
398 if ( ta > zero ) then
399 xz = 2.0*xt/ta
400 else
401 xz = z_w_max
402 endif
403 ! xzts = 2.0*xtts/ta
404
405 end subroutine dtm_1p_mta
406
409 subroutine convdepth(kdt,timestep,i0,q,sss,sep,rho,alpha,beta,xt,xs,xz,d_conv)
410
411 !
412 ! calculate depth for convective adjustment
413 !
414
415 integer, intent(in) :: kdt
416 real(kind=kind_phys), intent(in) :: timestep,i0,q,sss,sep,rho,alpha,beta
417 real(kind=kind_phys), intent(in) :: xt,xs,xz
418 real(kind=kind_phys), intent(out) :: d_conv
419 real(kind=kind_phys) :: t,s,d_conv_ini,d_conv2,fxp,aw,s1,s2,fac1
420 integer :: n
421 !
422 ! input variables
423 !
424 ! timestep: time step in seconds
425 ! i0 : solar radiation flux at the surface (wm^-2)
426 ! q : non-solar heat flux at the surface (wm^-2)
427 ! sss : salinity (ppt)
428 ! sep : sr(e-p) (ppt*m/s)
429 ! rho : sea water density (kg*m^-3)
430 ! alpha : thermal expansion coefficient (1/k)
431 ! beta : saline contraction coefficient (1/ppt)
432 ! xt : initial heat content (k*m)
433 ! xs : initial salinity content (ppt*m)
434 ! xz : initial dtl thickness (m)
435 !
436 ! output variables
437 !
438 ! d_conv : free convection depth (m)
439
440 ! t : initial diurnal warming t (k)
441 ! s : initial diurnal warming s (ppt)
442
443 n = 0
444 t = 2.0*xt/xz
445 s = 2.0*xs/xz
446
447 s1 = alpha*rho*t-omg_m*beta*rho*s
448
449 if ( s1 == zero ) then
450 d_conv = zero
451 else
452
453 fac1 = alpha*q/cp_w+omg_m*beta*rho*sep
454 if ( i0 <= zero ) then
455 d_conv2=(2.0*xz*timestep/s1)*fac1
456 if ( d_conv2 > zero ) then
457 d_conv = sqrt(d_conv2)
458 else
459 d_conv = zero
460 endif
461 elseif ( i0 > zero ) then
462
463 d_conv_ini = zero
464
465 iter_conv: do n = 1, niter_conv
466 call sw_ps_9b(d_conv_ini,fxp)
467 call sw_ps_9b_aw(d_conv_ini,aw)
468 s2 = alpha*(q-(fxp-aw*d_conv_ini)*i0)/cp_w+omg_m*beta*rho*sep
469 d_conv2=(2.0*xz*timestep/s1)*s2
470 if ( d_conv2 < zero ) then
471 d_conv = zero
472 exit iter_conv
473 endif
474 d_conv = sqrt(d_conv2)
475 if ( abs(d_conv-d_conv_ini) < eps_conv .and. n <= niter_conv ) exit iter_conv
476 d_conv_ini = d_conv
477 enddo iter_conv
478 d_conv = max(zero,min(d_conv,z_w_max))
479 endif ! if ( i0 <= zero ) then
480
481 endif ! if ( s1 == zero ) then
482
483 ! if ( d_conv > 0.01 ) then
484 ! write(*,'(a,i4,i3,10f9.3,3f10.6,f10.1,f6.2)') ' d_conv : ',kdt,n,d_conv,d_conv_ini,q,i0,rho,cp_w,timestep,xt,xs,xz,sep, &
485 ! s1,s2,d_conv2,aw
486 ! endif
487
488 end subroutine convdepth
489
491 subroutine dtm_onset(kdt,timestep,rich,tox,toy,i0,q,sss,sep,q_ts,hl_ts,rho, &
492 alpha,beta,alon,sinlat,soltim,grav,le,xt,xs,xu,xv,xz,xzts,xtts)
493 !
494 ! determine xz iteratively (starting wit fw = 0.5) and then update the other 6 variables
495 !
496
497 integer,intent(in) :: kdt
498 real(kind=kind_phys), intent(in) :: timestep,rich,tox,toy,i0,q,sss,sep,q_ts, &
499 hl_ts,rho,alpha,beta,alon,sinlat,soltim,grav,le
500 real(kind=kind_phys), intent(out) :: xt,xs,xu,xv,xz,xzts,xtts
501 real(kind=kind_phys) :: xt0,xs0,xu0,xv0,xz0
502 real(kind=kind_phys) :: xt1,xs1,xu1,xv1,xz1
503 real(kind=kind_phys) :: fw,aw,q_warm,ft0,fs0,fu0,fv0,fz0,ft1,fs1,fu1,fv1,fz1
504 real(kind=kind_phys) :: coeff1,coeff2,ftime,z_w,z_w_tmp,fc,warml,alat
505 integer :: n
506 !
507 ! input variables
508 !
509 ! timestep: time step in seconds
510 ! tox : x wind stress (n*m^-2 or kg/m/s^2)
511 ! toy : y wind stress (n*m^-2 or kg/m/s^2)
512 ! i0 : solar radiation flux at the surface (wm^-2)
513 ! q : non-solar heat flux at the surface (wm^-2)
514 ! sss : salinity (ppt)
515 ! sep : sr(e-p) (ppt*m/s)
516 ! rho : sea water density (kg*m^-3)
517 ! alpha : thermal expansion coefficient (1/k)
518 ! beta : saline contraction coefficient (1/ppt)
519 ! alon : longitude
520 ! sinlat : sine(latitude)
521 ! grav : gravity accelleration
522 ! le : le=(2.501-.00237*tsea)*1e6
523 !
524 ! output variables
525 !
526 ! xt : onset t content in dtl
527 ! xs : onset s content in dtl
528 ! xu : onset u content in dtl
529 ! xv : onset v content in dtl
530 ! xz : onset dtl thickness (m)
531 ! xzts : onset d(xz)/d(ts) (m/k )
532 ! xtts : onset d(xt)/d(ts) (m)
533
534 fc=1.46/10000.0/2.0*sinlat
535 alat = asin(sinlat)
536 !
537 ! initializing dtl (just before the onset)
538 !
539 xt0 = zero
540 xs0 = zero
541 xu0 = zero
542 xv0 = zero
543
544 z_w_tmp=z_w_ini
545
546 call sw_ps_9b(z_w_tmp,fw)
547 ! fw=0.5 !
548 q_warm=fw*i0-q !total heat abs in warm layer
549
550 if ( abs(alat) > 1.0 ) then
551 ftime=sqrt((2.0-2.0*cos(fc*timestep))/(fc*fc*timestep))
552 else
553 ftime=timestep
554 endif
555
556 coeff1=alpha*grav/cp_w
557 coeff2=omg_m*beta*grav*rho
558 warml = coeff1*q_warm-coeff2*sep
559
560 if ( warml > zero .and. q_warm > zero) then
561 iters_z_w: do n = 1,niter_z_w
562 if ( warml > zero .and. q_warm > zero ) then
563 z_w=sqrt(2.0*rich*ftime/rho)*sqrt(tox**2+toy**2)/sqrt(warml)
564 else
565 z_w = z_w_max
566 exit iters_z_w
567 endif
568
569 ! write(*,'(a,i4,i4,10f9.3,f9.6,f3.0)') ' z_w = ',kdt,n,z_w,z_w_tmp,timestep,q_warm,q,i0,fw,tox,toy,sep,warml,omg_m
570
571 if (abs(z_w - z_w_tmp) < eps_z_w .and. z_w/=z_w_max .and. n < niter_z_w) exit iters_z_w
572 z_w_tmp=z_w
573 call sw_ps_9b(z_w_tmp,fw)
574 q_warm = fw*i0-q
575 warml = coeff1*q_warm-coeff2*sep
576 end do iters_z_w
577 else
578 z_w=z_w_max
579 endif
580
581 xz0 = max(z_w,z_w_min)
582
583 !
584 ! update xt, xs, xu, xv
585 !
586 if ( z_w < z_w_max .and. q_warm > zero) then
587
588 call sw_ps_9b(z_w,fw)
589 q_warm=fw*i0-q !total heat abs in warm layer
590
591 ft0 = q_warm/(rho*cp_w)
592 fs0 = sep
593 fu0 = fc*xv0+tox/rho
594 fv0 = -fc*xu0+toy/rho
595
596 xt1 = xt0 + timestep*ft0
597 xs1 = xs0 + timestep*fs0
598 xu1 = xu0 + timestep*fu0
599 xv1 = xv0 + timestep*fv0
600
601 fz0 = xz0*((tox*xu1+toy*xv1)/rho+omg_m*beta*grav*sep*xz0*xz0/(4.0*rich) &
602 -alpha*grav*q_warm*xz0*xz0/(4.0*rich*cp_w*rho))/(xu1*xu1+xv1*xv1)
603 xz1 = xz0 + timestep*fz0
604
605 xz1 = max(xz1,z_w_min)
606
607 if ( xt1 < zero .or. xz1 > z_w_max ) then
608 call dtl_reset(xt,xs,xu,xv,xz,xtts,xzts)
609 return
610 endif
611
612 call sw_ps_9b(xz1,fw)
613 q_warm=fw*i0-q !total heat abs in warm layer
614
615 ft1 = q_warm/(rho*cp_w)
616 fs1 = sep
617 fu1 = fc*xv1+tox/rho
618 fv1 = -fc*xu1+toy/rho
619
620 fz1 = xz1*((tox*xu1+toy*xv1)/rho+omg_m*beta*grav*sep*xz1*xz1/(4.0*rich) &
621 -alpha*grav*q_warm*xz1*xz1/(4.0*rich*cp_w*rho))/(xu1*xu1+xv1*xv1)
622
623 xt = xt0 + 0.5*timestep*(ft0+ft1)
624 xs = xs0 + 0.5*timestep*(fs0+fs1)
625 xu = xu0 + 0.5*timestep*(fu0+fu1)
626 xv = xv0 + 0.5*timestep*(fv0+fv1)
627 xz = xz0 + 0.5*timestep*(fz0+fz1)
628
629 xz = max(xz,z_w_min)
630
631 call sw_ps_9b_aw(xz,aw)
632
633 ! xzts = (q_ts+(cp_w*omg_m*beta*sss/(le*alpha))*hl_ts)*xz/(i0*xz*aw+2.0*q_warm-2.0*(rho*cp_w*omg_m*beta*sss/alpha)*(sep/sss))
634 xzts = (q_ts+omg_m*rho*cp_w*beta*sss*hl_ts*xz/(le*alpha))/(i0*xz*aw+2.0*q_warm-2.0*omg_m*rho*cp_w*beta*sss*sep/(le*alpha))
635 xtts = timestep*(i0*aw*xzts-q_ts)/(rho*cp_w)
636 endif
637
638 if ( xt < zero .or. xz > z_w_max ) then
639 call dtl_reset(xt,xs,xu,xv,xz,xtts,xzts)
640 endif
641
642 return
643
644 end subroutine dtm_onset
645
649 subroutine cal_w(kdt,xz,xt,xzts,xtts,w_0,w_d)
650 !
651 ! abstract: calculate w_0,w_d
652 !
653 ! input variables
654 !
655 ! kdt : the number of time step
656 ! xt : dtl heat content
657 ! xz : dtl depth
658 ! xzts : d(zw)/d(ts)
659 ! xtts : d(xt)/d(ts)
660 !
661 ! output variables
662 !
663 ! w_0 : coefficint 1 to calculate d(tw)/d(ts)
664 ! w_d : coefficint 2 to calculate d(tw)/d(ts)
665
666 integer, intent(in) :: kdt
667 real(kind=kind_phys), intent(in) :: xz,xt,xzts,xtts
668 real(kind=kind_phys), intent(out) :: w_0,w_d
669
670 w_0 = 2.0*(xtts-xt*xzts/xz)/xz
671 w_d = (2.0*xt*xzts/xz**2-w_0)/xz
672
673 ! if ( 2.0*xt/xz > 1.0 ) then
674 ! write(*,'(a,i4,2f9.3,4f10.4))') ' cal_w : ',kdt,xz,xt,w_0,w_d,xzts,xtts
675 ! endif
676 end subroutine cal_w
677
681 subroutine cal_ttop(kdt,timestep,q_warm,rho,dz,xt,xz,ttop)
682 !
683 ! abstract: calculate
684 !
685 ! input variables
686 !
687 ! kdt : the number of record
688 ! timestep : the number of record
689 ! q_warm : total heat abs in layer dz
690 ! rho : sea water density
691 ! dz : dz = max(delz,d_conv) top layer thickness defined to adjust xz
692 ! xt : heat content in dtl at previous time
693 ! xz : dtl thickness at previous time
694 !
695 ! output variables
696 !
697 ! ttop : the diurnal warming amount at the top layer with thickness of delz
698
699 integer, intent(in) :: kdt
700 real(kind=kind_phys), intent(in) :: timestep,q_warm,rho,dz,xt,xz
701 real(kind=kind_phys), intent(out) :: ttop
702 real(kind=kind_phys) :: dt_warm,t0
703
704 dt_warm = (xt+xt)/xz
705 t0 = dt_warm*(1.0-dz/(xz+xz))
706 ttop = t0 + q_warm*timestep/(rho*cp_w*dz)
707
708 end subroutine cal_ttop
709
713 subroutine app_sfs(kdt,xt,xs,xu,xv,alpha,beta,grav,d_1p,xz)
714 !
715 ! abstract: adjust dtm-1p dtl thickness by applying shear flow stability with assumed exponetial profile
716 !
717 ! input variables
718 !
719 ! kdt : the number of record
720 ! xt : heat content in dtl
721 ! xs : salinity content in dtl
722 ! xu : u-current content in dtl
723 ! xv : v-current content in dtl
724 ! alpha
725 ! beta
726 ! grav
727 ! d_1p : dtl depth before sfs applied
728 !
729 ! output variables
730 !
731 ! xz : dtl depth
732
733 integer, intent(in) :: kdt
734 real(kind=kind_phys), intent(in) :: xt,xs,xu,xv,alpha,beta,grav,d_1p
735 real(kind=kind_phys), intent(out) :: xz
736 ! real(kind=kind_phys) :: ze,cc,xz0,l,d_sfs, t_sfs, tem
737 real(kind=kind_phys) :: cc,l,d_sfs,tem
738 real(kind=kind_phys), parameter :: c2 = 0.3782
739
740 cc = ri_g/(grav*c2)
741
742 tem = alpha*xt - beta*xs
743 if (tem > zero) then
744 d_sfs = sqrt(2.0*cc*(xu*xu+xv*xv)/tem)
745 else
746 d_sfs = zero
747 endif
748
749 ! xz0 = d_1p
750 ! iter_sfs: do n = 1, niter_sfs
751 ! l = int_epn(0.0,xz0,0.0,xz0,2)
752 ! d_sfs = cc*(xu*xu+xv*xv)/((alpha*xt-beta*xs)*l)
753 ! write(*,'(a,i6,i3,4f9.4))') ' app_sfs_iter : ',kdt,n,cc,l,xz0,d_sfs
754 ! if ( abs(d_sfs-xz0) < eps_sfs .and. n <= niter_sfs ) exit iter_sfs
755 ! xz0 = d_sfs
756 ! enddo iter_sfs
757
758 ! ze = a2*d_sfs ! not used!
759
760 l = int_epn(zero,d_sfs,zero,d_sfs,2)
761
762 ! t_sfs = xt/l
763 ! xz = (xt+xt) / t_sfs
764
765 xz = l + l
766
767 ! write(*,'(a,i6,6f9.4))') ' app_sfs : ',kdt,xz0,d_sfs,d_1p,xz,2.0*xt/d_1p,t_sfs
768 end subroutine app_sfs
769
772 subroutine cal_tztr(kdt,xt,c_0,c_d,w_0,w_d,zc,zw,z,tztr)
773 !
774 ! abstract: calculate d(tz)/d(ts)
775 !
776 ! input variables
777 !
778 ! kdt : the number of record
779 ! xt : heat content in dtl
780 ! xz : dtl depth (m)
781 ! c_0 : coefficint 1 to calculate d(tc)/d(ts)
782 ! c_d : coefficint 2 to calculate d(tc)/d(ts)
783 ! w_0 : coefficint 1 to calculate d(tw)/d(ts)
784 ! w_d : coefficint 2 to calculate d(tw)/d(ts)
785 !
786 ! output variables
787 !
788 ! tztr : d(tz)/d(tr)
789
790 integer, intent(in) :: kdt
791 real(kind=kind_phys), intent(in) :: xt,c_0,c_d,w_0,w_d,zc,zw,z
792 real(kind=kind_phys), intent(out) :: tztr
793
794 if ( xt > zero ) then
795 if ( z <= zc ) then
796 ! tztr = 1.0/(1.0-w_0+c_0)+z*(w_d-c_d)/(1.0-w_0+c_0)
797 tztr = (1.0+z*(w_d-c_d))/(1.0-w_0+c_0)
798 elseif ( z > zc .and. z < zw ) then
799 ! tztr = (1.0+c_0)/(1.0-w_0+c_0)+z*w_d/(1.0-w_0+c_0)
800 tztr = (1.0+c_0+z*w_d)/(1.0-w_0+c_0)
801 elseif ( z >= zw ) then
802 tztr = 1.0
803 endif
804 elseif ( xt == zero ) then
805 if ( z <= zc ) then
806 ! tztr = 1.0/(1.0+c_0)-z*c_d/(1.0+c_0)
807 tztr = (1.0-z*c_d)/(1.0+c_0)
808 else
809 tztr = 1.0
810 endif
811 else
812 tztr = 1.0
813 endif
814
815 ! write(*,'(a,i4,9f9.4))') ' cal_tztr : ',kdt,xt,c_0,c_d,w_0,w_d,zc,zw,z,tztr
816 end subroutine cal_tztr
817
821 subroutine cool_skin(ustar_a,f_nsol,f_sol_0,evap,sss,alpha,beta,rho_w,rho_a,ts,q_ts,hl_ts,grav,le,deltat_c,z_c,c_0,c_d)
822 !
823 ! upper ocean cool-skin parameterizaion, fairall et al, 1996.
824 !
825 ! input:
826 ! ustar_a : atmosphreic friction velocity at the air-sea interface (m/s)
827 ! f_nsol : the "nonsolar" part of the surface heat flux (w/m^s)
828 ! f_sol_0 : solar radiation at the ocean surface (w/m^2)
829 ! evap : latent heat flux (w/m^2)
830 ! sss : ocean upper mixed layer salinity (ppu)
831 ! alpha : thermal expansion coefficient
832 ! beta : saline contraction coefficient
833 ! rho_w : oceanic density
834 ! rho_a : atmospheric density
835 ! ts : oceanic surface temperature
836 ! q_ts : d(q)/d(ts) : q = the sum of non-solar heat fluxes
837 ! hl_ts : d(hl)/d(ts)
838 ! grav : gravity
839 ! le :
840 !
841 ! output:
842 ! deltat_c: cool-skin temperature correction (degrees k)
843 ! z_c : molecular sublayer (cool-skin) thickness (m)
844 ! c_0 : coefficient1 to calculate d(tz)/d(ts)
845 ! c_d : coefficient2 to calculate d(tz)/d(ts)
846
847 !
848 real(kind=kind_phys), intent(in) :: ustar_a,f_nsol,f_sol_0,evap,sss,alpha,beta,rho_w,rho_a,ts,q_ts,hl_ts,grav,le
849 real(kind=kind_phys), intent(out) :: deltat_c,z_c,c_0,c_d
850 ! declare local variables
851 real(kind=kind_phys), parameter :: a1=0.065, a2=11.0, a3=6.6e-5, a4=8.0e-4, tcw=0.6, tcwi=1.0/tcw
852 real(kind=kind_phys) :: a_c,b_c,zc_ts,bc1,bc2
853 real(kind=kind_phys) :: xi,hb,ustar1_a,bigc,deltaf,fxp
854 real(kind=kind_phys) :: zcsq
855 real(kind=kind_phys) :: cc1,cc2,cc3
856
857
858 z_c = z_c_ini ! initial guess
859
860 ustar1_a = max(ustar_a,ustar_a_min)
861
862 call sw_rad_skin(z_c,fxp)
863 deltaf = f_sol_0*fxp
864
865 hb = alpha*(f_nsol-deltaf)+beta*sss*cp_w*evap/le
866 bigc = 16*grav*cp_w*(rho_w*visw)**3/(rho_a*rho_a*kw*kw)
867
868 if ( hb > 0 ) then
869 xi = 6./(1+(bigc*hb/ustar1_a**4)**0.75)**0.3333333
870 else
871 xi = 6.0
872 endif
873 z_c = min(z_c_max,xi*visw/(sqrt(rho_a/rho_w)*ustar1_a ))
874
875 call sw_rad_skin(z_c,fxp)
876
877 deltaf = f_sol_0*fxp
878 deltaf = f_nsol - deltaf
879 if ( deltaf > 0 ) then
880 deltat_c = deltaf * z_c / kw
881 else
882 deltat_c = zero
883 z_c = zero
884 endif
885 !
886 ! calculate c_0 & c_d
887 !
888 if ( z_c > zero ) then
889 cc1 = 6.0*visw / (tcw*ustar1_a*sqrt(rho_a/rho_w))
890 cc2 = bigc*alpha / max(ustar_a,ustar_a_min)**4
891 cc3 = beta*sss*cp_w/(alpha*le)
892 zcsq = z_c * z_c
893 a_c = a2 + a3/zcsq - (a3/(a4*z_c)+a3/zcsq) * exp(-z_c/a4)
894
895 if ( hb > zero .and. zcsq > zero .and. alpha > zero) then
896 bc1 = zcsq * (q_ts+cc3*hl_ts)
897 bc2 = zcsq * f_sol_0*a_c - 4.0*(cc1*tcw)**3*(hb/alpha)**0.25/(cc2**0.75*zcsq)
898 zc_ts = bc1/bc2
899 ! b_c = z_c**2*(q_ts+cc3*hl_ts)/(z_c**2*f_sol_0*a_c-4.0*(cc1*tcw)**3*(hb/alpha)**0.25/(cc2**0.75*z_c**2)) ! d(z_c)/d(ts)
900 b_c = (q_ts+cc3*hl_ts)/(f_sol_0*a_c &
901 - 4.0*(cc1*tcw)**3*(hb/alpha)**0.25/(cc2**0.75*zcsq*zcsq)) ! d(z_c)/d(ts)
902 c_0 = (z_c*q_ts+(f_nsol-deltaf-f_sol_0*a_c*z_c)*b_c)*tcwi
903 c_d = (f_sol_0*a_c*z_c*b_c-q_ts)*tcwi
904
905 else
906 b_c = zero
907 zc_ts = zero
908 c_0 = z_c*q_ts*tcwi
909 c_d = -q_ts*tcwi
910 endif
911
912 ! if ( c_0 < 0.0 ) then
913 ! write(*,'(a,2f12.6,10f10.6)') ' c_0, c_d = ',c_0,c_d,b_c,zc_ts,hb,bc1,bc2,z_c,cc1,cc2,cc3,z_c**2
914 ! endif
915
916 ! c_0 = z_c*q_ts/tcw
917 ! c_d = -q_ts/tcw
918
919 else
920 c_0 = zero
921 c_d = zero
922 endif ! if ( z_c > 0.0 ) then
923
924 end subroutine cool_skin
925 !
926 !======================
927 !
930 real function int_epn(z1,z2,zmx,ztr,n)
931 !
932 ! abstract: calculate a definitive integral of an exponetial curve (power of 2)
933 !
934 real(kind_phys) :: z1,z2,zmx,ztr,zi
935 real(kind_phys) :: fa,fb,fi,int
936 integer :: m,i,n
937
938 m = nint((z2-z1)/delz)
939 fa = exp(-exp_const*((z1-zmx)/(ztr-zmx))**n)
940 fb = exp(-exp_const*((z2-zmx)/(ztr-zmx))**n)
941 int = zero
942 do i = 1, m-1
943 zi = z1 + delz*float(i)
944 fi = exp(-exp_const*((zi-zmx)/(ztr-zmx))**n)
945 int = int + fi
946 enddo
947 int_epn = delz*((fa+fb)/2.0 + int)
948 end function int_epn
949
952 subroutine dtl_reset_cv(xt,xs,xu,xv,xz)
953 real(kind=kind_phys), intent(inout) :: xt,xs,xu,xv,xz
954 xt = zero
955 xs = zero
956 xu = zero
957 xv = zero
958 xz = z_w_max
959 end subroutine dtl_reset_cv
960
963 subroutine dtl_reset(xt,xs,xu,xv,xz,xzts,xtts)
964 real(kind=kind_phys), intent(inout) :: xt,xs,xu,xv,xz,xzts,xtts
965 xt = zero
966 xs = zero
967 xu = zero
968 xv = zero
969 xz = z_w_max
970 xtts = zero
971 xzts = zero
972 end subroutine dtl_reset
973
974end module nst_module
subroutine, public convdepth(kdt, timestep, i0, q, sss, sep, rho, alpha, beta, xt, xs, xz, d_conv)
This subroutine calculates depth for convective adjustment.
subroutine, public dtm_1p_mwa(xt, xtts, xz, xzts)
This subroutine applies maximum warming adjustment (mwa).
subroutine, public dtm_1p_fca(d_conv, xt, xtts, xz, xzts)
This subroutine applies free convection adjustment(fca).
subroutine, public cal_ttop(kdt, timestep, q_warm, rho, dz, xt, xz, ttop)
This subroutine calculates the diurnal warming amount at the top layer with thickness of delz.
subroutine, public dtm_1p_mta(dta, xt, xtts, xz, xzts)
This subroutine applies maximum temperature adjustment (mta).
subroutine, public dtm_1p(kdt, timestep, rich, tox, toy, i0, q, sss, sep, q_ts, hl_ts, rho, alpha, beta, alon, sinlat, soltim, grav, le, d_conv, xt, xs, xu, xv, xz, xzts, xtts)
This subroutine contains the module of diurnal thermocline layer model.
subroutine, public dtm_1p_mda(xt, xtts, xz, xzts)
This subroutine applies minimum depth adjustment (xz adjustment).
subroutine, public dtl_reset(xt, xs, xu, xv, xz, xzts, xtts)
This subroutine resets the value of xt,xs,xu,xv,xz,xtts,xzts.
subroutine, public dtm_1p_tla(dz, te, xt, xtts, xz, xzts)
This subroutine applies top layer adjustment (tla).
subroutine, public cal_w(kdt, xz, xt, xzts, xtts, w_0, w_d)
This subroutine computes coefficients (w_0 and w_d) to calculate d(tw)/d(ts).
subroutine, public cool_skin(ustar_a, f_nsol, f_sol_0, evap, sss, alpha, beta, rho_w, rho_a, ts, q_ts, hl_ts, grav, le, deltat_c, z_c, c_0, c_d)
This subroutine contains the upper ocean cool-skin parameterization (Fairall et al,...
This module contains constants and parameters used in GFS near surface sea temperature scheme.
This module contains GFS NSST water property subroutines.
This module contains the diurnal thermocline layer model (DTM) of the GFS NSST scheme.