/[MITgcm]/MITgcm/pkg/atm_phys/surface_flux_mod.F90
ViewVC logotype

Contents of /MITgcm/pkg/atm_phys/surface_flux_mod.F90

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (show annotations) (download)
Wed May 8 22:14:15 2013 UTC (11 years, 4 months ago) by jmc
Branch: MAIN
CVS Tags: checkpoint64y, checkpoint64x, checkpoint64z, checkpoint64o, checkpoint64q, checkpoint64p, checkpoint64s, checkpoint64r, checkpoint64u, checkpoint64t, checkpoint64w, checkpoint64v, checkpoint66g, checkpoint66f, checkpoint66e, checkpoint66d, checkpoint66c, checkpoint66b, checkpoint66a, checkpoint64n, checkpoint66i, checkpoint66h, checkpoint65z, checkpoint65x, checkpoint65y, checkpoint65r, checkpoint65s, checkpoint65p, checkpoint65q, checkpoint65v, checkpoint65w, checkpoint65t, checkpoint65u, checkpoint65j, checkpoint65k, checkpoint65h, checkpoint65i, checkpoint65n, checkpoint65o, checkpoint65l, checkpoint65m, checkpoint65b, checkpoint65c, checkpoint65a, checkpoint65f, checkpoint65g, checkpoint65d, checkpoint65e, checkpoint64i, checkpoint64h, checkpoint64k, checkpoint65, checkpoint64j, checkpoint64m, checkpoint64l
add source code for new pkg "atm_phys" (atmospheric physics pkg
  from P. O'Gorman and T. Schneider, JCl, 2008).

1 ! $Header: $
2 ! $Name: $
3
4 ! ============================================================================
5 module surface_flux_mod
6 ! ============================================================================
7
8 ! use fms_mod, only: FATAL, close_file, mpp_pe, mpp_root_pe, &
9 ! write_version_number
10 ! use fms_mod, only: file_exist, check_nml_error, open_namelist_file, stdlog
11
12 use monin_obukhov_mod, only: mo_drag, mo_profile
13 use simple_sat_vapor_pres_mod, only: escomp, descomp
14 use gcm_params_mod, only: gcm_LEN_MBUF, gcm_SQZ_R, gcm_stdMsgUnit
15 use constants_mod, only: cp_air, hlv, stefan, rdgas, rvgas, grav
16
17 implicit none
18 private
19
20 ! ==== public interface ======================================================
21 public surface_flux
22 ! ==== end of public interface ===============================================
23
24
25 interface surface_flux
26 ! module procedure surface_flux_0d
27 ! module procedure surface_flux_1d
28 module procedure surface_flux_2d
29 end interface
30
31 !-----------------------------------------------------------------------
32
33 character(len=*), parameter :: version = '$Id: surface_flux_mod.F90,v 1.1 2012/09/11 03:53:05 jmc Exp $'
34 character(len=*), parameter :: tagname = '$Name: $'
35
36 logical :: do_init = .true.
37
38 real, parameter :: d622 = rdgas/rvgas
39 real, parameter :: d378 = 1.-d622
40 real, parameter :: hlars = hlv/rvgas
41 real, parameter :: gcp = grav/cp_air
42 real, parameter :: kappa = rdgas/cp_air
43 real :: d608 = d378/d622
44 ! d608 set to zero at initialization if the use of
45 ! virtual temperatures is turned off in namelist
46
47
48 ! ---- namelist with default values ------------------------------------------
49 logical :: no_neg_q = .false. ! for backwards compatibility
50 logical :: use_virtual_temp = .true.
51 logical :: alt_gustiness = .false.
52 logical :: use_mixing_ratio = .false.
53 real :: gust_const = 1.0
54
55 namelist /surface_flux_nml/ no_neg_q, &
56 use_virtual_temp, &
57 alt_gustiness, &
58 gust_const, &
59 use_mixing_ratio
60
61
62
63 contains
64
65
66 ! ============================================================================
67 subroutine surface_flux_1d ( &
68 t_atm, q_atm_in, u_atm, v_atm, p_atm, z_atm, &
69 p_surf, t_surf, t_ca, q_surf, &
70 u_surf, v_surf, &
71 rough_mom, rough_heat, rough_moist, gust, &
72 flux_t, flux_q, flux_r, flux_u, flux_v, &
73 cd_m, cd_t, cd_q, &
74 w_atm, u_star, b_star, q_star, &
75 dhdt_surf, dedt_surf, dedq_surf, drdt_surf, &
76 dhdt_atm, dedq_atm, dtaudv_atm, &
77 ! + slm Mar 28 2002 -- it is not necessary here since it is just cd_q*wind
78 ! drag_q, &
79 ! - slm Mar 28 2002
80 dt, land, avail, myThid )
81 ! ============================================================================
82 ! ---- arguments -----------------------------------------------------------
83 logical, intent(in), dimension(:) :: land, avail
84 real, intent(in), dimension(:) :: &
85 t_atm, q_atm_in, u_atm, v_atm, &
86 p_atm, z_atm, t_ca, &
87 p_surf, t_surf, u_surf, v_surf, &
88 rough_mom, rough_heat, rough_moist, gust
89 real, intent(out), dimension(:) :: &
90 flux_t, flux_q, flux_r, flux_u, flux_v, &
91 dhdt_surf, dedt_surf, dedq_surf, drdt_surf, &
92 dhdt_atm, dedq_atm, dtaudv_atm, &
93 w_atm, u_star, b_star, q_star, &
94 cd_m, cd_t, cd_q
95 real, intent(inout), dimension(:) :: q_surf
96 real, intent(in) :: dt
97 integer, intent(in) :: myThid
98
99 ! ---- local constants -----------------------------------------------------
100 ! temperature increment and its reciprocal value for comp. of derivatives
101 real, parameter:: del_temp=0.1, del_temp_inv=1.0/del_temp
102
103 ! ---- local vars ----------------------------------------------------------
104 real, dimension(size(t_atm)) :: &
105 thv_atm, th_atm, tv_atm, thv_surf, &
106 e_sat, e_sat1, q_sat, q_sat1, p_ratio, &
107 t_surf0, t_surf1, u_dif, v_dif, &
108 rho_drag, drag_t, drag_m, drag_q, rho, &
109 q_atm, q_surf0
110
111 integer :: i, nbad
112
113
114 if (do_init) call surface_flux_init(myThid)
115
116 !---- use local value of surf temp ----
117
118 t_surf0 = 200. ! avoids out-of-bounds in es lookup
119 where (avail)
120 where (land)
121 t_surf0 = t_ca
122 elsewhere
123 t_surf0 = t_surf
124 endwhere
125 endwhere
126
127 t_surf1 = t_surf0 + del_temp
128
129 call escomp ( t_surf0, e_sat ) ! saturation vapor pressure
130 call escomp ( t_surf1, e_sat1 ) ! perturbed vapor pressure
131
132 if(use_mixing_ratio) then
133 ! surface mixing ratio at saturation
134 q_sat = d622*e_sat /(p_surf-e_sat )
135 q_sat1 = d622*e_sat1/(p_surf-e_sat1)
136 else
137 ! surface specific humidity at saturation
138 q_sat = d622*e_sat /(p_surf-d378*e_sat )
139 q_sat1 = d622*e_sat1/(p_surf-d378*e_sat1)
140 endif
141
142 ! initilaize surface air humidity according to surface type
143 where (land)
144 q_surf0 = q_surf ! land calculates it
145 elsewhere
146 q_surf0 = q_sat ! everything else assumes saturated sfc humidity
147 endwhere
148
149 ! check for negative atmospheric humidities
150 where(avail) q_atm = q_atm_in
151 if(no_neg_q) then
152 where(avail .and. q_atm_in < 0.0) q_atm = 0.0
153 endif
154
155 ! generate information needed by monin_obukhov
156 where (avail)
157 p_ratio = (p_surf/p_atm)**kappa
158
159 tv_atm = t_atm * (1.0 + d608*q_atm) ! virtual temperature
160 th_atm = t_atm * p_ratio ! potential T, using p_surf as refernce
161 thv_atm = tv_atm * p_ratio ! virt. potential T, using p_surf as reference
162 thv_surf= t_surf0 * (1.0 + d608*q_surf0 ) ! surface virtual (potential) T
163 ! thv_surf= t_surf0 ! surface virtual (potential) T -- just for testing tun off the q_surf
164
165 u_dif = u_surf - u_atm ! velocity components relative to surface
166 v_dif = v_surf - v_atm
167 endwhere
168
169 if(alt_gustiness) then
170 where(avail) &
171 w_atm = max(sqrt(u_dif*u_dif + v_dif*v_dif), gust_const)
172 else
173 where(avail) &
174 w_atm = sqrt(u_dif*u_dif + v_dif*v_dif + gust*gust)
175 endif
176
177 ! monin-obukhov similarity theory
178 call mo_drag (thv_atm, thv_surf, z_atm, &
179 rough_mom, rough_heat, rough_moist, w_atm, &
180 cd_m, cd_t, cd_q, u_star, b_star, myThid, avail )
181
182
183 where (avail)
184 ! surface layer drag coefficients
185 drag_t = cd_t * w_atm
186 drag_q = cd_q * w_atm
187 drag_m = cd_m * w_atm
188
189 ! density
190 rho = p_atm / (rdgas * tv_atm)
191
192 ! sensible heat flux
193 rho_drag = cp_air * drag_t * rho
194 flux_t = rho_drag * (t_surf0 - th_atm) ! flux of sensible heat (W/m**2)
195 dhdt_surf = rho_drag ! d(sensible heat flux)/d(surface temperature)
196 dhdt_atm = -rho_drag*p_ratio ! d(sensible heat flux)/d(atmos temperature)
197
198 ! evaporation
199 rho_drag = drag_q * rho
200 flux_q = rho_drag * (q_surf0 - q_atm) ! flux of water vapor (Kg/(m**2 s))
201 where (land)
202 dedq_surf = rho_drag
203 dedt_surf = 0
204 elsewhere
205 dedq_surf = 0
206 dedt_surf = rho_drag * (q_sat1 - q_sat) *del_temp_inv
207 endwhere
208
209 dedq_atm = -rho_drag ! d(latent heat flux)/d(atmospheric mixing ratio)
210
211 q_star = flux_q / (u_star * rho) ! moisture scale
212 ! ask Chris and Steve K if we still want to keep this for diagnostics
213 q_surf = q_atm + flux_q / (rho*cd_q*w_atm) ! surface specific humidity
214
215 ! upward long wave radiation
216 flux_r = stefan*t_surf**4 ! (W/m**2)
217 drdt_surf = 4*stefan*t_surf**3 ! d(upward longwave)/d(surface temperature)
218
219 ! stresses
220 rho_drag = drag_m * rho
221 flux_u = rho_drag * u_dif ! zonal component of stress (Nt/m**2)
222 flux_v = rho_drag * v_dif ! meridional component of stress
223 dtaudv_atm = -rho_drag ! d(stress component)/d(atmos wind)
224
225 elsewhere
226 ! zero-out un-available data in output only fields
227 flux_t = 0.0
228 flux_q = 0.0
229 flux_r = 0.0
230 flux_u = 0.0
231 flux_v = 0.0
232 dhdt_surf = 0.0
233 dedt_surf = 0.0
234 dedq_surf = 0.0
235 drdt_surf = 0.0
236 dhdt_atm = 0.0
237 dedq_atm = 0.0
238 dtaudv_atm = 0.0
239 u_star = 0.0
240 b_star = 0.0
241 q_star = 0.0
242 q_surf = 0.0
243 w_atm = 0.0
244 endwhere
245
246 end subroutine surface_flux_1d
247
248 !#######################################################################
249
250 subroutine surface_flux_0d ( &
251 t_atm_0, q_atm_0, u_atm_0, v_atm_0, p_atm_0, z_atm_0, &
252 p_surf_0, t_surf_0, t_ca_0, q_surf_0, &
253 u_surf_0, v_surf_0, &
254 rough_mom_0, rough_heat_0, rough_moist_0, gust_0, &
255 flux_t_0, flux_q_0, flux_r_0, flux_u_0, flux_v_0, &
256 cd_m_0, cd_t_0, cd_q_0, &
257 w_atm_0, u_star_0, b_star_0, q_star_0, &
258 dhdt_surf_0, dedt_surf_0, dedq_surf_0, drdt_surf_0, &
259 dhdt_atm_0, dedq_atm_0, dtaudv_atm_0, &
260 dt, land_0, avail_0, myThid )
261
262 ! ---- arguments -----------------------------------------------------------
263 logical, intent(in) :: land_0, avail_0
264 real, intent(in) :: &
265 t_atm_0, q_atm_0, u_atm_0, v_atm_0, &
266 p_atm_0, z_atm_0, t_ca_0, &
267 p_surf_0, t_surf_0, u_surf_0, v_surf_0, &
268 rough_mom_0, rough_heat_0, rough_moist_0, gust_0
269 real, intent(out) :: &
270 flux_t_0, flux_q_0, flux_r_0, flux_u_0, flux_v_0, &
271 dhdt_surf_0, dedt_surf_0, dedq_surf_0, drdt_surf_0, &
272 dhdt_atm_0, dedq_atm_0, dtaudv_atm_0, &
273 w_atm_0, u_star_0, b_star_0, q_star_0, &
274 cd_m_0, cd_t_0, cd_q_0
275 real, intent(inout) :: q_surf_0
276 real, intent(in) :: dt
277 integer, intent(in) :: myThid
278
279 ! ---- local vars ----------------------------------------------------------
280 logical, dimension(1) :: land, avail
281 real, dimension(1) :: &
282 t_atm, q_atm, u_atm, v_atm, &
283 p_atm, z_atm, t_ca, &
284 p_surf, t_surf, u_surf, v_surf, &
285 rough_mom, rough_heat, rough_moist, gust
286 real, dimension(1) :: &
287 flux_t, flux_q, flux_r, flux_u, flux_v, &
288 dhdt_surf, dedt_surf, dedq_surf, drdt_surf, &
289 dhdt_atm, dedq_atm, dtaudv_atm, &
290 w_atm, u_star, b_star, q_star, &
291 cd_m, cd_t, cd_q
292 real, dimension(1) :: q_surf
293
294
295 avail = .true.
296
297 t_atm(1) = t_atm_0
298 q_atm(1) = q_atm_0
299 u_atm(1) = u_atm_0
300 v_atm(1) = v_atm_0
301 p_atm(1) = p_atm_0
302 z_atm(1) = z_atm_0
303 p_surf(1) = p_surf_0
304 t_surf(1) = t_surf_0
305 u_surf(1) = u_surf_0
306 v_surf(1) = v_surf_0
307 rough_mom(1) = rough_mom_0
308 rough_heat(1) = rough_heat_0
309 rough_moist(1) = rough_moist_0
310 gust(1) = gust_0
311
312 call surface_flux_1d ( &
313 t_atm, q_atm, u_atm, v_atm, p_atm, z_atm, &
314 p_surf, t_surf, t_ca, q_surf, &
315 u_surf, v_surf, &
316 rough_mom, rough_heat, rough_moist, gust, &
317 flux_t, flux_q, flux_r, flux_u, flux_v, &
318 cd_m, cd_t, cd_q, &
319 w_atm, u_star, b_star, q_star, &
320 dhdt_surf, dedt_surf, dedq_surf, drdt_surf, &
321 dhdt_atm, dedq_atm, dtaudv_atm, &
322 dt, land, avail, myThid )
323
324 flux_t_0 = flux_t(1)
325 flux_q_0 = flux_q(1)
326 flux_r_0 = flux_r(1)
327 flux_u_0 = flux_u(1)
328 flux_v_0 = flux_v(1)
329 dhdt_surf_0 = dhdt_surf(1)
330 dedt_surf_0 = dedt_surf(1)
331 drdt_surf_0 = drdt_surf(1)
332 dedq_surf_0 = dedq_surf(1)
333 dhdt_atm_0 = dhdt_atm(1)
334 dedq_atm_0 = dedq_atm(1)
335 dtaudv_atm_0 = dtaudv_atm(1)
336 w_atm_0 = w_atm(1)
337 u_star_0 = u_star(1)
338 b_star_0 = b_star(1)
339 q_star_0 = q_star(1)
340 q_surf_0 = q_surf(1)
341 cd_m_0 = cd_m(1)
342 cd_t_0 = cd_t(1)
343 cd_q_0 = cd_q(1)
344
345 end subroutine surface_flux_0d
346
347 subroutine surface_flux_2d ( &
348 t_atm, q_atm_in, u_atm, v_atm, p_atm, z_atm, &
349 p_surf, t_surf, t_ca, q_surf, &
350 u_surf, v_surf, &
351 rough_mom, rough_heat, rough_moist, gust, &
352 flux_t, flux_q, flux_r, flux_u, flux_v, &
353 cd_m, cd_t, cd_q, &
354 w_atm, u_star, b_star, q_star, &
355 dhdt_surf, dedt_surf, dedq_surf, drdt_surf, &
356 dhdt_atm, dedq_atm, dtaudv_atm, &
357 dt, land, avail, myThid )
358
359 ! ---- arguments -----------------------------------------------------------
360 logical, intent(in), dimension(:,:) :: land, avail
361 real, intent(in), dimension(:,:) :: &
362 t_atm, q_atm_in, u_atm, v_atm, &
363 p_atm, z_atm, t_ca, &
364 p_surf, t_surf, u_surf, v_surf, &
365 rough_mom, rough_heat, rough_moist, gust
366 real, intent(out), dimension(:,:) :: &
367 flux_t, flux_q, flux_r, flux_u, flux_v, &
368 dhdt_surf, dedt_surf, dedq_surf, drdt_surf, &
369 dhdt_atm, dedq_atm, dtaudv_atm, &
370 w_atm, u_star, b_star, q_star, &
371 cd_m, cd_t, cd_q
372 real, intent(inout), dimension(:,:) :: q_surf
373 real, intent(in) :: dt
374 integer, intent (in) :: myThid
375
376 ! ---- local vars -----------------------------------------------------------
377 integer :: j
378 do j = 1, size(t_atm,2)
379 call surface_flux_1d ( &
380 t_atm(:,j), q_atm_in(:,j), u_atm(:,j), v_atm(:,j), p_atm(:,j), z_atm(:,j), &
381 p_surf(:,j), t_surf(:,j), t_ca(:,j), q_surf(:,j), &
382 u_surf(:,j), v_surf(:,j), &
383 rough_mom(:,j), rough_heat(:,j), rough_moist(:,j), gust(:,j), &
384 flux_t(:,j), flux_q(:,j), flux_r(:,j), flux_u(:,j), flux_v(:,j), &
385 cd_m(:,j), cd_t(:,j), cd_q(:,j), &
386 w_atm(:,j), u_star(:,j), b_star(:,j), q_star(:,j), &
387 dhdt_surf(:,j), dedt_surf(:,j), dedq_surf(:,j), drdt_surf(:,j), &
388 dhdt_atm(:,j), dedq_atm(:,j), dtaudv_atm(:,j), &
389 dt, land(:,j), avail(:,j), myThid )
390 end do
391 end subroutine surface_flux_2d
392
393
394 ! ============================================================================
395 subroutine surface_flux_init (myThid)
396 ! ============================================================================
397 ! initializes surface flux module
398 ! ---- local vars ----------------------------------------------------------
399 integer, intent(in) :: myThid
400 integer :: unit, ierr, io
401 !-- added:
402 integer :: iUnit
403 CHARACTER*(gcm_LEN_MBUF) :: msgBuf
404
405 ! read namelist
406
407 ! _BARRIER
408 ! _BEGIN_MASTER(myThid)
409 CALL BARRIER(myThid)
410 IF ( myThid.EQ.1 ) THEN
411
412 WRITE(msgBuf,'(A)') 'SURFACE_FLUX_INIT: opening data.atm_gray'
413 CALL PRINT_MESSAGE( msgBuf, gcm_stdMsgUnit, gcm_SQZ_R, myThid )
414 CALL OPEN_COPY_DATA_FILE( &
415 'data.atm_gray', 'SURFACE_FLUX_INIT', &
416 iUnit, &
417 myThid )
418 ! Read parameters from open data file
419 READ(UNIT=iUnit,NML=surface_flux_nml)
420 WRITE(msgBuf,'(A)') &
421 'SURFACE_FLUX_INIT: finished reading data.atm_gray'
422 CALL PRINT_MESSAGE( msgBuf, gcm_stdMsgUnit, gcm_SQZ_R, myThid )
423 ! Close the open data file
424 CLOSE(iUnit)
425
426 ! if ( file_exist('input.nml')) then
427 ! unit = open_namelist_file ()
428 ! ierr=1;
429 ! do while (ierr /= 0)
430 ! read (unit, nml=surface_flux_nml, iostat=io, end=10)
431 ! ierr = check_nml_error(io,'surface_flux_nml')
432 ! enddo
433 !10 call close_file (unit)
434 ! endif
435
436 ! ! write version number
437 ! call write_version_number(version, tagname)
438
439 ! if ( mpp_pe() == mpp_root_pe() ) write (stdlog(), nml=surface_flux_nml)
440
441
442 ! if(.not. use_virtual_temp) d608 = 0.0
443
444 do_init = .false.
445
446 ENDIF
447 CALL BARRIER (myThid)
448
449 end subroutine surface_flux_init
450
451
452 end module surface_flux_mod

  ViewVC Help
Powered by ViewVC 1.1.22