← Back to Documentation Home
CCPP SciDoc v8.0.0  v8.0.0
Common Community Physics Package Developed at DTC
 
Loading...
Searching...
No Matches
canopy_levs.F90
1 module canopy_levs_mod
2 contains
3
4!:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
5
6 subroutine canopy_levs_init(im, km, nkc, nkt, &
7 ntrac, ntqv, ntke, & ! ndtend, &
8 zi, zl, zm, & ! in: 3D meters
9 prsl, prsi, & ! in: 3D (Pa)
10 dv, du, tdt, rtg, & ! in: 3D
11 u1, v1, t1, q1, & ! in: 3D " 4D q1(ix,km,ntrac1) kg kg-1
12 dens, dkt, dku, & ! in: 3D
13! dtend, & ! in: 4D
14 zmom_can3, zmid_can3, & !out: 3D
15 sigmom_can, sigmid_can, & !out
16 zl_can, zm_can, & !out
17 prsl_can, prsi_can, & !out
18 dv_can, du_can, tdt_can, rtg_can, & !out: 3D
19 t1_can, qv_can, dens_can, & !out
20 ws_can, dkt_can, dku_can, & !out
21 q1_can, q1_2m, & !out
22! DTEND_CAN, &
23 errmsg, errflg ) !out
24
25 use machine , only : kind_phys
26
27 IMPLICIT NONE
28
29!...Arguments:
30 integer, intent(in) :: im, km, nkc, nkt, ntrac, ntqv, ntke !, ndtend
31
32 real(kind=kind_phys), intent(in) :: zi(im, km+1), zl(im, km), &
33 zm(im, km), &
34 prsi(im, km+1), prsl(im, km)
35 real(kind=kind_phys), intent(in) :: dv(im, km), du(im, km), &
36 tdt(im, km), rtg(im, km,ntrac)
37 real(kind=kind_phys), intent(in) :: u1(im, km), v1(im, km), t1(im,km)
38 real(kind=kind_phys), intent(in) :: dens(im, km), dkt(im, km), dku(im,km)
39! real(kind=kind_phys), intent(in) :: dtend(im, km , ndtend)
40
41! ** Q1 is concentration field (including gas and aerosol variables) mass mixing ratio kg kg-1
42 real(kind=kind_phys), intent(in) :: q1(im, km, ntrac)
43
44 real(kind=kind_phys), intent(out) :: &
45! tendencies
46! DTEND_CAN (im, km , ndtend), &
47 dv_can(im, km) , &
48 du_can(im, km) , &
49 tdt_can(im, km) , &
50! tendencies all gas-phase species & TKE
51 rtg_can(im, km, ntrac) , &
52
53! met3d arrays
54 zl_can(im, nkt) , & ! dim(nkt)
55 zm_can(im, nkt) , & ! dim(nkt)
56 t1_can(im, nkt) , & ! dim(nkt)
57 qv_can(im, nkt) , & ! dim(nkt)
58 ws_can(im, nkt) , & ! dim(nkt)
59 prsl_can(im, nkt) , & ! dim(nkt)
60 prsi_can(im, nkt+1) , & ! dim(nkt+1)
61 dens_can(im, nkt) , & ! dim(nkt)
62 dkt_can(im, nkt) , & ! dim(nkt)
63 dku_can(im, nkt) , & ! dim(nkt)
64! all gas-phase species array
65 q1_can(im, nkt, ntrac) , & ! dim(nkt)
66 q1_2m(im, ntrac) , & !
67! canopy layers height arrays
68 zmom_can3(im, nkt+1) , & ! dim(nkt+1) ! Paul's sigmcan(:,nkt+1)
69 zmid_can3(im, nkt) , & ! dim(nkt) ! Paul's sigtcan(:,nkt+1)
70 sigmom_can(im, nkt+1) , & ! dim(nkt) ~ prsi(:,km+1)
71 sigmid_can(im, nkt) ! dim(nkt) ~ prsl(:,km)
72
73 character(len=*), intent(out) :: errmsg
74 integer, intent(out) :: errflg
75
76!...local variables
77
78 integer :: k, kc
79
80! Initialize CCPP error handling variables
81 errmsg = ''
82 errflg = 0
83
84! Initialize with values before in-canopy diffusion
85
86! Layers height
87 zmom_can3(:,:) = 0.
88 zmid_can3(:,:) = 0.
89 sigmom_can(:,:) = 0.
90 sigmid_can(:,:) = 0.
91
92! Zero in-canopy tendencies
93! dtend_can(:, :, : ) = 0.0
94
95! Tracers
96 q1_2m(:, :) = q1(:,1, :) ! kg kg-1
97
98! Subset (km combined layers minus top nkc layers)
99 do k = 1, km-nkc
100
101 ! km is top combined subset
102 ! nkc+1 is bot combined
103 kc= nkc+k ! 4th from top (nkt) to nkc+1 combined canopy plus resolved model layer
104
105! Tendencies
106 du_can(:,kc) = du(:,k) ! m s-2
107 dv_can(:,kc) = dv(:,k) ! m s-2
108 tdt_can(:,kc) = tdt(:,k) ! K s-1
109
110 rtg_can(:,kc, 1:ntrac-1) = rtg(:,k, 1:ntrac-1) ! kg kg-1 s-1
111 rtg_can(:,kc, ntke ) = rtg(:,k, ntke ) ! J s-1 s-1
112
113 end do
114
115! All combined canopy plus resolved layers
116 do k = 1, km
117
118 ! nkc+km is top (nkt) combined
119 ! nkc+1 is bot combined
120 kc= nkc+k ! top (nkt) to nkc+1 combined canopy plus resolved model layer
121
122! Height
123 zl_can(:,kc) = zl(:,k)
124 zm_can(:,kc) = zm(:,k)
125
126! Pressure & temperature
127 prsl_can(:,kc) = prsl(:,k) ! km combined canopy plus resolved layers
128 prsi_can(:,kc) = prsi(:,k) ! km combined canopy plus resolved layers
129 t1_can(:,kc) = t1(:,k)
130 dens_can(:,kc) = dens(:,k)
131
132! Diffusivities
133 dkt_can(:,kc) = dkt(:,k) ! m2 s-1
134 dku_can(:,kc) = dku(:,k) ! m2 s-1
135
136! Wind
137 ws_can(:,kc) = sqrt(u1(:,k)**2+v1(:,k)**2) ! m s-1
138
139! Mass tracers
140 q1_can(:,kc, 1:ntrac-1) = q1(:,k, 1:ntrac-1) ! all tracers ntrac1
141
142! TKE tracer
143 q1_can(:,kc, ntke ) = q1(:,k, ntke ) ! ntke=198 TKE tracer
144
145! Humidity
146 qv_can(:,kc) = q1(:,k, ntqv) ! ntqv=1
147
148 end do
149 prsi_can(:,km + nkc +1 ) = prsi(:,km+1) ! nkt combined canopy plus resolved layers
150
151! Canopy layers
152 do kc = 1, nkc ! 3-nkc canopy layers
153
154! Tendencies
155 du_can(:,kc) = du(:,1) ! m s-2
156 dv_can(:,kc) = dv(:,1) ! m s-2
157 tdt_can(:,kc) = tdt(:,1) ! K s-1
158
159 rtg_can(:,kc, 1:ntrac-1) = rtg(:,1, 1:ntrac-1) ! kg kg-1 s-1
160 rtg_can(:,kc, ntke ) = rtg(:,1, ntke ) ! J s-1 s-1
161
162! Height
163 zl_can(:,kc) = zl(:,1)
164 zm_can(:,kc) = zm(:,1)
165
166! Pressure & temperature
167 prsl_can(:,kc) = prsl(:,1) ! km combined canopy plus resolved layers
168 prsi_can(:,kc) = prsi(:,1) ! km combined canopy plus resolved layers
169 t1_can(:,kc) = t1(:,1)
170 dens_can(:,kc) = dens(:,1)
171
172! Diffusivities
173 dkt_can(:,kc) = dkt(:,1) ! m2 s-1
174 dku_can(:,kc) = dku(:,1) ! m2 s-1
175
176! Wind
177 ws_can(:,kc) = sqrt(u1(:,1)**2+v1(:,1)**2) ! m s-1
178
179! Mass tracers
180 q1_can(:,kc, 1:ntrac-1) = q1(:,1, 1:ntrac-1) ! all tracers ntrac1
181
182! TKE tracer
183 q1_can(:,kc, ntke ) = q1(:,1, ntke ) ! ntke=198 TKE tracer
184
185! Water vapor
186 qv_can(:,kc) = q1(:,1, ntqv) ! ntqv=1
187
188 end do
189
190 end subroutine canopy_levs_init
191
192!:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
193
194 subroutine canopy_levs_run(im, km, nkc, nkt, &
195 ntrac, ntqv, ntke, & ! in
196 RDGAS, PI, & ! in ?? units ??
197 zi, zl, zm, & ! in: 1D zm(i,k) = zi(i,k+1)
198 prsl, prsi, psfc, & ! in: 3D 3D 2D (Pa)
199 cfch, & ! in: 2D
200 garea, u10m, v10m, fm,fh, & ! in: 2D
201 rbsoil, & ! in: 2D
202 t2m, q2m, & ! in: 2D
203 stress, spd1, & ! in: 2D
204 dv, du, tdt, rtg, & ! in: 3D
205 u1, v1, t1, q1, & ! in: 3D " 4D
206 dens, dkt, dku, & ! in 3D
207 frt_mask, & ! in 2D
208 kmod, kcan3, & ! out
209 zmom_can3, zmid_can3, & ! out zmom_can3(:, nkt+1) zmid_can3(im, nkt)
210 sigmom_can, sigmid_can, & ! out 3D sigmom_can (:, nkt+1) sigmid_can (im, nkt)
211 zl_can, zm_can, & ! out 3D
212 prsl_can, prsi_can, & ! out 3D prsi_can (:, nkt+1)
213 dv_can, du_can, tdt_can, rtg_can, & ! out: 3D
214 t1_can, qv_can, dens_can, & ! out 3D
215 ws_can, dkt_can, dku_can, & ! out 3D
216 q1_can, q1_2m, & !out
217 errmsg,errflg)
218
219 use machine , only : kind_phys
220
221 IMPLICIT NONE
222
223! Includes:
224
225!...Arguments:
226
227 integer, intent(in) :: im, km, nkc, nkt, ntrac, ntqv, ntke
228 real(kind=kind_phys), intent(in) :: rdgas, pi
229
230 real(kind=kind_phys), intent(in) :: zi(im,km+1), zl(im,km), &
231 zm(im,km), &
232 prsi(im,km+1), prsl(im,km)
233 real(kind=kind_phys), intent(in) :: dv(im,km), du(im,km), &
234 tdt(im,km), rtg(im,km,ntrac)
235
236 real(kind=kind_phys), intent(in) :: u1(im,km), v1(im,km), t1(im,km)
237 real(kind=kind_phys), intent(in) :: dens(im,km), dkt(im,km), dku(im,km)
238
239 real(kind=kind_phys), intent(in) :: psfc(im) ! Pa
240 real(kind=kind_phys), intent(in) :: cfch(im), garea(im), u10m(im), v10m(im), &
241 spd1(im),stress(im), &
242 t2m(im), q2m(im), fm(im), fh(im), &
243 rbsoil(im)
244
245! ** Q1 is concentration field (including gas and aerosol variables) kg kg-1
246 real(kind=kind_phys), intent(in) :: q1(im, km, ntrac)
247
248 real(kind=kind_phys), intent(in) :: frt_mask(im)
249
250 integer, intent(out) :: kmod (im, km) , kcan3 (im, nkc)
251
252 real(kind=kind_phys), intent(out) :: &
253! tendencies
254 dv_can(im, km) , &
255 du_can(im, km) , &
256 tdt_can(im, km) , &
257! tendencies all gas-phase species & TKE
258 rtg_can(im, km, ntrac) , &
259! met3d arrays
260 zl_can(im, nkt) , &
261 zm_can(im, nkt) , &
262 t1_can(im, nkt) , &
263 qv_can(im, nkt) , &
264 ws_can(im, nkt) , &
265 prsl_can(im, nkt) , &
266 prsi_can(im, nkt+1) , &
267 dens_can(im, nkt) , &
268 dkt_can(im, nkt) , &
269 dku_can(im, nkt) , &
270! all gas-phase species array
271 q1_can(im, nkt, ntrac) , &
272 q1_2m(im, ntrac) , &
273! canopy layers height arrays
274 zmom_can3(im, nkt+1) , & ! Paul's sigmcan(:,nkt)
275 zmid_can3(im, nkt) , & ! Paul's sigtcan(:,nkt)
276 sigmom_can(im, nkt+1) , & ! ~ prsi(:,km+1)
277 sigmid_can(im, nkt) ! ~ prsl(:,km)
278
279 character(len=*), intent(out) :: errmsg
280 integer, intent(out) :: errflg
281
282!...Local arrays:
283
284 integer(kind=4) :: kcan_top
285 real (kind=kind_phys) :: hcan
286
287 logical :: sfcflg(im)
288
289 integer(kind=4) :: ka (im) , &
290 kl (im)
291
292 real(kind=kind_phys) :: zmid3(km) , &
293 zmom3(km) , & ! Paul's zfull
294 sigmom3(km+1), &
295 z2(km+1), & ! Paul's z2(:,chm_nk+1)
296 sigmid2(km+1), & ! Paul's sigt2(:,chm_nk+1)
297 zcan3(nkc), &
298 ta_can3(nkt), ta3(km) , &
299 qv_can3(nkt), qv3(km) , &
300 ws_can3(nkt), ws3(km) , &
301 dkt_can3(nkt), dkt3(km) , &
302 dku_can3(nkt), dku3(km) , &
303 prsl_can3(nkt), prsl3(km) , &
304 prsi_can3(nkt+1), prsi3(km+1), &
305 dens_can3(nkt), dens3(km) , &
306 mol3(km) , &
307 klower_can(nkc)
308
309 real(kind=kind_phys) :: &
310 dxdy(im), ustar(im), &
311 ws10m(im), &
312 zol(im), ilmo(im), &
313 safe_inv_mo_length(im)
314
315!...local variables
316
317 INTEGER :: i,L
318
319 logical(kind=4) :: flag_error
320 integer(kind=4) :: k, kk, kc, k2, II, npass
321
322 real(kind=kind_phys) :: tmp
323 real(kind=kind_phys) :: hol, a1, b1, c1, rat
324
325! del: Minimum allowable distance between a resolved model layer and a canopy layer
326! (fraction of canopy layer height)
327 real(kind=kind_phys), parameter :: del = 0.2
328 real(kind=kind_phys), parameter :: min_kt = 0.1
329 real(kind=kind_phys), parameter :: zfmin=1.e-8
330 real(kind=kind_phys), parameter :: rimin=-100.
331 real(kind=kind_phys), parameter :: karman=0.4 ! von karman constant
332 real(kind=kind_phys), parameter :: threshold = 1.e06 ! MOL threshold, similar to mach_plumerise
333 real(kind=kind_phys), parameter :: epsilon = 1.e-10
334
335 real(kind=kind_phys) :: zm2, zr, td, hd, ddel
336 real(kind=kind_phys) :: uh, uspr, wndr, sigw, tl, ktr, kur
337
338! Assign the fractional heights of the canopy layers (fraction of canopy height)
339 real(kind=kind_phys), dimension(3), parameter :: can_frac = (/1.0, 0.5, 0.2/)
340
341 logical(kind=4) :: local_dbg
342
343! Initialize CCPP error handling variables
344 errmsg = ''
345 errflg = 0
346
347 local_dbg = (.false.)
348
349 kmod(:,:) = -999
350 kcan3(:,:) = -999
351
352! Initializations
353
354! NB. mfpbltq_mod: q1(ix,km,ntrac1) kg kg-1
355 q1_2m(:, :) = q1(:,1,:) ! kg kg-1
356
357! Subset (km combined layers minus top nkc layers)
358 do k = 1, km-nkc
359 ! km is top combined subset
360 ! nkc+1 is bot combined
361 kc= nkc+k ! 4th from top (nkt) to nkc+1 combined canopy plus resolved model layer
362
363! PBL Tendencies are declared in CCPP_typdefs as dim(im,km) instead (im, nkt)
364 du_can(:,kc) = du(:,k) ! m s-2
365 dv_can(:,kc) = dv(:,k) ! m s-2
366 tdt_can(:,kc) = tdt(:,k) ! K s-1
367
368 rtg_can(:,kc, 1:ntrac-1) = rtg(:,k, 1:ntrac-1) ! kg kg-1 s-1
369 rtg_can(:,kc, ntke ) = rtg(:,k, ntke ) ! J s-1 s-1
370
371 end do
372
373! All combined canopy plus resolved layers
374 do k = km, 1, -1 ! top to 1hy model layer
375 ! nkc+km is top (nkt) combined
376 ! nkc+1 is bot combined
377 kc= nkc+k ! top (nkt) to nkc+1 combined canopy plus resolved model layer
378
379! Pressure & Temperature
380 prsl_can(:,kc) = prsl(:,k) ! km combined canopy plus resolved layers
381 prsi_can(:,kc) = prsi(:,k) ! km combined canopy plus resolved layers
382 t1_can(:,kc) = t1(:,k)
383 dens_can(:,kc) = dens(:,k)
384
385! Diffusivities
386 dkt_can(:,kc) = dkt(:,k) ! m2 s-1
387 dku_can(:,kc) = dku(:,k) ! m2 s-1
388
389! Wind
390 ws_can(:,kc) = sqrt(u1(:,k)**2+v1(:,k)**2) ! m s-1
391
392! Mass tracers
393 q1_can(:,kc, 1:ntrac-1) = q1(:,k, 1:ntrac-1) ! all tracers ntrac1
394
395! TKE tracer
396 q1_can(:,kc, ntke ) = q1(:,k, ntke ) ! ntke=198 TKE tracer
397
398! Water vapor
399 qv_can(:,kc) = q1(:,k, ntqv) ! ntqv=1
400
401 end do
402 prsi_can(:,nkt+1 ) = prsi(:,km+1) ! km combined canopy plus resolved layers
403
404! Canopy layers
405 do kc = 1, nkc ! 3-nkc canopy layers
406
407 du_can(:,kc) = du(:,1) ! m s-2
408 dv_can(:,kc) = dv(:,1) ! m s-2
409 tdt_can(:,kc) = tdt(:,1) ! K s-1
410
411 rtg_can(:,kc, 1:ntrac-1) = rtg(:,1, 1:ntrac-1) ! kg kg-1 s-1
412 rtg_can(:,kc, ntke ) = rtg(:,1, ntke ) ! J s-1 s-1
413
414 prsl_can(:,kc) = prsl(:,1) ! km combined canopy plus resolved layers
415 prsi_can(:,kc) = prsi(:,1) ! km combined canopy plus resolved layers
416 t1_can(:,kc) = t1(:,1)
417 dens_can(:,kc) = dens(:,1)
418
419 dkt_can(:,kc) = dkt(:,1) ! m2 s-1
420 dku_can(:,kc) = dku(:,1) ! m2 s-1
421 ws_can(:,kc) = sqrt(u1(:,1)**2+v1(:,1)**2) ! m s-1
422
423! Mass tracers
424 q1_can(:,kc, 1:ntrac-1) = q1(:,1, 1:ntrac-1) ! all tracers ntrac-1
425
426! TKE tracer
427 q1_can(:,kc, ntke ) = q1(:,1, ntke ) ! ntke=198 TKE tracer
428
429! Water vapor
430 qv_can(:,kc) = q1(:,1, ntqv) ! ntqv=1
431
432 end do
433
434
435 DO i = 1, im
436
437 sfcflg(i)= .true.
438 if(rbsoil(i) > 0.) sfcflg(i) = .false.
439
440 dxdy(i) = garea( i ) ! dx*dy ~1.6E+8 m2
441
442 ustar(i) = sqrt(stress(i))
443! ws10m(i) = sqrt(u10m(i)**2+v10m(i)**2)
444
454 zol(i) = max(rbsoil(i)*fm(i)*fm(i)/fh(i),rimin)
455 if(sfcflg(i)) then
456 zol(i) = min(zol(i),-zfmin)
457 else
458 zol(i) = max(zol(i),zfmin)
459 endif
460! Inverse of Monin-Obukhov length
461 ilmo(i) = 1./zol(i)
462
463!!!! Non-Canopy columns
464 IF (frt_mask(i) <= 0.) THEN
465
466 do k = 1, km ! from bottom to top
467 ii = km + 1 - k ! from top to bottom of resolved model layers
468!!! Paul's zmom is our zmom
469! zmom(1) = ZFULL(km) is top model layer height
470! zmom(km) = ZFULL(1) is bottom model layer height
471 ! NB. zm(:,k) = zi(:,k+1)
472 zmom3(ii) = zm(i,k) ! ZFULL(i,k)
473!! Heights of the original model layers for the canopy columns are extracted to the zmom array.
474
475 ! Create temperature & humidity array on reversed layer order for interpolation
476 ta3(ii) = t1(i,k) ! K
477 qv3(ii) = q1(i,k,1) ! 1=water vapor kg kg-1
478 prsl3(ii) = prsl(i,k) ! Pa mean layer pressure
479 dens3(ii) = dens(i,k) ! kg m-3
480 ws3(ii) = sqrt(u1(i,k)**2+v1(i,k)**2) ! rename wspd3 ???
481 dkt3(ii) = dkt(i,k) ! m2 s-2
482 dku3(ii) = dku(i,k) ! m2 s-2
483 end do ! k = 1, km ! from bottom to top
484
485 do k = 1, km+1 ! from bottom to top
486 ii = (km + 1) + 1 - k ! from top to bottom of resolved model layers
487
488 prsi3(ii) = prsi(i,k) ! Pa air pressure at model layer interfaces
489! ! [pgr] surface air pressure meta var
490 sigmom3(ii) = prsi(i, k) / psfc(i) ! PRES_FULL
491 end do ! k = 1, km+1
492
493! First, carry over original model values for the matching layers
494 do k = 1, km ! from bottom to top of resolved model layers
495 ! kmod(1) is 1 top model layer
496 ! kmod(km) is 65 top canopy layer (modified after mono adj.)
497 kk = k ! kmod(i,k)
498
499 sigmom_can(i, kk) = sigmom3(k) !
500
501 ta_can3(kk) = ta3(k) ! TA (i, k) ! temperature [K]
502 qv_can3(kk) = qv3(k) ! Met_Data%QV (i, k) ! spec. humidity
503 prsl_can3(kk) = prsl3(k) ! Met_Data%PRES(i, k) ! Pa
504 prsi_can3(kk) = prsi3(k) !
505 dens_can3(kk) = dens3(k) ! Met_Data%DENS(i, k) ! kg m-3
506 ws_can3(kk) = ws3(k) ! ! m s-1
507 dkt_can3(kk) = dkt3(k) ! DKT (i, k) ! m2 s-2 atmos. thermal diffus.
508 dku_can3(kk) = dku3(k) ! DKU (i, k) ! m2 s-2 atmos. momentum diffus.
509 end do
510
511 do kc = 1, nkc ! from top to bottom of canopy layers
512 ! kk = 65 = kcan3(1) = km + 1
513 ! kk = 66 = kcan3(2) = km + 2
514 ! kk = 67 = kcan3(3) = km + 3
515 kk = kc + km ! kcan3(i,kc)
516
517! zmom_can3 (i, kk) = zmom3 (km) ! full layer height [m]
518 sigmom_can(i, kk) = sigmom3(km) !
519
520 ta_can3(kk) = ta3(km) ! TA (i, k) ! temperature [K]
521 qv_can3(kk) = qv3(km) ! Met_Data%QV (i, k) ! spec. humidity
522 prsl_can3(kk) = prsl3(km) ! Met_Data%PRES(i, k) ! Pa
523 prsi_can3(kk) = prsi3(km)
524 dens_can3(kk) = dens3(km) ! Met_Data%DENS(i, k) ! kg m-3
525 ws_can3(kk) = ws3(km) ! ! m s-1
526 dkt_can3(kk) = dkt3(km) ! DKT (i, k) ! m2 s-2 atmos. thermal diffus.
527 dku_can3(kk) = dku3(km) ! DKU (i, k) ! m2 s-2 atmos. momentum diffus.
528 end do
529! Lower interface at surface
530 prsi_can3( nkt+1) = prsi3(km+1)
531 sigmom_can(i, nkt+1) = 1.0
532
533!!!!! End non-canopy columns!!!!!
534
535 ! Continuous forest canopy
536 ELSE IF (frt_mask(i) > 0.) THEN
537
538 hcan = cfch( i )
539!!! Extract the canopy height (FCH)
540
541! Generate initial canopy levels, as altitude above sea level
542!
543 do kc = 1, nkc
544 zcan3(kc) = hcan * can_frac(kc) ! Paul's hc is our hcan
545 ! Paul's zcan is our zcan3
546!!! Set the initial values of the heights of the inserted canopy layers to hc, 0.5 hc, and 0.2 hc
547!!!
548!!! NB. zcan3(1) is hc, top of canopy
549!!! zcan3(2) is 0.5 * hc
550!!! zcan3(3) is 0.2 * hc (bottom canopy level)
551!
552! print*,'canopy_levs: ZCAN = ', i, kc, zcan3(kc)
553 end do
554
555! 1 = bottom (1st) model layer
556! km= top model layer
557 do k = 1, km ! from bottom to top
558 ii = km + 1 - k ! from top to bottom of resolved model layers
559! zl is height of layer center
560! zmid3(1) = zl(km) is top model layer height
561! zmid3(km) = zl(1) is bottom model layer height
562 ! Paul's zt is our zmid
563 zmid3(ii) = zl(i,k) ! mid layer height [m]
564!!! Heights of the original model layers for the canopy columns are extracted to the zmid array.
565
566! write(errmsg,*) 'canopy_levs: ZMID = ', i, II, zmid3(II)
567
568 ! Paul's sigt2 is our sigmid2
569 sigmid2(ii) = prsl(i,k)/ psfc(i)
570
571 end do
572 sigmid2(km+1) = 1.0
573
574 do k = 1, km ! from bottom to top
575 ii = km + 1 - k ! from top to bottom of resolved model layers
576!!! Paul's zmom is our zmom
577! zmom(1) = ZFULL(km) is top model layer height
578! zmom(km) = ZFULL(1) is bottom model layer height
579 ! NB. zm(:,k) = zi(:,k+1)
580 zmom3(ii) = zm(i,k) ! ZFULL(i,k)
581!! Heights of the original model layers for the canopy columns are extracted to the zmom array.
582
583 ! Create temperature & humidity array on reversed layer order for interpolation
584 ta3(ii) = t1(i,k) ! K
585 qv3(ii) = q1(i,k,1) ! 1=water vapor kg kg-1
586 prsl3(ii) = prsl(i,k) ! Pa mean layer pressure
587 dens3(ii) = dens(i,k) ! kg m-3
588 ws3(ii) = sqrt(u1(i,k)**2+v1(i,k)**2)
589 dkt3(ii) = dkt(i,k) ! m2 s-2
590 dku3(ii) = dku(i,k) ! m2 s-2
591
592! From satmedmfvdifq.F:
593! MOL = zol(i)/zl(i,k) !Monin-Obukhov Length in layer
594! ZL is mid layer height [m]
595 mol3(ii) = zol(i)/zl(i,k) !Monin-Obukhov Length in layer
596 end do
597
598 do k = 1, km+1 ! from bottom to top
599 ii = (km + 1) + 1 - k ! from top to bottom of resolved model layers
600
601 prsi3(ii) = prsi(i,k) ! Pa air pressure at model layer interfaces
602! Paul's SIGM does not include surface layer lower interface (1.0) !!!
603 sigmom3(ii) = prsi(i, k)/ psfc(i) ! PRES_FULL(i, k) / psfc(i)
604
605 end do
606
607!!! Find the resolved model level which lies above the top of the forest canopy,
608!!! in each canopy column. Usually the canopy is within the km or km-1
609!!! level of the original model structure.
610!
611! The model level above the tallest canopy in grid
612 kcan_top = 2 ! initialize to 2nd top model layer
613 do l = km, 3, -1 ! from bottom to top model layer (going up)
614 ! Mid-layer height m, zmid
615 if (zmid3(l) > hcan) then ! Paul's zt is our zmid
616 kcan_top = l - 1 ! level above the tallest canopy
617 exit
618 end if
619 end do
620! kcan_top = 62 or 63
621! print*,'canopy_levs: kcan_top = ', i, kcan_top
622
623! MV2D_ILMO: Aggregated Inverse of Monin-Obukhov length
624! Setup of Monin-Obhukov Length similar to plumerise for upper limit:
625! from satmedmfvdifq.F: ! MOL = zol(i)/zl(i,k) !Monin-Obukhov Length in layer
626 safe_inv_mo_length(i) = ilmo(i)
627 if (abs(ilmo(i)) > threshold) then
628 safe_inv_mo_length(i) = sign(threshold, ilmo(i))
629 end if
630!
631! Adjust the canopy levels: we don't want canopy levels to get closer than del (0.2m)
632! to the model levels to prevent possible differencing errors in the diffusion.
633! If zcan3 > zmid3 but is too close to zmid3, move zcan3 up by ddel. If zcan3 < zmid3
634! but is too close to zmid3, move zcan3 down by ddel. The net result will be that the
635! canopy levels are never closer than del from the original model levels.
636 do k = kcan_top, km! from model layer above the canopy to bottom of model layer
637 do kc = 1, nkc ! from top to bottom of canopy
638 if (abs(zmid3(k) - zcan3(kc)) < del) then
639 ddel = max(0.0, del - abs(zcan3(kc) - zmid3(k)))
640 zcan3(kc) = zcan3(kc) + sign(ddel, zcan3(kc) - zmid3(k))
641
642!!! The reason why this section is necessary: while it would be preferable for
643!!! the canopy levels to stick with values of hc, 0.5 hc and 0.2 hc, somewhere in a
644!!! large domain, there may be an overlap where one of these canopy levels is very
645!!! close to or on top of an existing model level. Which we dont want!
646!!! What is done here, if the canopy levels come within "ddel" of an original model level,
647!!! is to shift the canopy level in question a bit, to avoid overlaps.
648 end if
649 end do
650 end do
651
652!!! Starts the creation of the local array with the heights of the thermodynamic
653!!! levels (layer midpoints) for the combined canopy + no canopy layers.
654!!! Note that zmid_can at this point does not have these layers sorted in the
655!!! correct order - the canopy layers have been tacked onto the bottom of the
656!!! zmid_can array, but the values of zmid_can are not monotonically increasing with
657!!! decreasing height index.
658!
659! Set the initial values of the combined height array:
660!
661! Note that here, zmid_can is created, but the heights within each column have
662! yet to be sorted to rearrange the layers in the correct order.
663 do k = 1, km ! from top to bottom model layers
664 zmid_can3(i,k) = zmid3(k)
665 ! Paul's zthrmcan is our zmid_can
666!
667 end do
668
669! Add zcan3 additional thermo levels into zmid_can array for later sorting
670 do kc = 1, nkc ! from top to bottom canopy layers
671 zmid_can3(i,km+kc) = zcan3(kc)
672 end do
673
674!
675! Determine locations of canopy and resolved model levels within
676! the combined array for the canopy columns:
677!
678!!! This section sorts the zmid_can array to make sure that the new layers are
679!!! all ordered so they monotonically increase with decreasing height.
680
681! Top canopy layer height (km+1) is higher than the bottom model layer height (km)
682 if (zmid_can3(i, km) < zmid_can3(i,km+1)) then
683!
684! Non-trivial case: the ancillary and original array levels intermingle.
685! Sort the combined height array to get the right order of the the heights:
686!
687! zmid_can is the height locations of the combined array, which needs to be sorted:
688! since there are only NKC levels in the canopy, and both zcan3 and z
689! decrease monotonically, only nkc+1 passes are needed to sort the combined array:
690 do npass = 1, nkc+1
691 flag_error = .false.
692 do k = nkt, 2, -1
693! Top canopy layer height (nkt-2) is larger than the bottom model layer height (nkt-3 = km)
694! Middle canopy layer height (nkt-1) is larger than the top canopy layer height (nkt-2)
695! Bottom canopy layer height (nkt) is larger than the middle canopy layer height (nkt-1)
696 if (zmid_can3(i, k) > zmid_can3(i, k-1)) then
697! The combined array heights are out of order, sort them:
698 tmp = zmid_can3(i, k-1)
699 zmid_can3(i, k-1) = zmid_can3(i,k)
700 zmid_can3(i, k) = tmp
701 flag_error = .true.
702 end if
703 end do
704 end do
705 if (flag_error) then
706 write(errmsg,fmt='(*(a))') 'NKC+1 passes insufficient to sort canopy array ' // &
707 'in canopy_levs.F90. Scream and die.'
708 errflg = 1
709 return
710 end if
711 end if
712
713!
714! Heights in zmid_can should now be monotonically decreasing.
715
716! Next, identify the locations of the vertical levels in the combined
717! array relative to the resolved model array and canopy array
718!
719!!! Now that the heights in zmid_can are in the right order, we can use them to
720!!! identify the values of kcan and kmod: the vertical locations of the canopy and
721!!! original model layers in the augmented canopy layer code.
722 do kc = 1, nkc ! from top to bottom canopy layers
723 do kk = nkt, 1, -1 ! from bottom to top of combined canopy and resolved model levels
724 if (zmid_can3(i, kk) == zcan3(kc)) then
725 kcan3(i,kc) = kk
726 exit
727 endif
728 end do
729 end do
730
731! k=1 is top model layer
732! k=km is bottom model layer
733 do k = 1, km ! from top to bottom model layers
734 do kk = k, nkt! from bottom to top of combined resolved plus canopy layers
735
736! zmid_can3(1) = zmid3(1) is top model layer height
737! ...
738! zmid_can3(km)= zmid3(km) is bottom model layer height
739 if (zmid_can3(i, kk) == zmid3(k)) then
740
741! kmod(1) is 1 , top model layer
742! kmod(km-1) is km-1, 2nd model layer
743! kmod(km) is top canopy layer (modified after monotonic adj.)
744 kmod(i,k) = kk
745 exit
746 endif
747 end do
748 end do
749
750 if (local_dbg) then
751 do kc = 1, nkc
752 if (kcan3(i,kc) < 1) then
753! write(errmsg,fmt='(*(a,i0,a,i0))') 'canopy_levs: kcan undefined: kc=', kc, &
754! ' kcan3=', kcan3(i,kc)
755 write(errmsg,*) 'canopy_levs: kcan undefined: ', kc, kcan3(i,kc)
756 errflg = 1
757 return
758 end if
759 end do
760 do k = 1,km
761 if (kmod(i,k) < 1) then
762! write(errmsg,fmt='(*(a,i0,a,i0))') 'canopy_levs: kmod undefined: k=', k, &
763! ' kmod=', kmod(i,k)
764 write(errmsg,*) 'cannopy_levs: kmod undefined: ',k, kmod(i,k)
765 errflg = 1
766 return
767 end if
768 end do
769 end if
770
771
772! Create the corresponding momentum height array
773!
774! The original methodology adopted made use of the at2m array and the thermodynamic heights determined above.
775! However, this methodology resulted in momentum levels which did not match the original model levels
776! above the region modified for canopy layers. Here, the thermodynamic layers will be used to
777! (1) Determine whether the original model and canopy thermodynamic layers coincide, and if so,
778! (2) Use the existing model layer values for the momentum layers, while if not,
779! (3) Assign the new momentum layers as being 1/2 way between the canopy layers
780! Note that these changes only exist inside the chemistry part of GEM-MACH and do not affect the model physics
781!!!
782!!! Create the momentum height (layer interface) array. The original momentum layers are used above the canopy height.
783!!! Below the canopy height, the "momentum" layers are assumed to be 1/2 way between the thermodynamic layers.
784
785! Default case: all added canopy thermodynamic layers are below the lowest resolved model thermodynamic layer
786! kcan_top is either 2nd or 3rd (63 or 62) resolved model layer
787 do k = 1, kcan_top - 1 ! from top model layer to model layer above the canopy
788! zmom(1) is top model layer height
789! zmom(kcan_top-1) is model layer above the canopy < 234.061m
790 zmom_can3(i,k) = zmom3(k) ! full layer height [m]
791 end do
792
793 ka(i) =km
794 inner0: do k = kcan_top, km-1 ! from resolved model layer above the canopy to top model layer
795! Starting from the top, scan down through the original and combined mid layer heights, to see when
796! they first deviate from each other
797 !Paul's zthrmcan is our zmid_can
798 !Paul's zt is our zmid
799 if (zmid_can3(i,k) == zmid3(k) .and. zmid_can3(i,k+1) == zmid3(k+1)) then
800 ! Paul's zmom is our zmom
801 ! Paul's zmomcan(nkt+1) is our zmom_can
802 zmom_can3(i,k) = zmom3(k) ! full layer height [m]
803 else
804 ka(i) = k
805 exit inner0
806 end if
807 end do inner0
808
809! ka is 63 or 64
810! print*,'canopy_levs: ka = ', i, ka(i)
811
812! ka is the lower-most layer for which the combined layer zmom_can = zmom resolved model layer
813 ! Paul's zmom is our zmom
814 ! Paul's zmomcan is our zmom_can
815 zmom_can3(i,ka(i)) = zmom3(ka(i))
816 do k = ka(i)+1, nkt! from ka to bottom combined canopy and resolved layers
817 zmom_can3(i,k) = (zmid_can3(i,k-1) + zmid_can3(i,k)) * 0.5
818
819 end do
820
821!########################################################################
822
823! create original model arrays of z and sigma-t which include the surface, to
824! allow interpolation:
825 !Paul's sigtcan is our sigmid_can
826 sigmid_can(:,:) = 0.0
827 do k = 1, km! from top to bottom of resolved model layers
828
829! zmid3(1) is top model layer height
830! zmid3(km) is bottom model layer height
831 z2(k) = zmid3(k)
832
833! Fill in the thermodynamic sigma levels (Pre-existing levels first):
834! kmod(1) is 1 top (last) model layer
835! kmod(km) is 64 bottom (1st) model layer
836 kk = kmod(i,k)
837 sigmid_can(i, kk) = sigmid2(k)
838
839 end do
840 klower_can(:) = -999
841 z2(km+1) = 0.0
842
843! fill in the remaining sigma levels by interpolating in z:
844 do kc = 1, nkc ! from top to bottom canopy layers
845 do k2 = kcan_top, km+1 ! from resolved model layer above the canopy to top model layer
846 if (zcan3(kc) > z2(k2) .and. zcan3(kc) <= z2(k2-1)) then
847
848! Interpolate in sigma
849 sigmid_can(i, kcan3(i,kc)) = sigmid2(k2-1) + &
850 (sigmid2(k2) - sigmid2(k2-1)) / &
851 ( z2(k2) - z2(k2-1)) * &
852 (zcan3(kc) - z2(k2-1))
853
854! Store grid locations for use in later interpolations
855 klower_can(kc) = k2
856 end if
857
858 end do
859
860 if (klower_can(kc) < 1) then
861 errflg = 1
862
863 write(errmsg,*) 'canopy_levs: klower_can is unassigned at i, kc: ', i, kc
864 write(errmsg,*) 'canopy_levs: zcan3(kc): ',zcan3(kc)
865!
866 do kk = kcan_top, km+1
867 write(errmsg,*) 'canopy_levs: kk z2(kk) which should bracket the above zcan3: ',kk, z2(kk)
868 end do
869 do kk = 1, km+1
870 write(errmsg,*) 'canopy_levs: kk z2(kk) full set of z2 values: ', kk, z2(kk)
871 end do
872 do kk = 1,nkc
873 write(errmsg,*) 'canopy_levs: kc zcan3(kc) hcan fr(kc) for full set of zcan3 values: ',kk, zcan3(kk), hcan, can_frac(kk)
874 end do
875
876 return
877 end if
878 end do
879
880! NB. klower_can(1) is 64 or 65
881! klower_can(2) is 65 except for individual grid points near West coast
882! klower_can(3) is 65 uniformly
883!
884!
885 if (local_dbg) then
886! Check on klower_can for NaN or out of bounds:
887 do kc = 1,nkc
888 if ((klower_can(kc) /= klower_can(kc)) .or. &
889 (klower_can(kc) <= 0) .or. &
890 (klower_can(kc) > km+ 1) ) then
891! write(errmsg,*) 'canopy_levs: klower_can after creation NaN or <=0 or >km+1 : ', &
892! kc, klower_can(kk)
893 return
894 end if
895 end do
896 end if
897!
898! Create sigma coordinate momentum levels:
899!
900! As above, the existing momentum levels and the canopy values are used to create SIGM levels
901!
902! (1) Determine whether the original model and canopy thermodynamic layers coincide, and if so,
903! (2) Use the existing model layer values for the momentum layers, while if not,
904! (3) Assign the new momentum layers as being 1/2 way between the canopy layers
905! Note that these changes only exist inside the chemistry part of GEM-MACH and do not affect the
906! model physics
907
908
909! Default case: all added canopy half layers are
910! below the lowest resolved model half layer
911 ka(i) = km
912 inner2: do k = 1, km-1
913 if (sigmid_can(i, k) == sigmid2(k) .and. sigmid_can(i, k+1) == sigmid2(k+1) ) then
914 sigmom_can(i, k) = sigmom3(k)
915 else
916 ka(i) = k
917 exit inner2
918 end if
919 end do inner2
920! ka is the last layer for which sigmom_can= sigmom3(k)
921 sigmom_can(i, ka(i)) = sigmom3(ka(i))
922 do k = ka(i)+1,nkt
923 sigmom_can(i, k) = (sigmid_can(i, k-1) + sigmid_can(i, k)) * 0.5
924 end do
925 sigmom_can(i, nkt+1) = 1.0
926
927! Next, do a sort of all of the variables in the original METV3D array into canopy. Note that
928! the declaration of the met arrays for the new canopy subdomain has occurred earlier in the code.
929! Three-D variables are a bit more complicated, in that one must make decisions regarding
930! the values of the met variables in the canopy region.
931! The code which follows is based on chm_load_metvar.ftn90
932!
933! First, carry over original model values for the matching layers
934 do k = 1, km ! from bottom to top of resolved model layers
935 ! kmod(1) is 1 top model layer
936 ! kmod(km) is 65 top canopy layer (modified after mono adj.)
937 kk = kmod(i,k)
938 ta_can3(kk) = ta3(k) ! TA (i, k) ! temperature [K]
939 qv_can3(kk) = qv3(k) ! Met_Data%QV (i, k) ! spec. humidity
940 prsl_can3(kk) = prsl3(k) ! Met_Data%PRES(i, k) ! Pa
941 prsi_can3(kk) = prsi3(k) !
942 dens_can3(kk) = dens3(k) ! Met_Data%DENS(i, k) ! kg m-3
943 ws_can3(kk) = ws3(k) ! ! m s-1
944 dkt_can3(kk) = dkt3(k) ! DKT (i, k) ! m2 s-2 atmos. thermal diffus.
945 dku_can3(kk) = dku3(k) ! DKU (i, k) ! m2 s-2 atmos. momentum diffus.
946
947 end do ! km
948
949!----------------------------------------------------------------------------
950! Canopy region: next, go through each variable to work out canopy values.
951!
952! (1) Do those variables for which special canopy formulae will NOT be used:
953 do kc = 1, nkc ! from top to bottom of canopy layers
954
955! Each of the following 2 variables have a screen height (2m) value in the 2D met arrays
956! Temperature: TA, T2M
957! Specific humidity: Q, Q2M
958
959! kcan3(1) = 65
960! kcan3(2) = 66
961! kcan3(3) = 67
962 kk = kcan3(i,kc)
963 if (klower_can(kc) <= km) then
964! Level is above first resolved model level
965
966 k2 = klower_can(kc)
967 zm2 = (zcan3(kc) - z2(k2-1)) / (z2(k2) - z2(k2-1))
968! zm2 = (zcan3(kc) - z2(k2-1)) / max(z2(k2) - z2(k2-1), epsilon)
969
970 td = ( ta3(k2) - ta3(k2-1)) * zm2
971 hd = ( qv3(k2) - qv3(k2-1)) * zm2
972 ta_can3(kk) = ta3(k2-1) + td
973 qv_can3(kk) = qv3(k2-1) + hd
974
975 else
976! Level is below first resolved model level
977
978 if (zcan3(kc) - z2(km+1) >= 2.0) then
979 ! Level is below first resolved model level but above screen height
980
981 zm2 = (zcan3(kc) - z2(km+1) - 2.0) / (z2(km) - z2(km+1) - 2.0)
982! zm2 = (zcan3(kc) - z2(km+1) - 2.0) / max(z2(km) - z2(km+1) - 2.0, epsilon)
983
984 td = (ta3(km) - t2m( i ) ) * zm2
985 hd = (qv3(km) - q2m( i ) ) * zm2
986 ta_can3(kk) = t2m( i ) + td
987 qv_can3(kk) = q2m( i ) + hd
988
989 else
990 ! Level in canopy is below screen height; assume constant values below screen height
991
992 ta_can3(kk) = t2m( i ) ! 2-m temperature [K]
993 qv_can3(kk) = q2m( i ) ! 2-m spec. humidity
994 end if
995
996 end if
997
998! Evaluate the air density in canopy columns using values determined above
999!
1000! NB. PRSL is air pressure on ZL, formerly ZH (mid-layers)
1001! PRSI is air pressure on ZI, formerly ZF (interfaces)
1002! psfc is surface air pressure psfc
1003
1004! get pressure from sigma levels in Pa
1005 prsl_can3(kk) = sigmid_can(i, kk) * psfc(i) ! ~zl mid-layers centers
1006 prsi_can3(kk) = sigmom_can(i, kk) * psfc(i) ! ~zm/zi layers interfaces
1007
1008! aqm_methods: dens: buffer(k) = stateIn % prl(c,r,l) / ( rdgas * stateIn % temp(c,r,l) )
1009 ! (1) is top model layer
1010 ! ...
1011 ! (km) is 1hy model layer
1012 ! (km+1) is top canopy layer
1013 ! (nkt) is 1st canopy layer
1014 dens_can3(kk) = prsl_can3(kk) / ( rdgas * ta_can3(kk)) ! kg m-3
1015
1016
1017! The following variables are assumed to have uniform values throughout the
1018! lowest resolved model layer:
1019!
1020! Cloud liquid water mass mixing ratio (QCPLUS)
1021! Total cloud fraction (FTOT)
1022! Stratospheric cloud fraction (FXP)
1023! Convective cloud fraction (FDC)
1024! Total liquid water flux (RNFLX)
1025! Total solid water flux (SNOFLX)
1026! Precipitation evaporation (FEVP)
1027! Cloud to rain collection tendency (PPRO)
1028! Search over the original model layers (k). Note that the outer loop above this
1029! one is over the canopy layers kc: we are looking for the values to assign the
1030! canopy layers in the combined canopy+resolved scale space. For these variables,
1031! the resolved scale values will be used, hence the aim is to determine the
1032! resolved scale layer in which the canopy layer resides, and assign the
1033! corresponding values to the locations of the canopy layers in the combined
1034! canopy + resolved scale space (kk).
1035
1036
1037 end do ! kc = 1,nkc
1038! Surface layer lower interface
1039 prsi_can3(nkt+1) = prsi3(km+1)
1040
1041 if (local_dbg) then
1042! Several checks for suspicious values:
1043 do kk = 1,nkt
1044 if ( ta_can3(kk) < 150.0) then
1045 write(errmsg,*) 'canopy_levs: suspicious temperature detected in canopy_levs after creation (kk value): ',&
1046 i, kk, ta_can3(kk)
1047 errflg = 1
1048
1049 do kc = 1, nkc
1050 write(errmsg,*) 'canopy_levs: value of zcan(kc) z2(km+1) and difference at this value of ic for kk: ',&
1051 kc,' are: ',zcan3(kc),z2(km+1), zcan3(kc)-z2(km+1)
1052 end do
1053
1054 do k = 1, nkt
1055 write(errmsg,*) 'canopy_levs: value of zmid_can for = ', i,' at k = ',k,' is: ',zmid_can3(i,k)
1056 end do
1057
1058 do kc = 1,nkc
1059 write(errmsg,*) 'canopy_levs: values of kcan zcan and original zcan for = ', i,' at kc = ',kc,' are: ',&
1060 kcan3(i,kc), zcan3(kc), hcan * can_frac(kc)
1061 end do
1062
1063 do k = 1,km
1064 write(errmsg,*) 'canopy_levs: value of kmod and z for = ', i,' at k = ',k,' are: ',kmod(i,k), zmid3(k)
1065 end do
1066
1067 do kc = 1,nkc
1068 write(errmsg,*) 'canopy_levs: value of klower_can at this grid point for kc: ',kc,' is: ',klower_can(kc)
1069 end do
1070
1071 return
1072 end if
1073 end do
1074 end if
1075
1076! (2) For the last few variables, the value at the lowest resolved model layer and typical profiles for that variable
1077! within the canopy will be used to create the canopy values:
1078 do kc = 1, nkc
1079 kk = kcan3(i,kc)
1080! Ratio of lowest model level to canopy height:
1081!
1082 zr = (zmid3(km) - z2(km+1)) / hcan
1083!
1084! Horizontal wind and KT profiles are from Raupach, Quarterly Journal
1085! of the Royal Meteorological Society, vol 115, pp 609-632, 1989, examples
1086! from page 626, equations (48) through (51).
1087!
1088! Wind speed (equation 51), assumed to scale similarly in each horizontal dimension:
1089!
1090! U(z) = ustar/karman * ln((z - d) / z0), where
1091! k = 0.4
1092! d = 0.75 hc
1093! z0 = 0.07530 hc
1094! The next few lines calculate the average value of u(z), v(z), Raupach's eqn 51,
1095! at the first resolved level model height
1096! Paul's UE is our ustar, surface friction velocity
1097 uh = ustar(i) * 3.0
1098 if (zr >= 1.0) then
1099 ! Paul's zt is our zmid (i.e. zmid(km) is zt(i,chm_nk))
1100 ! Paul's hc is our hcan
1101 uspr = ustar(i) / karman * &
1102 log((zmid3(km) - z2(km+1) - 0.75 * hcan) / &
1103 (0.07530 * hcan))
1104! log(max((zmid3(km) - z2(km+1) - 0.75 * hcan) / &
1105! (0.07530 * hcan), epsilon))
1106 else
1107 uspr = uh * exp(- 2.0 * ( 1.0 - zr))
1108 end if
1109! wndr is the ratio of the wind to Raupach's average us(), eqn 51.
1110! This is used to scale the wind speed with height values from eqn 51 to the current grid square
1111 ! Paul's WS(nk) is our spd1, wind speed at lowest model level m s-1
1112 wndr = spd1(i) / uspr
1113! wndr = spd1(i) / max(uspr, epsilon)
1114! Using Raupach's formulae for wind speed, multiplied by the above ratio, for the canopy layers:
1115!
1116 zr = (zcan3(kc) - z2(km+1)) / hcan
1117 if (zr >= 1.0) then
1118 uspr = log((zcan3(kc) - z2(km+1) - 0.75 * hcan) / &
1119 (0.07530 * hcan)) * ustar(i)
1120 else
1121 uspr = uh * exp(- 2.0 * (1.0 - (zcan3(kc) - z2(km+1)) / hcan))
1122 end if
1123
1124 ws_can3(kk) = wndr * uspr
1125!
1126! Coefficients of diffusivity:
1127! Find value of K at first model level from raupach's sigw and TL formulae (eqns 48, 49)
1128 zr = (zmid3(km) - z2(km+1)) / hcan
1129! Gradient in stability under the canopy is reduced for higher stability conditions
1130! in accord with Shaw, den Hartog and Neumann, BLM 45, 391-409, 1988, Fig 16.
1131 ! Paul's zl is our hol (as in satmedmfvdifq.F)
1132 hol = hcan * safe_inv_mo_length(i)
1133! Unstable:
1134 if(hol < -0.1) then
1135 a1 = 0.75
1136 b1 = 0.5
1137 c1 = 1.25
1138 end if
1139! Neutral:
1140 if(hol >= -0.1 .and. hol < 0.1) then
1141 a1 = 0.625
1142 b1 = 0.375
1143 c1 = 1.0
1144 end if
1145! Stable:
1146 if(hol >= 0.1 .and. hol < 0.9) then
1147 rat = 4.375 - 3.75 * hol
1148 a1 = 0.125 * rat + 0.125
1149 b1 = 0.125 * rat - 0.125
1150 c1 = 0.25 * rat
1151 end if
1152! Very stable (from extrapolation of Shaw et al's values at 0.1 and 0.5:
1153 ! Paul's MV3D_KT(nk) is our dkt3(km) m2 s-1 atmospheric heat diffusivity (thermal vertical diffusion coefficient)
1154 ! 1st (bottom) model layer
1155 if(hol >= 0.9 .or. dkt3(km) <= min_kt) then
1156 a1 = 0.25
1157 b1 = 0.0
1158 c1 = 0.25
1159 end if
1160! Raupach's originals:
1161! if (zr >= 1.0) then
1162! sigw = ustar(i) * 1.25
1163! else
1164! sigw = ustar(i) * ( 0.75 + 0.5 * cos(pi * (1.0 - (zmid3(km) - z2(km+1))/hcan) ) )
1165! end if
1166! Replace Raupach's originals with fit to Patton et al and Shaw et al 1988
1167 if(zr < 0.175) then
1168 sigw = ustar(i) * 0.25
1169 else
1170 if(zr < 1.25) then
1171 sigw = ustar(i) * ( a1 + b1 * cos(pi / 1.06818 * &
1172 (1.25 - (zmid3(km) - z2(km+1)) / hcan)))
1173 else
1174 sigw = ustar(i) * c1
1175 end if
1176 end if
1177
1178! tl = hcan / max(ustar(i), epsilon) * &
1179 tl = hcan / ustar(i) * &
1180 (0.256 * ((zmid3(km) - z2(km+1) - 0.75 * hcan) / hcan) + &
1181 0.492 * exp(-(0.256 * ((zmid3(km) - z2(km+1)) / hcan) / 0.492)))
1182! ktr is the ratio of the resolved model diffusivity at the lowest resolved
1183! model level to that derived by Raupach's formula
1184!
1185 ktr = dkt3(km) / (sigw * sigw * tl)
1186 kur = dku3(km) / (sigw * sigw * tl)
1187! ktr = dkt3(km) / max(sigw * sigw * tl, epsilon)
1188! kur = dku3(km) / max(sigw * sigw * tl, epsilon)
1189
1190! print*, 'canopy_levs: KTR= ', i, ktr, dkt3(km), kk, kc
1191!
1192! Use Raupach's formulae for diffusivity, multiplied by the above ratio, for the canopy layers:
1193!
1194 zr = (zcan3(kc) - z2(km+1)) / hcan
1195! Gradient in stability under the canopy is reduced for higher stability conditions
1196! in accord with Shaw, den Hartog and Neumann, BLM 45, 391-409, 1988, Fig 16.
1197! Raupach's original:
1198! if (zr >= 1.0) then
1199! sigw = ustar(i) * 1.25
1200! else
1201! sigw = ustar(i) * ( 0.75 + 0.5 * cos(pi * (1.0 - (zcan3(kc) - z2(km+1))/hcan) ) )
1202! end if
1203 if(zr < 0.175) then
1204 sigw = ustar(i) * 0.25
1205 else
1206 if(zr < 1.25) then
1207 sigw = ustar(i) * ( a1 + b1 * cos(pi / 1.06818 * &
1208 (1.25 - (zcan3(kc) - z2(km+1))/hcan)))
1209 else
1210 sigw = ustar(i) * c1
1211 end if
1212 end if
1213!
1214! tl = hcan / max(ustar(i), epsilon) * &
1215 tl = hcan / ustar(i) * &
1216 (0.256 * ( (zcan3(kc) - z2(km+1) - 0.75 * hcan) / hcan) + &
1217 (0.492 * exp(-(0.256 * (zcan3(kc) - z2(km+1)) / hcan) / 0.492) ) )
1218
1219 dkt_can3(kk) = (sigw * sigw * tl) * ktr
1220 dku_can3(kk) = (sigw * sigw * tl) * kur
1221
1222! print*, 'canopy_levs: DKT_CAN= ', i, sigw, tl, dkt_can3(kk), kk, kc
1223 end do ! kc = 1,nkc
1224!
1225 if (local_dbg) then
1226 do kc = 1, nkc
1227 if (kcan3(i, kc) == 0) then
1228 write(errmsg,fmt='(*(a,i0,a,i0))') 'kcan zero inside canopy_levs at i=', i, ' kc=', kc
1229 errflg = 1
1230 return
1231 end if
1232 end do
1233 end if
1234!
1235 do k = 1, nkt! from top to bottom of combined layers
1236 ii = nkt + 1 - k ! from bottom to top of combined layer
1237
1238 ! Flip back meteo arrays on combined layers in same layer order as original model layer
1239 ! nkt is top model layer <= 1
1240 ! ...
1241 ! (4) is 1st (bottom) model layer <= km
1242 ! (3) is 3rd (top) canopy layer <= nkt-2
1243 ! (2) is 2nd canopy layer <= nkt-1
1244 ! (1) is 1st (bottom) canopy layer <=nkt
1245 zl_can(i,ii) = zmid_can3(i, k)
1246 zm_can(i,ii) = zmom_can3(i, k)
1247 prsl_can(i,ii) = prsl_can3(k)
1248
1249 t1_can(i,ii) = ta_can3(k)
1250 qv_can(i,ii) = qv_can3(k)
1251 dens_can(i,ii) = dens_can3(k)
1252 ws_can(i,ii) = ws_can3(k)
1253 dkt_can(i,ii) = dkt_can3(k)
1254 dku_can(i,ii) = dku_can3(k)
1255
1256 end do ! k = 1, nkt
1257
1258! Pressure at layers interfaces
1259 do k = 1, nkt+1 ! from top to bottom of combined layers
1260 ii = (nkt+1) + 1 - k ! from bottom to top of combined layer
1261
1262! (km+1) (68=nkc+km +1) prsi3( 1) Top model layer upper interface prsi_can3(1)
1263! (km) (67=nkc+km ) prsi3( 2)
1264! ...
1265! (2) (5 =nkc +2) prsi3(km) Bottom model layer upper interface prsi_can3(km)
1266! (4 =nkc +1) Top canopy layer upper interface prsi_can3(km+1)
1267! (3) Mid canopy layer upper interface
1268! (2) Bottom canopy layer upper interface prsi_can3(nkt)
1269! (1) (1) prsi3(km+1) Bottom model layer LOWER interface prsi_can3(nkt+1)
1270!
1271 prsi_can(i,ii) = prsi_can3(k)
1272
1273 end do ! k = 1, nkt+1
1274
1275
1276 END IF ! Continuous forest canopy: FRT_MASK == 1.
1277
1278! ... have not finished Paul's code ...
1279
1280
1281 END DO !I-index
1282
1283 end subroutine canopy_levs_run
1284
1285 end module canopy_levs_mod