← Back to Documentation Home
CCPP SciDoc v8.0.0  v8.0.0
Common Community Physics Package Developed at DTC
 
Loading...
Searching...
No Matches
clm_lake.f90
1
3
23
24 use machine, only: kind_phys, kind_dbl_prec
25
26 implicit none
27
28 private
29
30 public :: clm_lake_run, clm_lake_init, lakedebug
31
32 ! In WRF, the CLM Lake Model was hard-coded to use double precision, regardless of
33 ! precision of physics. For that reason, we retain double precision here. However,
34 ! we're not yet certain that all of CLM Lake needs to be double precision, so we
35 ! maintain a "kind_lake" to allow future experimentation in datatypes.
36 integer, parameter, public :: kind_lake = kind_dbl_prec
37
38 logical :: LAKEDEBUG = .false. ! Enable lots of checks and debug prints and errors
39 logical :: DEBUG_PRINT = .false. ! Enable lots of checks and debug prints and errors
40
41 logical, parameter :: PERGRO = .false.
42
43 logical, parameter :: USE_ETALAKE = .false.
44 real(kind_lake), parameter :: ETALAKE = 1.1925*50**(-0.424)
45
46 ! Level counts must be consistent with model (GFS_typedefs.F90)
47 integer, parameter :: nlevsoil = 10
48 integer, parameter :: nlevlake = 10
49 integer, parameter :: nlevsnow = 5
50 real(kind_lake), parameter :: scalez = 0.025_kind_lake
51
52 integer,parameter :: lbp = 1
53 integer,parameter :: ubp = 1
54 integer,parameter :: lbc = 1
55 integer,parameter :: ubc = 1
56 integer,parameter :: num_shlakec = 1
57 integer,parameter :: filter_shlakec(1) = 1
58 integer,parameter :: num_shlakep = 1
59 integer,parameter :: filter_shlakep(1) = 1
60 integer,parameter :: pcolumn(1) = 1
61 integer,parameter :: pgridcell(1) = 1
62 integer,parameter :: cgridcell(1) = 1
63 integer,parameter :: clandunit(1) = 1
64
65 integer,parameter :: begg = 1
66 integer,parameter :: endg = 1
67 integer,parameter :: begl = 1
68 integer,parameter :: endl = 1
69 integer,parameter :: begc = 1
70 integer,parameter :: endc = 1
71 integer,parameter :: begp = 1
72 integer,parameter :: endp = 1
73
74 integer,parameter :: column =1
75 logical,parameter :: lakpoi(1) = .true.
76
77 !Initialize physical constants not available from model:
78 real(kind_lake), parameter :: tcrit = 2.5
79 real(kind_lake), parameter :: tkwat = 0.6
80 real(kind_lake), parameter :: tkice = 2.290
81 real(kind_lake), parameter :: tkairc = 0.023
82 real(kind_lake), parameter :: snow_bd = 250
83
84 ! Constants that are copied from model values by clm_lake_init:
85 real(kind_lake) :: pi
86 real(kind_lake) :: vkc
87 real(kind_lake) :: grav
88 real(kind_lake) :: sb
89 real(kind_lake) :: tfrz
90 real(kind_lake) :: denh2o
91 real(kind_lake) :: denice
92 real(kind_lake) :: cpice
93 real(kind_lake) :: cpliq
94 real(kind_lake) :: hfus
95 real(kind_lake) :: hvap
96 real(kind_lake) :: hsub
97 real(kind_lake) :: invhvap
98 real(kind_lake) :: invhsub
99 real(kind_lake) :: rair
100 real(kind_lake) :: cpair
101 real(kind_lake) :: con_eps
102 real(kind_lake) :: one_minus_con_eps
103 real(kind_lake) :: con_fvirt
104
105 real(kind_lake), public, parameter :: spval = 1.e36
106 real(kind_lake), parameter :: depth_c = 50.
107 real(kind_lake), parameter :: zero_h2o = 1e-12
108
109 ! These are tunable constants
110 real(kind_lake), parameter :: wimp = 0.05
111 real(kind_lake), parameter :: ssi = 0.033
112 real(kind_lake), parameter :: cnfac = 0.5
113
114 ! Initialize water type constants
115 integer,parameter :: istsoil = 1!soil "water" type
116
117 ! percent sand
118 real(kind_lake), parameter :: sand(19) = &
119 (/92.,80.,66.,20.,5.,43.,60.,10.,32.,51., 6.,22.,39.7,0.,100.,54.,17.,100.,92./)
120
121 ! percent clay
122 real(kind_lake), parameter :: clay(19) = &
123 (/ 3., 5.,10.,15.,5.,18.,27.,33.,33.,41.,47.,58.,14.7,0., 0., 8.5,54., 0., 3./)
124
125 ! These are initialized in clm_lake_init and are not modified elsewhere
126 real(kind_lake) :: zlak(1:nlevlake)
127 real(kind_lake) :: dzlak(1:nlevlake)
128 real(kind_lake) :: zsoi(1:nlevsoil)
129 real(kind_lake) :: dzsoi(1:nlevsoil)
130 real(kind_lake) :: zisoi(0:nlevsoil)
131
132 real, parameter :: saltlk_t(1:25) = (/ 0.5, 0.,-0.5, 3., 4., 7., 8., 12., 13., 16., 19., 21., &
133 23.5, 25., 26.,24.,23.,20.5,18., 15., 11.5, 8., 4., 1., 0.5/)
134 real, parameter :: month_length(12) = (/ 31, 29, 31, 30, 31, 30, 31, 30, 30, 31, 30, 31 /)
135 logical, parameter :: include_all_salty_locations = .false.
136
137 CONTAINS
138
139 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
140
141 logical function limit_temperature_by_climatology(xlat_d,xlon_positive)
142 implicit none
143 real(kind_phys), intent(in) :: xlat_d, xlon_positive
144 real(kind_phys) :: xlon_d
145
146 xlon_d = xlon_positive
147 if(xlon_d>180) xlon_d = xlon_d - 360
148
149 limit_temperature_by_climatology=.false.
150
160 if ((xlon_d.gt.-117.7 .and. xlon_d.lt.-111.5) .and. &
161 ! excludes Willard Bay
162 .not. (xlon_d.gt.-112.104 .and. xlon_d.lt.-112.100))then
163
164 if(xlat_d.gt.39.5 .and. xlat_d.lt.41.22) then
165 if(debug_print) then
166 print *,'The Great Salt Lake south of 41.22 N, lat,lon',xlat_d,xlon_d
167 endif
168 limit_temperature_by_climatology = .true.
169
170 elseif(( xlat_d.ge.41.22 .and. xlat_d.lt.42.) .and. .not. &
171 ! excludes Willard Bay
172 (xlat_d.gt.41.352 .and. xlat_d.lt.41.354)) then
173 if(debug_print) then
174 print *,'The Great Salt Lake north of 41.22 N xlat_d,xlon_d ',xlat_d,xlon_d
175 endif
176 !print *,'Ice fraction on the GSL ', i,j,lake_icefrac3d(i,:,j)
177 limit_temperature_by_climatology = .true.
178
179 endif ! xlat_d
180
181 endif ! xlon_d
182
183 !if(i==495.and.j==668) print *,'Willard Bay salty=',i,j,limit_temperature_by_climatology,xlat_d,xlon_d
184
185 end function limit_temperature_by_climatology
186
187 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
188
189 subroutine is_salty(xlat_d,xlon_positive, cannot_freeze, salty)
190 implicit none
191 real(kind_phys), intent(in) :: xlat_d, xlon_positive
192 logical, intent(inout) :: cannot_freeze, salty
193 real(kind_phys) :: xlon_d
194
195 xlon_d = xlon_positive
196 if(xlon_d>180) xlon_d = xlon_d - 360
197
198 ! for the Great Salt Lake
199 cannot_freeze = limit_temperature_by_climatology(xlat_d,xlon_d)
200 salty = cannot_freeze
201
202 ! --- The Mono Lake in California, salinity is 75 ppt with freezing point at
203 ! --- -4.2 C (Stan). The Mono Lake lat/long (37.9-38.2, -119.3 - 118.8)
204 if (xlon_d.gt.-119.3.and. xlon_d.lt.-118.8) then
205 if(xlat_d.gt.37.9 .and. xlat_d.lt.38.2) then
206 salty = .true.
207 if(debug_print) then
208 print *,'Salty Mono Lake, i,j',xlat_d,xlon_d
209 endif
210 endif ! xlat_d
211 endif ! xlon_d
212
213 other_locations: if(include_all_salty_locations) then
214 ! --- Caspian Sea and Dead Sea are salty too (Sam, Tanya)
215 if ( xlat_d>36.5_kind_phys .and. xlat_d<47.1_kind_phys .and. xlon_d>46.8_kind_phys .and. xlon_d<55.0_kind_phys ) then
216 if(debug_print) then
217 print *,'Salty Caspian Sea ',xlat_d,xlon_d
218 endif
219 salty = .true.
220 end if
221 if ( xlon_d>35.3 .and. xlon_d<35.6 .and. xlat_d>31.3 .and. xlat_d<31.8) then
222 if(debug_print) then
223 print *,'Salty Dead Sea ',xlat_d,xlon_d
224 endif
225 salty = .true.
226 endif
227 endif other_locations
228 !tgs --- end of special treatment for salty lakes
229 end subroutine is_salty
230
231 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
232
233 subroutine calculate_z_dz_lake(i,input_lakedepth,clm_lakedepth,z_lake,dz_lake)
234 implicit none
235 integer, intent(in) :: i
236 real(kind_phys), intent(inout) :: clm_lakedepth(:) ! lake depth used by clm
237 real(kind_phys), intent(in) :: input_lakedepth(:) ! lake depth before correction (m)
238 real(kind_lake) :: z_lake(nlevlake) ! layer depth for lake (m)
239 real(kind_lake) :: dz_lake(nlevlake) ! layer thickness for lake (m)
240 real(kind_lake) :: depthratio
241
242 if (input_lakedepth(i) == spval .or. input_lakedepth(i) < 0.1) then
243 ! This is a safeguard against:
244 ! 1. missing in the lakedepth database (== spval)
245 ! 2. errors in model cycling or unexpected changes in the orography database (< 0.1)
246 clm_lakedepth(i) = zlak(nlevlake) + 0.5_kind_lake*dzlak(nlevlake)
247 z_lake(1:nlevlake) = zlak(1:nlevlake)
248 dz_lake(1:nlevlake) = dzlak(1:nlevlake)
249 else
250 depthratio = input_lakedepth(i) / (zlak(nlevlake) + 0.5_kind_lake*dzlak(nlevlake))
251 z_lake(1) = zlak(1)
252 dz_lake(1) = dzlak(1)
253 dz_lake(2:nlevlake) = dzlak(2:nlevlake)*depthratio
254 z_lake(2:nlevlake) = zlak(2:nlevlake)*depthratio + dz_lake(1)*(1._kind_lake - depthratio)
255 end if
256
257 end subroutine calculate_z_dz_lake
258
259 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
260
264 SUBROUTINE clm_lake_run( &
265 ! Model time and metadata:
266 flag_restart, im, km, me, master, fhour, IDATE, kdt, &
267
268 ! Configuration and initialization:
269 iopt_lake, iopt_lake_clm, min_lakeice, lakedepth_default, use_lakedepth, &
270 dtp, use_lake_model, clm_lake_initialized, frac_grid, frac_ice, lkm, &
271 use_cdeps_data, mask_dat, &
272
273 ! Atmospheric model state inputs:
274 tg3, pgr, zlvl, gt0, prsi, phii, qvcurr, gu0, gv0, xlat_d, xlon_d, &
275 ch, cm, dlwsfci, dswsfci, oro_lakedepth, wind, tsfc, &
276 flag_iter, flag_lakefreeze, ISLTYP, rainncprv, raincprv, &
277
278 ! Feedback to atmosphere:
279 evap_wat, evap_ice, hflx_wat, hflx_ice, gflx_wat, gflx_ice, &
280 ep1d_water, ep1d_ice, tsurf_water, tsurf_ice, tsfc_wat, tisfc, &
281 weasdi, snodi, hice, qss_water, qss_ice, &
282 cmm_water, cmm_ice, chh_water, chh_ice, &
283 uustar_water, uustar_ice, lake_t_snow, albedo, zorlw, &
284 zorli, lake_t2m, lake_q2m, weasd, snowd, fice, &
285 icy, &
286
287 ! Lake model internal state stored by caller:
288
289 salty, savedtke12d, snowdp2d, h2osno2d, snl2d, t_grnd2d, t_lake3d, &
290 lake_icefrac3d, t_soisno3d, h2osoi_ice3d, h2osoi_liq3d, h2osoi_vol3d, &
291 z3d, dz3d, zi3d, t1, qv1, prsl1, &
292 input_lakedepth, clm_lakedepth, cannot_freeze, &
293
294 ! Error reporting:
295 errflg, errmsg)
296
297 !==============================================================================
298 ! This subroutine was first edited by Hongping Gu and Jiming Jin for coupling
299 ! 07/20/2010
300 ! Long after, in June 2022, Sam Trahan updated it for CCPP
301 !==============================================================================
302
303 IMPLICIT NONE
304
305 !
306 ! Model time and metadata:
307 !
308 LOGICAL , INTENT (IN) :: flag_restart
309 INTEGER , INTENT (IN) :: im,km,me,master
310 INTEGER, INTENT(IN) :: idate(4), kdt
311 REAL(kind_phys), INTENT(IN) :: fhour
312 INTEGER, INTENT(IN) :: lkm
313
314 !
315 ! Configuration and initialization:
316 !
317 INTEGER, INTENT(IN) :: iopt_lake, iopt_lake_clm
318 REAL(kind_phys), INTENT(IN) :: min_lakeice, lakedepth_default, dtp
319 LOGICAL, INTENT(IN) :: use_lakedepth
320 INTEGER, DIMENSION(:), INTENT(IN) :: use_lake_model
321 REAL(kind_phys), INTENT(INOUT) :: clm_lake_initialized(:)
322 LOGICAL, INTENT(IN) :: frac_grid, frac_ice, use_cdeps_data
323 REAL(kind_phys), INTENT(IN), OPTIONAL :: mask_dat(:)
324
325
326 !
327 ! Atmospheric model state inputs:
328 !
329 REAL(kind_phys), DIMENSION(:), INTENT(IN):: &
330 tg3, pgr, zlvl, qvcurr, xlat_d, xlon_d, ch, cm, &
331 dlwsfci, dswsfci, oro_lakedepth, wind, &
332 t1, qv1, prsl1
333 REAL(kind_phys), DIMENSION(:), INTENT(IN) :: &
334 rainncprv, raincprv
335 REAL(kind_phys), DIMENSION(:,:), INTENT(in) :: gu0, gv0, prsi, gt0, phii
336 LOGICAL, DIMENSION(:), INTENT(IN) :: flag_iter
337 LOGICAL, DIMENSION(:), INTENT(INOUT) :: flag_lakefreeze
338
339 INTEGER, DIMENSION(:), INTENT(IN) :: isltyp
340
341 !
342 ! Feedback to atmosphere:
343 !
344 REAL(kind_phys), DIMENSION(:), INTENT(INOUT) :: &
345 evap_wat, evap_ice, hflx_wat, hflx_ice, gflx_wat, gflx_ice, &
346 ep1d_water, ep1d_ice, tsurf_water, tsurf_ice, tsfc_wat, tisfc, tsfc, &
347 weasdi, snodi, hice, qss_water, qss_ice, &
348 cmm_water, cmm_ice, chh_water, chh_ice, &
349 uustar_water, uustar_ice, zorlw, zorli, weasd, snowd, fice
350 REAL(kind_phys), DIMENSION(:), INTENT(INOUT) :: &
351 lake_t_snow, albedo, lake_t2m, lake_q2m
352 LOGICAL, INTENT(INOUT) :: icy(:)
353
354 !
355 ! Lake model internal state stored by caller:
356 !
357 INTEGER, DIMENSION( : ), INTENT(INOUT) :: salty
358 INTEGER, DIMENSION( : ), INTENT(INOUT) :: cannot_freeze
359
360 real(kind_phys), dimension(: ) ,intent(inout) :: savedtke12d, &
361 snowdp2d, &
362 h2osno2d, &
363 snl2d, &
364 t_grnd2d
365
366 real(kind_phys), dimension( :,: ), INTENT(inout) :: t_lake3d, &
367 lake_icefrac3d
368 real(kind_phys), dimension( :,-nlevsnow+1: ) ,INTENT(inout) :: t_soisno3d, &
369 h2osoi_ice3d, &
370 h2osoi_liq3d, &
371 h2osoi_vol3d, &
372 z3d, &
373 dz3d
374 real(kind_phys), dimension( :,-nlevsnow+0: ) ,INTENT(inout) :: zi3d
375
376 REAL(kind_phys), DIMENSION( : ) ,INTENT(INOUT) :: clm_lakedepth
377 REAL(kind_phys), DIMENSION( : ) ,INTENT(INOUT) :: input_lakedepth
378
379 !
380 ! Error reporting:
381 !
382 INTEGER, INTENT(OUT) :: errflg
383 CHARACTER(*), INTENT(OUT) :: errmsg
384
385
386
387 !
388 !local variables:
389 !
390
391 REAL(kind_lake) :: sfctmp,pbot,psfc,q2k,lwdn,prcp,soldn,solnet,dtime
392 INTEGER :: c,i,j,k
393
394
395 !temporary varibles in:
396 real(kind_lake) :: forc_t(1) ! atmospheric temperature (Kelvin)
397 real(kind_lake) :: forc_pbot(1) ! atm bottom level pressure (Pa)
398 real(kind_lake) :: forc_psrf(1) ! atmospheric surface pressure (Pa)
399 real(kind_lake) :: forc_hgt(1) ! atmospheric reference height (m)
400 real(kind_lake) :: forc_hgt_q(1) ! observational height of humidity [m]
401 real(kind_lake) :: forc_hgt_t(1) ! observational height of temperature [m]
402 real(kind_lake) :: forc_hgt_u(1) ! observational height of wind [m]
403 real(kind_lake) :: forc_q(1) ! atmospheric specific humidity (kg/kg)
404 real(kind_lake) :: forc_u(1) ! atmospheric wind speed in east direction (m/s)
405 real(kind_lake) :: forc_v(1) ! atmospheric wind speed in north direction (m/s)
406 real(kind_lake) :: forc_lwrad(1) ! downward infrared (longwave) radiation (W/m**2)
407 real(kind_lake) :: prec(1) ! snow or rain rate [mm/s]
408 real(kind_lake) :: sabg(1) ! solar radiation absorbed by ground (W/m**2)
409 real(kind_lake) :: lat(1) ! latitude (radians)
410 real(kind_lake) :: z_lake(1,nlevlake) ! layer depth for lake (m)
411 real(kind_lake) :: dz_lake(1,nlevlake) ! layer thickness for lake (m)
412
413 real(kind_lake) :: lakedepth(1) ! column lake depth (m)
414 logical :: do_capsnow(1) ! true => do snow capping
415
416 !in&out
417 real(kind_lake) :: h2osoi_vol(1,-nlevsnow+1:nlevsoil) ! volumetric soil water (0<=h2osoi_vol<=watsat)[m3/m3]
418 real(kind_lake) :: t_grnd(1) ! ground temperature (Kelvin)
419 real(kind_lake) :: h2osno(1) ! snow water (mm H2O)
420 real(kind_lake) :: snowdp(1) ! snow height (m)
421 real(kind_lake) :: z(1,-nlevsnow+1:nlevsoil) ! layer depth for snow & soil (m)
422 real(kind_lake) :: dz(1,-nlevsnow+1:nlevsoil) ! layer thickness for soil or snow (m)
423 real(kind_lake) :: t_soisno(1,-nlevsnow+1:nlevsoil) ! soil (or snow) temperature (Kelvin)
424 real(kind_lake) :: t_lake(1,nlevlake) ! lake temperature (Kelvin)
425 integer :: snl(1) ! number of snow layers
426 real(kind_lake) :: h2osoi_liq(1,-nlevsnow+1:nlevsoil) ! liquid water (kg/m2)
427 real(kind_lake) :: h2osoi_ice(1,-nlevsnow+1:nlevsoil) ! ice lens (kg/m2)
428 real(kind_lake) :: savedtke1(1) ! top level eddy conductivity from previous timestep (W/m.K)
429 real(kind_lake) :: zi(1,-nlevsnow+0:nlevsoil) ! interface level below a "z" level (m)
430 real(kind_lake) :: lake_icefrac(1,nlevlake) ! mass fraction of lake layer that is frozen
431
432
433 !out:
434 real(kind_lake) :: eflx_gnet(1) !net heat flux into ground (W/m**2)
435 real(kind_lake) :: eflx_lwrad_net(1) ! net infrared (longwave) rad (W/m**2) [+ = to atm]
436 real(kind_lake) :: eflx_sh_tot(1) ! total sensible heat flux (W/m**2) [+ to atm]
437 real(kind_lake) :: eflx_lh_tot(1) ! total latent heat flux (W/m8*2) [+ to atm]
438 real(kind_lake) :: t_ref2m(1) ! 2 m height surface air temperature (Kelvin)
439 real(kind_lake) :: q_ref2m(1) ! 2 m height surface specific humidity (kg/kg)
440 real(kind_lake) :: taux(1) ! wind (shear) stress: e-w (kg/m/s**2)
441 real(kind_lake) :: tauy(1) ! wind (shear) stress: n-s (kg/m/s**2)
442 real(kind_lake) :: ram1(1) ! aerodynamical resistance (s/m)
443 ! for calculation of decay of eddy diffusivity with depth
444 ! Change the type variable to pass back to WRF.
445 real(kind_lake) :: z0mg(1) ! roughness length over ground, momentum (m(
446 real(kind_lake) :: qfx ! mass flux, old WRF qfx(:) variable, (kg/(sm^2))
447
448 real(kind_lake) :: ustar_out(1) ! friction velocity (temporary) [m/s]
449
450 real(kind_lake) :: discard1, discard2, discard3 ! for unused temporary data
451
452 real(kind_lake) :: watsat(1,nlevsoil) ! volumetric soil water at saturation (porosity)
453 real(kind_lake) :: tksatu(1,nlevsoil) ! thermal conductivity, saturated soil [W/m-K]
454 real(kind_lake) :: tkmg(1,nlevsoil) ! thermal conductivity, soil minerals [W/m-K]
455 real(kind_lake) :: tkdry(1,nlevsoil) ! thermal conductivity, dry soil (W/m/Kelvin)
456 real(kind_lake) :: csol(1,nlevsoil) ! heat capacity, soil solids (J/m**3/Kelvin)
457
458! real(kind_lake) :: emiss ! surface emissivity
459
460 integer :: lake_points, snow_points, ice_points
461 character*255 :: message
462 logical, parameter :: feedback_to_atmosphere = .true. ! FIXME: REMOVE
463
464 real(kind_lake) :: to_radians, lat_d, lon_d, qss, tkm, bd
465 real(kind_lake) :: rho0 ! lowest model level air density
466
467 integer :: month,num1,num2,day_of_month,isl
468 real(kind_lake) :: wght1,wght2,tclim,depthratio
469
470 logical salty_flag, cannot_freeze_flag
471
472 errmsg = ' '
473 errflg = 0
474
475 if(iopt_lake/=iopt_lake_clm .or. lkm==0 .or. all(use_lake_model==0)) then
476 return ! nothing to do
477 endif
478
479 dtime=dtp
480
481 ! Initialize any uninitialized lake points.
482 call lakeini(kdt=kdt, isltyp=isltyp, gt0=gt0, snowd=snowd, weasd=weasd, &
483 lakedepth_default=lakedepth_default, fhour=fhour, &
484 oro_lakedepth=oro_lakedepth, savedtke12d=savedtke12d, snowdp2d=snowdp2d, &
485 h2osno2d=h2osno2d, snl2d=snl2d, t_grnd2d=t_grnd2d, t_lake3d=t_lake3d, &
486 lake_icefrac3d=lake_icefrac3d, &
487 t_soisno3d=t_soisno3d, h2osoi_ice3d=h2osoi_ice3d, h2osoi_liq3d=h2osoi_liq3d, &
488 h2osoi_vol3d=h2osoi_vol3d, z3d=z3d, dz3d=dz3d, zi3d=zi3d, &
489 fice=fice, hice=hice, min_lakeice=min_lakeice, &
490 tsfc=tsfc, &
491 use_lake_model=use_lake_model, use_lakedepth=use_lakedepth, &
492 im=im, prsi=prsi, xlat_d=xlat_d, xlon_d=xlon_d, &
493 clm_lake_initialized=clm_lake_initialized, input_lakedepth=input_lakedepth, &
494 tg3=tg3, clm_lakedepth=clm_lakedepth, km=km, me=me, master=master, &
495 errmsg=errmsg, errflg=errflg)
496 if(errflg/=0) then
497 return
498 endif
499
500 lake_points=0
501 snow_points=0
502 ice_points=0
503
504 to_radians = pi/180
505
506 month = idate(2)
507 day_of_month = idate(3)
508
509 num1 = month*2-1
510 if(day_of_month>15) then
511 num1 = num1 + 1
512 endif
513 num2 = num1+1
514
515 wght2 = day_of_month/month_length(month)
516 if(wght2<0 .or. wght2>1) then
517 if(debug_print) then
518 write(0,*) 'Warning: wght2 is not 0..1: ',wght2
519 endif
520 wght2 = max(0.0_kind_lake,min(1.0_kind_lake,wght2))
521 endif
522 wght1 = 1.0_kind_lake - wght2
523
524 if(debug_print ) then
525 print *,'month,num1,num2,wght1,wght2',month,num1,num2,wght1,wght2
526 endif
527
528 lake_top_loop: DO i = 1,im
529
530 if_lake_is_here: if (flag_iter(i) .and. use_lake_model(i)/=0) THEN
531
532 call is_salty(xlat_d(i),xlon_d(i),salty_flag,cannot_freeze_flag)
533
534 if(salty_flag) then
535 salty(i) = 1 ! The Great Salt Lake and Mono Lake
536 else
537 salty(i) = 0
538 endif
539
540 if(cannot_freeze_flag) then
541 cannot_freeze(i) = 1 ! only the Great Salt Lake
542 else
543 cannot_freeze(i) = 0
544 endif
545
546 sfctmp = gt0(i,1)
547 pbot = prsi(i,1)
548 psfc = pgr(i)
549 q2k = qvcurr(i)
550! EMISS = 0.99 * lake_icefrac3d(i,1) + emg * (1.0-lake_icefrac3d(i,1)) ! emg=0.97, parameter, needs to be moved to the top
551 lwdn = dlwsfci(i) ! LWDN is downward LW flux, do not use EMISS here.
552! LWDN = DLWSFCI(I)*EMISS(I)
553 ! FIXME: Should multiply PRCP by 1000
554 prcp = (raincprv(i)+rainncprv(i))/dtime ! [mm/s] use physics timestep since PRCP comes from non-surface schemes
555 soldn = dswsfci(i) ! SOLDN is total incoming solar
556 albedo(i) = ( 0.6 * lake_icefrac3d(i,1) ) + &
557 ( (1.0-lake_icefrac3d(i,1)) * 0.08)
558 solnet = soldn*(1.-albedo(i)) ! use mid-day albedo to determine net downward solar
559 ! (no solar zenith angle correction)
560
561 lake_points = lake_points+1
562
563 call calculate_z_dz_lake(i,input_lakedepth,clm_lakedepth,z_lake(1,:),dz_lake(1,:))
564
565 do c = 2,column
566 z_lake(c,:) = z_lake(1,:)
567 dz_lake(c,:) = dz_lake(1,:)
568 enddo
569
570 ! Soil hydraulic and thermal properties
571 isl = isltyp(i)
572 if (isl == 0 ) isl = 14
573 if (isl == 14 ) isl = isl + 1
574
575 watsat = 0.489_kind_lake - 0.00126_kind_lake*sand(isl)
576 csol = (2.128_kind_lake*sand(isl)+2.385_kind_lake*clay(isl)) / (sand(isl)+clay(isl))*1.e6_kind_lake ! J/(m3 K)
577 tkm = (8.80_kind_lake*sand(isl)+2.92_kind_lake*clay(isl))/(sand(isl)+clay(isl)) ! W/(m K)
578 bd = (1._kind_lake-watsat(1,1))*2.7e3_kind_lake
579 tkmg = tkm ** (1._kind_lake- watsat(1,1))
580 tkdry = (0.135_kind_lake*bd + 64.7_kind_lake) / (2.7e3_kind_lake - 0.947_kind_lake*bd)
581 tksatu = tkmg(1,1)*0.57_kind_lake**watsat(1,1)
582
583 do c = 1,column
584
585 forc_t(c) = sfctmp ! [K]
586 forc_pbot(c) = pbot ! [Pa]
587 forc_psrf(c) = psfc ! [Pa]
588 forc_hgt(c) = zlvl(i) ! [m]
589 forc_hgt_q(c) = zlvl(i) ! [m]
590 forc_hgt_t(c) = zlvl(i) ! [m]
591 forc_hgt_u(c) = zlvl(i) ! [m]
592 forc_q(c) = q2k ! [kg/kg]
593 forc_u(c) = gu0(i,1) ! [m/s]
594 forc_v(c) = gv0(i,1) ! [m/s]
595 forc_lwrad(c) = lwdn ! [W/m/m]
596 prec(c) = prcp ! [mm/s]
597 sabg(c) = solnet
598 lat(c) = xlat_d(i)*to_radians ! [radian]
599 do_capsnow(c) = .false.
600
601 lakedepth(c) = clm_lakedepth(i)
602 savedtke1(c) = savedtke12d(i)
603 snowdp(c) = snowdp2d(i)
604 h2osno(c) = h2osno2d(i)
605 snl(c) = snl2d(i)
606 t_grnd(c) = t_grnd2d(i)
607 do k = 1,nlevlake
608 t_lake(c,k) = t_lake3d(i,k)
609 lake_icefrac(c,k) = lake_icefrac3d(i,k)
610 enddo
611 do k = -nlevsnow+1,nlevsoil
612 t_soisno(c,k) = t_soisno3d(i,k)
613 h2osoi_ice(c,k) = h2osoi_ice3d(i,k)
614 h2osoi_liq(c,k) = h2osoi_liq3d(i,k)
615 h2osoi_vol(c,k) = h2osoi_vol3d(i,k)
616 z(c,k) = z3d(i,k)
617 dz(c,k) = dz3d(i,k)
618 enddo
619 do k = -nlevsnow+0,nlevsoil
620 zi(c,k) = zi3d(i,k)
621 enddo
622 enddo
623
624 eflx_lwrad_net = -9999
625 eflx_gnet = -9999
626 eflx_sh_tot = -9999
627 eflx_lh_tot = -9999
628 t_ref2m = -9999
629 q_ref2m = -9999
630 taux = -9999
631 tauy = -9999
632 ram1 = -9999
633 z0mg = -9999
634 ustar_out = -9999
635 lat_d = xlat_d(i)
636 lon_d = xlon_d(i)
637
638 CALL lakemain(forc_t,forc_pbot,forc_psrf,forc_hgt,forc_hgt_q, & !I
639 forc_hgt_t,forc_hgt_u,forc_q, forc_u, &
640 forc_v,forc_lwrad,prec, sabg,lat, &
641 z_lake,dz_lake,lakedepth,do_capsnow, &
642 h2osno,snowdp,snl,z,dz,zi, & !H
643 h2osoi_vol,h2osoi_liq,h2osoi_ice, &
644 t_grnd,t_soisno,t_lake, &
645 savedtke1,lake_icefrac, &
646 eflx_lwrad_net,eflx_gnet, & !O
647 eflx_sh_tot,eflx_lh_tot, &
648 t_ref2m,q_ref2m, dtime, &
649 watsat, tksatu, tkmg, tkdry, csol, &
650 taux,tauy,ram1,z0mg,ustar_out,errmsg,errflg, &
651 lat_d,lon_d)
652 ! Renew Lake State Variables:(14)
653 do c = 1,column
654
655 if(cannot_freeze(i) == 1) then
656 ! The Great Salt Lake
657 do k = 1,nlevlake
658 lake_icefrac(c,k) = 0._kind_lake
659 enddo
660 ! bound lake temperture with the climatology
661 tclim = tfrz + wght1*saltlk_t(num1) &
662 + wght2*saltlk_t(num2)
663 if(debug_print) print *,'GSL - Tclim,tsfc,t_lake3d',i,tclim,t_grnd(c),t_lake(c,:),t_soisno(c,:)
664 t_grnd(c) = min(tclim+3.0_kind_lake,(max(t_grnd(c),tclim-3.0_kind_lake)))
665 do k = 1,nlevlake
666 t_lake(c,k) = min(tclim+3.0_kind_lake,(max(t_lake(c,k),tclim-3.0_kind_lake)))
667 enddo
668 t_soisno(c,1) = min(tclim+3.0_kind_lake,(max(t_soisno(c,1),tclim-3.0_kind_lake)))
669 if(debug_print) print *,'GSL - after Tclim,tsfc,t_lake3d',i,tclim,t_grnd(c),t_lake(c,:),t_soisno(c,:)
670 elseif(salty(i) == 1) then
671 ! Mono Lake never freezes, its temperature is above freezing point = -4.2 C
672 t_grnd(c) = max(tfrz-4.2_kind_lake,t_grnd(c))
673 do k = 1,nlevlake
674 lake_icefrac(c,k) = 0._kind_lake
675 t_lake(c,k) = max(tfrz-4.2_kind_lake,t_lake(c,k))
676 enddo
677 t_soisno(c,1) = max(tfrz-4.2_kind_lake,t_soisno(c,1))
678 if(debug_print) print *,'Mono - tsfc,t_lake3d',i,t_grnd(c),t_lake(c,:),t_soisno(c,:)
679 endif
680
681 savedtke12d(i) = savedtke1(c)
682 snowdp2d(i) = snowdp(c)
683 h2osno2d(i) = h2osno(c)
684 snl2d(i) = snl(c)
685 t_grnd2d(i) = t_grnd(c)
686 do k = 1,nlevlake
687 t_lake3d(i,k) = t_lake(c,k)
688 lake_icefrac3d(i,k) = lake_icefrac(c,k)
689 enddo
690 do k = -nlevsnow+1,nlevsoil
691 z3d(i,k) = z(c,k)
692 dz3d(i,k) = dz(c,k)
693 t_soisno3d(i,k) = t_soisno(c,k)
694 h2osoi_liq3d(i,k) = h2osoi_liq(c,k)
695 h2osoi_ice3d(i,k) = h2osoi_ice(c,k)
696 h2osoi_vol3d(i,k) = h2osoi_vol(c,k)
697 enddo
698 do k = -nlevsnow+0,nlevsoil
699 zi3d(i,k) = zi(c,k)
700 enddo
701
702 enddo
703
704 feedback: if(feedback_to_atmosphere) then
705 c = 1
706
707 !-- The CLM output is combined for fractional ice and water
708 if( t_grnd(c) >= tfrz ) then
709 qfx = eflx_lh_tot(c)*invhvap
710 else
711 qfx = eflx_lh_tot(c)*invhsub ! heat flux (W/m^2)=>mass flux(kg/(sm^2))
712 endif
713 rho0 = prsl1(i) / (rair*t1(i)*(1.0 + con_fvirt*qv1(i)))
714 evap_wat(i) = qfx/rho0 ! kinematic_surface_upward_latent_heat_flux_over_water
715 hflx_wat(i) = eflx_sh_tot(c)/(rho0*cpair) ! kinematic_surface_upward_sensible_heat_flux_over_water
716 gflx_wat(i) = eflx_gnet(c) ![W/m/m] upward_heat_flux_in_soil_over_water
717 ep1d_water(i) = eflx_lh_tot(c) ![W/m/m] surface_upward_potential_latent_heat_flux_over_water
718 !don't overwrite surface skin temperature over ice, sea ice area fraction, skin temperature over water when using CDEPS inline over the mask
719 if (use_cdeps_data) then
720 if (mask_dat(i) <= 0.0) then
721 tsfc_wat(i) = t_grnd(c) ![K] surface skin temperature over water
722 tisfc(i) = t_grnd(c)
723 fice(i) = lake_icefrac3d(i,1) ! sea_ice_area_fraction_of_sea_area_fraction
724 tsurf_water(i) = t_grnd(c) ![K] surface skin temperature after iteration over water
725 tsurf_ice(i) = t_grnd(c) ! surface_skin_temperature_after_iteration_over_ice
726 endif
727 else
728 tsfc_wat(i) = t_grnd(c) ![K] surface skin temperature over water
729 tisfc(i) = t_grnd(c)
730 fice(i) = lake_icefrac3d(i,1) ! sea_ice_area_fraction_of_sea_area_fraction
731 tsurf_water(i) = t_grnd(c) ![K] surface skin temperature after iteration over water
732 tsurf_ice(i) = t_grnd(c) ! surface_skin_temperature_after_iteration_over_ice
733 endif
734 tsfc(i) = t_grnd(c)
735 lake_t2m(i) = t_ref2m(c) ![K] temperature_at_2m_from_clm_lake
736 lake_q2m(i) = q_ref2m(c) ! [frac] specific_humidity_at_2m_from_clm_lake
737 albedo(i) = ( 0.6 * lake_icefrac3d(i,1) ) + & ! mid_day_surface_albedo_over_lake
738 ( (1.0-lake_icefrac3d(i,1)) * 0.08)
739 !uustar_water(i) = ustar_out(c) ! surface_friction_velocity_over_water
740 zorlw(i) = z0mg(c) ! surface_roughness_length_over_water
741
742 ! WRF variables with no equivalent in CCPP:
743 ! LH(I) = eflx_lh_tot(c)/rho1(i) ![kg*m/(kg*s)]
744 !TH2(I) = T2(I)*(1.E5/PSFC)**RCP ! potential temperature
745
746 ! Calculate qsfc from t_grnd: ! surface_specific_humidity_over_water
747 psfc = prsi(i,1)
748 discard1 = -9999
749 discard2 = -9999
750 discard3 = -9999
751 qss = qss_water(i)
752 call qsat(t_grnd(c),psfc,discard1,discard2,qss,discard3)
753 qss_water(i) = qss
754
755 ! Combined water-ice chh and cmm calculations come from Flake model:
756 chh_water(i) = ch(i)*wind(i)*1.225 ! surface_drag_mass_flux_for_heat_and_moisture_in_air_over_water
757 cmm_water(i) = cm(i)*wind(i) ! surface_drag_wind_speed_for_momentum_in_air_over_water
758
759 ice_point: if(fice(i)>=min_lakeice) then
760 ! Icy lake
761 ! Most ice variables are identical to water variables.
762 if(debug_print) print *,'Icy xlat_d(i),xlon_d(i),frac_ice,frac_grid ',xlat_d(i),xlon_d(i),frac_ice,frac_grid
763 if(frac_ice .or. frac_grid) then
764 evap_ice(i) = evap_wat(i) ! kinematic_surface_upward_latent_heat_flux_over_ice
765 hflx_ice(i) = hflx_wat(i) ! kinematic_surface_upward_sensible_heat_flux_over_ice
766 gflx_ice(i) = gflx_wat(i) ! upward_heat_flux_in_soil_over_ice
767 ep1d_ice(i) = ep1d_water(i) ! surface_upward_potential_latent_heat_flux_over_ice
768 chh_ice(i) = chh_water(i) ! surface_drag_mass_flux_for_heat_and_moisture_in_air_over_ice
769 cmm_ice(i) = cmm_water(i) ! surface_drag_wind_speed_for_momentum_in_air_over_ice
770 qss_ice(i) = qss_water(i) ! surface_specific_humidity_over_ice
771! uustar_ice(i) = uustar_water(i) ! surface_friction_velocity_over_ice
772 endif
773
774 !don't overwrite surface skin temperature over ice when using CDEPS inline over the mask
775 if (use_cdeps_data) then
776 if (mask_dat(i) <= 0.0) then
777 tisfc(i) = t_grnd(c)
778 tsurf_ice(i) = t_grnd(c) ! surface_skin_temperature_after_iteration_over_ice
779 endif
780 else
781 tisfc(i) = t_grnd(c)
782 tsurf_ice(i) = t_grnd(c) ! surface_skin_temperature_after_iteration_over_ice
783 endif
784 tsfc(i) = t_grnd(c) ! surface_skin_temperature_over_ice
785 weasdi(i) = h2osno(c) ! water_equivalent_accumulated_snow_depth_over_ice
786 snodi(i) = snowdp(c)*1.e3 ! surface_snow_thickness_water_equivalent_over_ice
787 weasd(i) = weasdi(i)
788 snowd(i) = snodi(c) ! surface_snow_thickness_water_equivalent_over_ice
789
790
791 if (.not. icy(i)) then
792 flag_lakefreeze(i)=.true.
793 end if
794
795 ! Ice points are icy:
796 icy(i)=.true. ! flag_nonzero_sea_ice_surface_fraction
797 ice_points = ice_points+1
798
799 zorli(i) = z0mg(c) ! surface_roughness_length_over_ice
800
801 ! Assume that, if a layer has ice, the entire layer thickness is ice.
802 !don't overwrite sea ice thickness when using CDEPS inline over the mask
803 if (use_cdeps_data) then
804 if (mask_dat(i) <= 0.0) then
805 hice(i) = 0 ! sea_ice_thickness
806 do k=1,nlevlake
807 if(lake_icefrac3d(i,k)>0) then
808 hice(i) = hice(i) + dz_lake(c,k)
809 endif
810 end do
811 endif
812 else
813 hice(i) = 0 ! sea_ice_thickness
814 do k=1,nlevlake
815 if(lake_icefrac3d(i,k)>0) then
816 hice(i) = hice(i) + dz_lake(c,k)
817 endif
818 end do
819 endif
820
821 else ! Not an ice point
822 ! On non-icy lake points, set variables relevant to
823 ! lake ice to reasonable defaults. Let LSM fill in
824 ! other variables.
825 icy(i)=.false.
826 weasdi(i) = 0
827 snodi(i) = 0
828 weasd(i) = 0
829 snowd(i) = 0
830 !don't overwrite surface skin temperature over ice when using CDEPS inline over the mask
831 if (use_cdeps_data) then
832 if (mask_dat(i) <= 0.0) then
833 tisfc(i) = t_grnd(c)
834 tsurf_ice(i) = tisfc(i)
835 endif
836 else
837 tisfc(i) = t_grnd(c)
838 tsurf_ice(i) = tisfc(i)
839 endif
840 tsfc(i) = t_grnd(c)
841 !don't overwrite sea ice thickness when using CDEPS inline over the mask
842 if (use_cdeps_data) then
843 if (mask_dat(i) <= 0.0) then
844 hice(i) = 0
845 fice(i) = 0
846 endif
847 else
848 hice(i) = 0
849 fice(i) = 0
850 endif
851 endif ice_point
852
853 if(snl2d(i)<0) then
854 ! If there is snow, ice surface temperature should be snow temperature.
855 lake_t_snow(i) = t_grnd(c) ! surface_skin_temperature_over_ice
856 !don't overwrite surface skin temperature over ice when using CDEPS inline over the mask
857 if (use_cdeps_data) then
858 if (mask_dat(i) <= 0.0) then
859 tisfc(i) = lake_t_snow(i) ! temperature_of_snow_on_lake
860 endif
861 else
862 tisfc(i) = lake_t_snow(i) ! temperature_of_snow_on_lake
863 endif
864 snow_points = snow_points+1
865 else
866 lake_t_snow(i) = -9999
867 endif
868
869 endif feedback
870
871 endif if_lake_is_here
872 ENDDO lake_top_loop
873
874 if(debug_print .and. lake_points>0 .and. (kdt<3 .or. mod(kdt,30)==3)) then
8753082 format('lake points processed in timestep ',i0,' by rank ',i0,' = ',i0,' snow=',i0,' ice=',i0)
876 print 3082,kdt,me,lake_points,snow_points,ice_points
877 endif
878
879 END SUBROUTINE clm_lake_run
880
881
882 SUBROUTINE lakemain(forc_t,forc_pbot,forc_psrf,forc_hgt,forc_hgt_q, & !I
883 forc_hgt_t,forc_hgt_u,forc_q, forc_u, &
884 forc_v,forc_lwrad,prec, sabg,lat, &
885 z_lake,dz_lake,lakedepth,do_capsnow, &
886 h2osno,snowdp,snl,z,dz,zi, & !H
887 h2osoi_vol,h2osoi_liq,h2osoi_ice, &
888 t_grnd,t_soisno,t_lake, &
889 savedtke1,lake_icefrac, &
890 eflx_lwrad_net,eflx_gnet, & !O
891 eflx_sh_tot,eflx_lh_tot, &
892 t_ref2m,q_ref2m, dtime, &
893 watsat, tksatu, tkmg, tkdry, csol, &
894 taux,tauy,ram1,z0mg,ustar_out,errmsg,errflg, xlat_d,xlon_d)
895 implicit none
896 !in:
897
898 integer, intent(inout) :: errflg
899 character(*), intent(inout) :: errmsg
900 real(kind_lake),intent(in) :: dtime
901 real(kind_lake),intent(in) :: xlat_d, xlon_d
902 real(kind_lake),intent(in) :: forc_t(1)
903 real(kind_lake),intent(in) :: forc_pbot(1)
904 real(kind_lake),intent(in) :: forc_psrf(1)
905 real(kind_lake),intent(in) :: forc_hgt(1)
906 real(kind_lake),intent(in) :: forc_hgt_q(1)
907 real(kind_lake),intent(in) :: forc_hgt_t(1)
908 real(kind_lake),intent(in) :: forc_hgt_u(1)
909 real(kind_lake),intent(in) :: forc_q(1)
910 real(kind_lake),intent(in) :: forc_u(1)
911 real(kind_lake),intent(in) :: forc_v(1)
912 ! real(kind_lake),intent(in) :: forc_rho(1) ! density (kg/m**3)
913 real(kind_lake),intent(in) :: forc_lwrad(1)
914 real(kind_lake),intent(in) :: prec(1)
915 real(kind_lake),intent(in) :: sabg(1)
916 real(kind_lake),intent(in) :: lat(1)
917 real(kind_lake),intent(in) :: z_lake(1,nlevlake)
918 real(kind_lake),intent(in) :: dz_lake(1,nlevlake)
919 real(kind_lake),intent(out) :: ustar_out(1)
920 real(kind_lake), intent(in) :: lakedepth(1)!!!!!!!!!!!!!!tep(in),hydro(in)
922 ! real(kind_lake), intent(in) :: watsat(1,1:nlevsoil) ! volumetric soil water at saturation (porosity)
923 !!!!!!!!!!!!!!!!hydro
924 logical , intent(in) :: do_capsnow(1)
925 real(kind_lake), intent(in) :: watsat(1,nlevsoil)
926 real(kind_lake), intent(in) :: tksatu(1,nlevsoil)
927 real(kind_lake), intent(in) :: tkmg(1,nlevsoil)
928 real(kind_lake), intent(in) :: tkdry(1,nlevsoil)
929 real(kind_lake), intent(in) :: csol(1,nlevsoil)
930
931
932
933 !in&out
934 real(kind_lake),intent(inout) :: h2osoi_vol(1,-nlevsnow+1:nlevsoil)
935 real(kind_lake),intent(inout) :: t_grnd(1)
936 real(kind_lake),intent(inout) :: h2osno(1)
937 real(kind_lake),intent(inout) :: snowdp(1)
938 real(kind_lake),intent(inout) :: z(1,-nlevsnow+1:nlevsoil)
939 real(kind_lake),intent(inout) :: dz(1,-nlevsnow+1:nlevsoil)
940 real(kind_lake),intent(inout) :: t_soisno(1,-nlevsnow+1:nlevsoil)
941 real(kind_lake),intent(inout) :: t_lake(1,nlevlake)
942 integer ,intent(inout) :: snl(1)
943 real(kind_lake),intent(inout) :: h2osoi_liq(1,-nlevsnow+1:nlevsoil)
944 real(kind_lake),intent(inout) :: h2osoi_ice(1,-nlevsnow+1:nlevsoil)
945 real(kind_lake),intent(inout) :: savedtke1(1)
946 real(kind_lake),intent(inout) :: zi(1,-nlevsnow+0:nlevsoil)
947 real(kind_lake),intent(inout) :: lake_icefrac(1,nlevlake)
948
949
950 !out:
951 real(kind_lake),intent(out) :: eflx_gnet(1)
952 real(kind_lake),intent(out) :: eflx_lwrad_net(1)
953 real(kind_lake),intent(out) :: eflx_sh_tot(1)
954 real(kind_lake),intent(out) :: eflx_lh_tot(1)
955 real(kind_lake),intent(out) :: t_ref2m(1)
956 real(kind_lake),intent(out) :: q_ref2m(1)
957 real(kind_lake),intent(out) :: taux(1)
958 real(kind_lake),intent(out) :: tauy(1)
959 real(kind_lake),intent(out) :: ram1(1)
962 real(kind_lake),intent(out) :: z0mg(1)
963
964
965 !local output
966
967 real(kind_lake) :: begwb(1) ! water mass begining of the time step
968 real(kind_lake) :: t_veg(1) ! vegetation temperature (Kelvin)
969 real(kind_lake) :: eflx_soil_grnd(1) ! soil heat flux (W/m**2) [+ = into soil]
970 real(kind_lake) :: eflx_lh_grnd(1) ! ground evaporation heat flux (W/m**2) [+ to atm]
971 real(kind_lake) :: eflx_sh_grnd(1) ! sensible heat flux from ground (W/m**2) [+ to atm]
972 real(kind_lake) :: eflx_lwrad_out(1) ! emitted infrared (longwave) radiation (W/m**2)
973 real(kind_lake) :: qflx_evap_tot(1) ! qflx_evap_soi + qflx_evap_veg + qflx_tran_veg
974 real(kind_lake) :: qflx_evap_soi(1) ! soil evaporation (mm H2O/s) (+ = to atm)
975 real(kind_lake) :: qflx_prec_grnd(1) ! water onto ground including canopy runoff [kg/(m2 s)]
976 real(kind_lake) :: forc_snow(1) ! snow rate [mm/s]
977 real(kind_lake) :: forc_rain(1) ! rain rate [mm/s]
978 real(kind_lake) :: ws(1) ! surface friction velocity (m/s)
979 real(kind_lake) :: ks(1) ! coefficient passed to ShalLakeTemperature
980 real(kind_lake) :: qflx_snomelt(1) !snow melt (mm H2O /s) tem(out),snowwater(in)
981 integer :: imelt(1,-nlevsnow+1:nlevsoil) !flag for melting (=1), freezing (=2), Not=0 (new)
982 real(kind_lake) :: endwb(1) ! water mass end of the time step
983 real(kind_lake) :: snowage(1) ! non dimensional snow age [-]
984 real(kind_lake) :: snowice(1) ! average snow ice lens
985 real(kind_lake) :: snowliq(1) ! average snow liquid water
986 real(kind_lake) :: t_snow(1) ! vertically averaged snow temperature
987 real(kind_lake) :: qflx_drain(1) ! sub-surface runoff (mm H2O /s)
988 real(kind_lake) :: qflx_surf(1) ! surface runoff (mm H2O /s)
989 real(kind_lake) :: qflx_infl(1) ! infiltration (mm H2O /s)
990 real(kind_lake) :: qflx_qrgwl(1) ! qflx_surf at glaciers, wetlands, lakes
991 real(kind_lake) :: qcharge(1) ! aquifer recharge rate (mm/s)
992 real(kind_lake) :: qflx_snowcap(1) ! excess precipitation due to snow capping (mm H2O /s) [+]
993 real(kind_lake) :: qflx_snowcap_col(1) ! excess precipitation due to snow capping (mm H2O /s) [+]
994 real(kind_lake) :: qflx_snow_grnd_pft(1) ! snow on ground after interception (mm H2O/s) [+]
995 real(kind_lake) :: qflx_snow_grnd_col(1) ! snow on ground after interception (mm H2O/s) [+]
996 real(kind_lake) :: qflx_rain_grnd(1) ! rain on ground after interception (mm H2O/s) [+]
997 real(kind_lake) :: frac_iceold(1,-nlevsnow+1:nlevsoil) ! fraction of ice relative to the tot water
998 real(kind_lake) :: qflx_evap_tot_col(1) !pft quantity averaged to the column (assuming one pft)
999 real(kind_lake) :: soilalpha(1) !factor that reduces ground saturated specific humidity (-)
1000 real(kind_lake) :: zwt(1) !water table depth
1001 real(kind_lake) :: fcov(1) !fractional area with water table at surface
1002 real(kind_lake) :: rootr_column(1,1:nlevsoil) !effective fraction of roots in each soil layer
1003 real(kind_lake) :: qflx_evap_grnd(1) ! ground surface evaporation rate (mm H2O/s) [+]
1004 real(kind_lake) :: qflx_sub_snow(1) ! sublimation rate from snow pack (mm H2O /s) [+]
1005 real(kind_lake) :: qflx_dew_snow(1) ! surface dew added to snow pack (mm H2O /s) [+]
1006 real(kind_lake) :: qflx_dew_grnd(1) ! ground surface dew formation (mm H2O /s) [+]
1007 real(kind_lake) :: qflx_rain_grnd_col(1) !rain on ground after interception (mm H2O/s) [+]
1008 begwb = 0
1009
1010 ! lat = lat*pi/180 ! [radian]
1011
1012 if (prec(1)> 0.) then
1013 if ( forc_t(1) > (tfrz + tcrit)) then
1014 forc_rain(1) = prec(1)
1015 forc_snow(1) = 0.
1016 ! flfall(1) = 1.
1017 else
1018 forc_rain(1) = 0.
1019 forc_snow(1) = prec(1)
1020
1021 ! if ( forc_t(1) <= tfrz) then
1022 ! flfall(1) = 0.
1023 ! else if ( forc_t(1) <= tfrz+2.) then
1024 ! flfall(1) = -54.632 + 0.2 * forc_t(1)
1025 ! else
1026 ! flfall(1) = 0.4
1027 endif
1028 else
1029 forc_rain(1) = 0.
1030 forc_snow(1) = 0.
1031 ! flfall(1) = 1.
1032 endif
1033
1034 CALL shallakefluxes(forc_t,forc_pbot,forc_psrf,forc_hgt,forc_hgt_q, & !i
1035 forc_hgt_t,forc_hgt_u,forc_q, &
1036 forc_u,forc_v,forc_lwrad,forc_snow, &
1037 forc_rain,t_grnd,h2osno,snowdp,sabg,lat, &
1038 dz,dz_lake,t_soisno,t_lake,snl,h2osoi_liq, &
1039 h2osoi_ice,savedtke1, &
1040 qflx_prec_grnd,qflx_evap_soi,qflx_evap_tot, & !o
1041 eflx_sh_grnd,eflx_lwrad_out,eflx_lwrad_net, &
1042 eflx_soil_grnd,eflx_sh_tot,eflx_lh_tot, &
1043 eflx_lh_grnd,t_veg,t_ref2m,q_ref2m,taux,tauy, &
1044 ram1,ws,ks,eflx_gnet,z0mg,ustar_out,errmsg,errflg,xlat_d,xlon_d)
1045 if(errflg/=0) then
1046 return ! State is invalid now, so pass error to caller.
1047 endif
1048
1049 CALL shallaketemperature(t_grnd,h2osno,sabg,dz,dz_lake,z,zi, & !i
1050 z_lake,ws,ks,snl,eflx_gnet,lakedepth, &
1051 lake_icefrac,snowdp, & !i&o
1052 eflx_sh_grnd,eflx_sh_tot,eflx_soil_grnd, & !o
1053 t_lake,t_soisno,h2osoi_liq, &
1054 h2osoi_ice,savedtke1, &
1055 watsat, tksatu, tkmg, tkdry, csol, dtime, &
1056 frac_iceold,qflx_snomelt,imelt,errmsg,errflg,xlat_d,xlon_d)
1057 if(errflg/=0) then
1058 return ! State is invalid now, so pass error to caller.
1059 endif
1060
1061 CALL shallakehydrology(dz_lake,forc_rain,forc_snow, & !i
1062 begwb,qflx_evap_tot,forc_t,do_capsnow, &
1063 t_grnd,qflx_evap_soi, &
1064 qflx_snomelt,imelt,frac_iceold, & !i add by guhp
1065 z,dz,zi,snl,h2osno,snowdp,lake_icefrac,t_lake, & !i&o
1066 endwb,snowage,snowice,snowliq,t_snow, & !o
1067 t_soisno,h2osoi_ice,h2osoi_liq,h2osoi_vol, &
1068 qflx_drain,qflx_surf,qflx_infl,qflx_qrgwl, &
1069 qcharge,qflx_prec_grnd,qflx_snowcap, &
1070 qflx_snowcap_col,qflx_snow_grnd_pft, &
1071 qflx_snow_grnd_col,qflx_rain_grnd, &
1072 qflx_evap_tot_col,soilalpha,zwt,fcov, &
1073 rootr_column,qflx_evap_grnd,qflx_sub_snow, &
1074 qflx_dew_snow,qflx_dew_grnd,qflx_rain_grnd_col, &
1075 watsat, tksatu, tkmg, tkdry, csol, &
1076 dtime,errmsg,errflg)
1077 if(errflg/=0) then
1078 return ! State is invalid now, so pass error to caller.
1079 endif
1080
1081 !==================================================================================
1082 ! !DESCRIPTION:
1083 ! Calculation of Shallow Lake Hydrology. Full hydrology of snow layers is
1084 ! done. However, there is no infiltration, and the water budget is balanced with
1085
1086 END SUBROUTINE lakemain
1087
1088
1089 ! DESCRIPTION:
1096SUBROUTINE shallakefluxes(forc_t,forc_pbot,forc_psrf,forc_hgt,forc_hgt_q, & !i
1097 forc_hgt_t,forc_hgt_u,forc_q, &
1098 forc_u,forc_v,forc_lwrad,forc_snow, &
1099 forc_rain,t_grnd,h2osno,snowdp,sabg,lat, &
1100 dz,dz_lake,t_soisno,t_lake,snl,h2osoi_liq, &
1101 h2osoi_ice,savedtke1, &
1102 qflx_prec_grnd,qflx_evap_soi,qflx_evap_tot, & !o
1103 eflx_sh_grnd,eflx_lwrad_out,eflx_lwrad_net, &
1104 eflx_soil_grnd,eflx_sh_tot,eflx_lh_tot, &
1105 eflx_lh_grnd,t_veg,t_ref2m,q_ref2m,taux,tauy, &
1106 ram1,ws,ks,eflx_gnet,z0mg,ustar_out,errmsg,errflg,xlat_d,xlon_d)
1107 !==============================================================================
1108 ! REVISION HISTORY:
1109 ! - Created by Zack Subin, 2009
1110 ! - Reedited by Hongping Gu, 2010
1111 ! - Updated for CCPP by Sam Trahan, 2022
1112 !==============================================================================
1113
1114 ! implicit none
1115
1116 implicit none
1117
1118 !in:
1119
1120 integer, intent(inout) :: errflg
1121 character(len=*), intent(inout) :: errmsg
1122 real(kind_lake),intent(in) :: xlat_d,xlon_d
1123 real(kind_lake),intent(in) :: forc_t(1)
1124 real(kind_lake),intent(in) :: forc_pbot(1)
1125 real(kind_lake),intent(in) :: forc_psrf(1)
1126 real(kind_lake),intent(in) :: forc_hgt(1)
1127 real(kind_lake),intent(in) :: forc_hgt_q(1)
1128 real(kind_lake),intent(in) :: forc_hgt_t(1)
1129 real(kind_lake),intent(in) :: forc_hgt_u(1)
1130 real(kind_lake),intent(in) :: forc_q(1)
1131 real(kind_lake),intent(in) :: forc_u(1)
1132 real(kind_lake),intent(in) :: forc_v(1)
1133 real(kind_lake),intent(in) :: forc_lwrad(1)
1134 ! real(kind_lake),intent(in) :: forc_rho(1) ! density (kg/m**3)
1135 real(kind_lake),intent(in) :: forc_snow(1)
1136 real(kind_lake),intent(in) :: forc_rain(1)
1137 real(kind_lake),intent(in) :: h2osno(1)
1138 real(kind_lake),intent(in) :: snowdp(1)
1139 real(kind_lake),intent(in) :: sabg(1)
1140 real(kind_lake),intent(in) :: lat(1)
1141 real(kind_lake),intent(in) :: dz(1,-nlevsnow+1:nlevsoil)
1142 real(kind_lake),intent(in) :: dz_lake(1,nlevlake)
1143 real(kind_lake),intent(in) :: t_soisno(1,-nlevsnow+1:nlevsoil)
1144 real(kind_lake),intent(in) :: t_lake(1,nlevlake)
1145 integer ,intent(in) :: snl(1)
1146 real(kind_lake),intent(in) :: h2osoi_liq(1,-nlevsnow+1:nlevsoil)
1147 real(kind_lake),intent(in) :: h2osoi_ice(1,-nlevsnow+1:nlevsoil)
1148 real(kind_lake),intent(in) :: savedtke1(1)
1149
1150 !inout:
1151 real(kind_lake),intent(inout) :: t_grnd(1)
1152 !out:
1153 real(kind_lake),intent(out):: ustar_out(1)
1154 real(kind_lake),intent(out):: qflx_prec_grnd(1)
1155 real(kind_lake),intent(out):: qflx_evap_soi(1)
1156 real(kind_lake),intent(out):: qflx_evap_tot(1)
1157 real(kind_lake),intent(out):: eflx_sh_grnd(1)
1158 real(kind_lake),intent(out):: eflx_lwrad_out(1)
1159 real(kind_lake),intent(out):: eflx_lwrad_net(1)
1160 real(kind_lake),intent(out):: eflx_soil_grnd(1)
1161 real(kind_lake),intent(out):: eflx_sh_tot(1)
1162 real(kind_lake),intent(out):: eflx_lh_tot(1)
1163 real(kind_lake),intent(out):: eflx_lh_grnd(1)
1164 real(kind_lake),intent(out):: t_veg(1)
1165 real(kind_lake),intent(out):: t_ref2m(1)
1166 real(kind_lake),intent(out):: q_ref2m(1)
1167 real(kind_lake),intent(out):: taux(1)
1168 real(kind_lake),intent(out):: tauy(1)
1169 real(kind_lake),intent(out):: ram1(1)
1170 real(kind_lake),intent(out):: ws(1)
1171 real(kind_lake),intent(out):: ks(1)
1173 real(kind_lake),intent(out):: eflx_gnet(1)
1175 real(kind_lake),intent(out):: z0mg(1)
1176
1177
1178
1179 !OTHER LOCAL VARIABLES:
1180
1181 integer , parameter :: islak = 2 ! index of lake, 1 = deep lake, 2 = shallow lake
1182 integer , parameter :: niters = 3 ! maximum number of iterations for surface temperature
1183 real(kind_lake), parameter :: beta1 = 1._kind_lake ! coefficient of convective velocity (in computing W_*) [-]
1184 real(kind_lake), parameter :: emg = 0.97_kind_lake ! ground emissivity (0.97 for water)
1185 real(kind_lake), parameter :: zii = 1000._kind_lake! convective boundary height [m]
1186 real(kind_lake), parameter :: tdmax = 277._kind_lake ! temperature of maximum water density
1187 real(kind_lake) :: forc_th(1) ! atmospheric potential temperature (Kelvin)
1188 real(kind_lake) :: forc_vp(1) !atmospheric vapor pressure (Pa)
1189 real(kind_lake) :: forc_rho(1) ! density (kg/m**3)
1190 integer :: i,fc,fp,g,c,p ! do loop or array index
1191 integer :: fncopy ! number of values in pft filter copy
1192 integer :: fnold ! previous number of pft filter values
1193 integer :: fpcopy(num_shlakep) ! pft filter copy for iteration loop
1194 integer :: iter ! iteration index
1195 integer :: nmozsgn(lbp:ubp) ! number of times moz changes sign
1196 integer :: jtop(lbc:ubc) ! top level for each column (no longer all 1)
1197 real(kind_lake) :: ax ! used in iteration loop for calculating t_grnd (numerator of NR solution)
1198 real(kind_lake) :: bx ! used in iteration loop for calculating t_grnd (denomin. of NR solution)
1199 real(kind_lake) :: degdt ! d(eg)/dT
1200 real(kind_lake) :: dqh(lbp:ubp) ! diff of humidity between ref. height and surface
1201 real(kind_lake) :: dth(lbp:ubp) ! diff of virtual temp. between ref. height and surface
1202 real(kind_lake) :: dthv ! diff of vir. poten. temp. between ref. height and surface
1203 real(kind_lake) :: dzsur(lbc:ubc) ! 1/2 the top layer thickness (m)
1204 real(kind_lake) :: eg ! water vapor pressure at temperature T [pa]
1205 real(kind_lake) :: htvp(lbc:ubc) ! latent heat of vapor of water (or sublimation) [j/kg]
1206 real(kind_lake) :: obu(lbp:ubp) ! monin-obukhov length (m)
1207 real(kind_lake) :: obuold(lbp:ubp) ! monin-obukhov length of previous iteration
1208 real(kind_lake) :: qsatg(lbc:ubc) ! saturated humidity [kg/kg]
1209 real(kind_lake) :: qsatgdt(lbc:ubc) ! d(qsatg)/dT
1210 real(kind_lake) :: qstar ! moisture scaling parameter
1211 real(kind_lake) :: ram(lbp:ubp) ! aerodynamical resistance [s/m]
1212 real(kind_lake) :: rah(lbp:ubp) ! thermal resistance [s/m]
1213 real(kind_lake) :: raw(lbp:ubp) ! moisture resistance [s/m]
1214 real(kind_lake) :: stftg3(lbp:ubp) ! derivative of fluxes w.r.t ground temperature
1215 real(kind_lake) :: temp1(lbp:ubp) ! relation for potential temperature profile
1216 real(kind_lake) :: temp12m(lbp:ubp) ! relation for potential temperature profile applied at 2-m
1217 real(kind_lake) :: temp2(lbp:ubp) ! relation for specific humidity profile
1218 real(kind_lake) :: temp22m(lbp:ubp) ! relation for specific humidity profile applied at 2-m
1219 real(kind_lake) :: tgbef(lbc:ubc) ! initial ground temperature
1220 real(kind_lake) :: thm(lbc:ubc) ! intermediate variable (forc_t+0.0098*forc_hgt_t)
1221 real(kind_lake) :: thv(lbc:ubc) ! virtual potential temperature (kelvin)
1222 real(kind_lake) :: thvstar ! virtual potential temperature scaling parameter
1223 real(kind_lake) :: tksur ! thermal conductivity of snow/soil (w/m/kelvin)
1224 real(kind_lake) :: tsur ! top layer temperature
1225 real(kind_lake) :: tstar ! temperature scaling parameter
1226 real(kind_lake) :: um(lbp:ubp) ! wind speed including the stablity effect [m/s]
1227 real(kind_lake) :: ur(lbp:ubp) ! wind speed at reference height [m/s]
1228 real(kind_lake) :: ustar(lbp:ubp) ! friction velocity [m/s]
1229 real(kind_lake) :: wc ! convective velocity [m/s]
1230 real(kind_lake) :: zeta ! dimensionless height used in Monin-Obukhov theory
1231 real(kind_lake) :: zldis(lbp:ubp) ! reference height "minus" zero displacement height [m]
1232 real(kind_lake) :: displa(lbp:ubp) ! displacement (always zero) [m]
1233 ! real(kind_lake) :: z0mg(lbp:ubp) ! roughness length over ground, momentum [m]
1234 real(kind_lake) :: z0hg(lbp:ubp) ! roughness length over ground, sensible heat [m]
1235 real(kind_lake) :: z0qg(lbp:ubp) ! roughness length over ground, latent heat [m]
1236 real(kind_lake) :: u2m ! 2 m wind speed (m/s)
1237 real(kind_lake) :: u10(1) ! 10-m wind (m/s) (for dust model)
1238 real(kind_lake) :: fv(1) ! friction velocity (m/s) (for dust model)
1239
1240 real(kind_lake) :: fm(lbp:ubp) ! needed for BGC only to diagnose 10m wind speed
1241 real(kind_lake) :: bw ! partial density of water (ice + liquid)
1242 real(kind_lake) :: t_grnd_temp ! Used in surface flux correction over frozen ground
1243 real(kind_lake) :: betaprime(lbc:ubc) ! Effective beta: 1 for snow layers, beta(islak) otherwise
1244 character*256 :: message
1245 ! tgs COARE
1246 real(kind_lake) :: tc, visc, ren
1247
1248 ! This assumes all radiation is absorbed in the top snow layer and will need
1249 ! to be changed for CLM 4.
1250 !
1251 ! Constants for lake temperature model
1252 !
1253 real(kind_lake), parameter :: beta(2) = & ! fraction solar rad absorbed at surface: depends on lake type
1254 (/0.4_kind_lake, 0.4_kind_lake/) ! (deep lake, shallow lake)
1255 ! This is the energy absorbed at the lake surface if no snow.
1256 ! data za /0.6_kind_lake, 0.5_kind_lake/
1257 ! data eta /0.1_kind_lake, 0.5_kind_lake/
1258 !-----------------------------------------------------------------------
1259
1260 ! Begin calculations
1261
1262 !dir$ concurrent
1263 !cdir nodep
1264 forc_th(1) = forc_t(1) * (forc_psrf(1)/ forc_pbot(1))**(rair/cpair)
1265 forc_vp(1) = forc_q(1) * forc_pbot(1)/ (con_eps + one_minus_con_eps * forc_q(1))
1266 forc_rho(1) = (forc_pbot(1) - one_minus_con_eps * forc_vp(1)) / (rair * forc_t(1))
1267
1268 do fc = 1, num_shlakec
1269 c = filter_shlakec(fc)
1270 g = cgridcell(c)
1271
1272 ! Surface temperature and fluxes
1273
1274 ! Find top layer
1275 if (snl(c) > 0 .or. snl(c) < -5) then
1276 errmsg='snl is not defined in ShalLakeFluxesMod; snl: out of range value'
1277 errflg=1
1278 return ! Cannot continue
1279 end if
1280 ! if (snl(c) /= 0) then
1281 ! write(6,*)'snl is not equal to zero in ShalLakeFluxesMod'
1282 ! call endrun()
1283 ! end if
1284 jtop(c) = snl(c) + 1
1285
1286
1287 if (snl(c) < 0) then
1288 betaprime(c) = 1._kind_lake !Assume all solar rad. absorbed at the surface of the top snow layer.
1289 dzsur(c) = dz(c,jtop(c))*0.5_kind_lake
1290 else
1291 betaprime(c) = beta(islak)
1292 dzsur(c) = dz_lake(c,1)*0.5_kind_lake
1293 end if
1294 ! Originally this was 1*dz, but shouldn't it be 1/2?
1295
1296 ! Saturated vapor pressure, specific humidity and their derivatives
1297 ! at lake surface
1298
1299 call qsat(t_grnd(c), forc_pbot(g), eg, degdt, qsatg(c), qsatgdt(c))
1300
1301 ! Potential, virtual potential temperature, and wind speed at the
1302 ! reference height
1303
1304 thm(c) = forc_t(g) + 0.0098_kind_lake*forc_hgt_t(g) ! intermediate variable
1305 thv(c) = forc_th(g)*(1._kind_lake+con_fvirt*forc_q(g)) ! virtual potential T
1306 end do
1307
1308 !dir$ concurrent
1309 !cdir nodep
1310 do fp = 1, num_shlakep
1311 p = filter_shlakep(fp)
1312 c = pcolumn(p)
1313 g = pgridcell(p)
1314
1315 nmozsgn(p) = 0
1316 obuold(p) = 0._kind_lake
1317 displa(p) = 0._kind_lake
1318
1319 ! Roughness lengths
1320
1321
1322 ! changed by Hongping Gu
1323 ! if (t_grnd(c) >= tfrz) then ! for unfrozen lake
1324 ! z0mg(p) = 0.01_kind_lake
1325 ! else ! for frozen lake
1326 ! ! Is this okay even if it is snow covered? What is the roughness over
1327 ! non-veg. snow?
1328 ! z0mg(p) = 0.04_kind_lake
1329 ! end if
1330
1331 if (t_grnd(c) >= tfrz) then ! for unfrozen lake
1332 z0mg(p) = 0.001_kind_lake !original 0.01
1333 else if(snl(c) == 0 ) then ! for frozen lake
1334 ! Is this okay even if it is snow covered? What is the roughness over
1335 ! non-veg. snow?
1336 z0mg(p) = 0.005_kind_lake !original 0.04, now for frozen lake without snow
1337 else ! for frozen lake with snow
1338 z0mg(p) = 0.0024_kind_lake
1339 end if
1340
1341 if(.false.) then
1342 ! This can't work since it uses ustar before ustar is initialized
1343 !- tgs - use COARE formulation for z0hg and z0qg.
1344 !-- suggestion from Ayumi Manome (GLERL), Aug. 2018
1345 !-- Charusombat et al., 2018, https://doi.org/10.5194/hess-2017-725
1346 tc=forc_t(g)-273.15_kind_lake
1347 visc=1.326e-5_kind_lake*(1._kind_lake + 6.542e-3_kind_lake*tc + 8.301e-6_kind_lake*tc*tc &
1348 - 4.84e-9_kind_lake*tc*tc*tc)
1349 visc=max(1e-7_kind_lake, visc)
1350
1351 ren = max(ustar(p)*z0mg(p)/visc, 0.1_kind_lake)
1352 z0hg(p) = (5.5e-5_kind_lake)*(ren**(-0.60_kind_lake))
1353
1354 z0hg(p) = min(z0hg(p),1.0e-4_kind_lake)
1355 z0hg(p) = max(z0hg(p),2.0e-9_kind_lake)
1356
1357 z0qg(p) = z0hg(p)
1358
1359 ! end COARE
1360 endif
1361 z0hg(p) = z0mg(p)
1362 z0qg(p) = z0mg(p)
1363
1364 ! Latent heat
1365
1366 if(pergro) then
1367 htvp(c) = hvap
1368 else
1369 if (t_grnd(c) > tfrz) then
1370 htvp(c) = hvap
1371 else
1372 htvp(c) = hsub
1373 end if
1374 endif
1375
1376 ! Zack Subin, 3/26/09: Shouldn't this be the ground temperature rather than the air temperature above?
1377 ! I'll change it for now.
1378
1379 ! Initialize stability variables
1380
1381 ur(p) = max(1.0_kind_lake,sqrt(forc_u(g)*forc_u(g)+forc_v(g)*forc_v(g)))
1382 dth(p) = thm(c)-t_grnd(c)
1383 dqh(p) = forc_q(g)-qsatg(c)
1384 dthv = dth(p)*(1._kind_lake+con_fvirt*forc_q(g))+con_fvirt*forc_th(g)*dqh(p)
1385 zldis(p) = forc_hgt_u(g) - 0._kind_lake
1386
1387 ! Initialize Monin-Obukhov length and wind speed
1388
1389 call moninobukini(ur(p), thv(c), dthv, zldis(p), z0mg(p), um(p), obu(p))
1390
1391 end do
1392
1393 iter = 1
1394 fncopy = num_shlakep
1395 fpcopy(1:num_shlakep) = filter_shlakep(1:num_shlakep)
1396
1397 ! Begin stability iteration
1398
1399 iteration : do while (iter <= niters .and. fncopy > 0)
1400
1401 ! Determine friction velocity, and potential temperature and humidity
1402 ! profiles of the surface boundary layer
1403
1404 call frictionvelocity(pgridcell,forc_hgt,forc_hgt_u, & !i
1405 forc_hgt_t,forc_hgt_q, & !i
1406 lbp, ubp, fncopy, fpcopy, & !i
1407 displa, z0mg, z0hg, z0qg, & !i
1408 obu, iter, ur, um, & !i
1409 ustar,temp1, temp2, temp12m, temp22m, & !o
1410 u10,fv, & !o
1411 fm) !i&o
1412
1413 !dir$ concurrent
1414 !cdir nodep
1415 do fp = 1, fncopy
1416 p = fpcopy(fp)
1417 c = pcolumn(p)
1418 g = pgridcell(p)
1419
1420 tgbef(c) = t_grnd(c)
1421 if (t_grnd(c) > tfrz .and. t_lake(c,1) > tfrz .and. snl(c) == 0) then
1422 tksur = savedtke1(c)
1423 ! Set this to the eddy conductivity from the last
1424 ! timestep, as the molecular conductivity will be orders of magnitude too small.
1425 ! Will have to deal with first timestep.
1426 tsur = t_lake(c,1)
1427 else if (snl(c) == 0) then !frozen but no snow layers
1428 tksur = tkice
1429 tsur = t_lake(c,1)
1430 else
1431 !Need to calculate thermal conductivity of the top snow layer
1432 bw = (h2osoi_ice(c,jtop(c))+h2osoi_liq(c,jtop(c)))/dz(c,jtop(c))
1433 tksur = tkairc + (7.75e-5_kind_lake *bw + 1.105e-6_kind_lake*bw*bw)*(tkice-tkairc)
1434 tsur = t_soisno(c,jtop(c))
1435 end if
1436
1437 ! Determine aerodynamic resistances
1438
1439 ram(p) = 1._kind_lake/(ustar(p)*ustar(p)/um(p))
1440 rah(p) = 1._kind_lake/(temp1(p)*ustar(p))
1441 raw(p) = 1._kind_lake/(temp2(p)*ustar(p))
1442 ram1(p) = ram(p) !pass value to global variable
1443
1444 ! Get derivative of fluxes with respect to ground temperature
1445
1446 stftg3(p) = emg*sb*tgbef(c)*tgbef(c)*tgbef(c)
1447
1448 ! Changed surface temperature from t_lake(c,1) to tsur.
1449 ! Also adjusted so that if there are snow layers present, all radiation is absorbed in the top layer.
1450 ax = betaprime(c)*sabg(p) + emg*forc_lwrad(g) + 3._kind_lake*stftg3(p)*tgbef(c) &
1451 + forc_rho(g)*cpair/rah(p)*thm(c) &
1452 - htvp(c)*forc_rho(g)/raw(p)*(qsatg(c)-qsatgdt(c)*tgbef(c) - forc_q(g)) &
1453 + tksur*tsur/dzsur(c)
1454 !Changed sabg(p) and to betaprime(c)*sabg(p).
1455 bx = 4._kind_lake*stftg3(p) + forc_rho(g)*cpair/rah(p) &
1456 + htvp(c)*forc_rho(g)/raw(p)*qsatgdt(c) + tksur/dzsur(c)
1457
1458 t_grnd(c) = ax/bx
1459
1460 ! Update htvp
1461 if(.not.pergro) then
1462 if (t_grnd(c) > tfrz) then
1463 htvp(c) = hvap
1464 else
1465 htvp(c) = hsub
1466 end if
1467 endif
1468
1469 ! Surface fluxes of momentum, sensible and latent heat
1470 ! using ground temperatures from previous time step
1471
1472 eflx_sh_grnd(p) = forc_rho(g)*cpair*(t_grnd(c)-thm(c))/rah(p)
1473 qflx_evap_soi(p) = forc_rho(g)*(qsatg(c)+qsatgdt(c)*(t_grnd(c)-tgbef(c))-forc_q(g))/raw(p)
1474
1475 ! Re-calculate saturated vapor pressure, specific humidity and their
1476 ! derivatives at lake surface
1477
1478 call qsat(t_grnd(c), forc_pbot(g), eg, degdt, qsatg(c), qsatgdt(c))
1479
1480 dth(p)=thm(c)-t_grnd(c)
1481 dqh(p)=forc_q(g)-qsatg(c)
1482
1483 tstar = temp1(p)*dth(p)
1484 qstar = temp2(p)*dqh(p)
1485
1486 thvstar=tstar*(1._kind_lake+con_fvirt*forc_q(g)) + con_fvirt*forc_th(g)*qstar
1487 zeta=zldis(p)*vkc * grav*thvstar/(ustar(p)**2*thv(c))
1488
1489 if (zeta >= 0._kind_lake) then !stable
1490 zeta = min(2._kind_lake,max(zeta,0.01_kind_lake))
1491 um(p) = max(ur(p),0.1_kind_lake)
1492 else !unstable
1493 zeta = max(-100._kind_lake,min(zeta,-0.01_kind_lake))
1494 wc = beta1*(-grav*ustar(p)*thvstar*zii/thv(c))**0.333_kind_lake
1495 um(p) = sqrt(ur(p)*ur(p)+wc*wc)
1496 end if
1497 obu(p) = zldis(p)/zeta
1498
1499 if (obuold(p)*obu(p) < 0._kind_lake) nmozsgn(p) = nmozsgn(p)+1
1500
1501 obuold(p) = obu(p)
1502
1503 end do ! end of filtered pft loop
1504
1505 iter = iter + 1
1506 if (iter <= niters ) then
1507 ! Rebuild copy of pft filter for next pass through the ITERATION loop
1508
1509 fnold = fncopy
1510 fncopy = 0
1511 do fp = 1, fnold
1512 p = fpcopy(fp)
1513 if (nmozsgn(p) < 3) then
1514 fncopy = fncopy + 1
1515 fpcopy(fncopy) = p
1516 end if
1517 end do ! end of filtered pft loop
1518 end if
1519
1520 end do iteration ! end of stability iteration
1521
1522 !dir$ concurrent
1523 !cdir nodep
1524 do fp = 1, num_shlakep
1525 p = filter_shlakep(fp)
1526 c = pcolumn(p)
1527 g = pgridcell(p)
1528
1529 ! If there is snow on the ground and t_grnd > tfrz: reset t_grnd = tfrz.
1530 ! Re-evaluate ground fluxes.
1531 ! h2osno > 0.5 prevents spurious fluxes.
1532 ! note that qsatg and qsatgdT should be f(tgbef) (PET: not sure what this
1533 ! comment means)
1534 ! Zack Subin, 3/27/09: Since they are now a function of whatever t_grnd was before cooling
1535 ! to freezing temperature, then this value should be used in the derivative correction term.
1536 ! Should this happen if the lake temperature is below freezing, too? I'll assume that for now.
1537 ! Also, allow convection if ground temp is colder than lake but warmer than 4C, or warmer than
1538 ! lake which is warmer than freezing but less than 4C.
1539 if ( (h2osno(c) > 0.5_kind_lake .or. t_lake(c,1) <= tfrz) .and. t_grnd(c) > tfrz) then
1540 t_grnd_temp = t_grnd(c)
1541 t_grnd(c) = tfrz
1542 eflx_sh_grnd(p) = forc_rho(g)*cpair*(t_grnd(c)-thm(c))/rah(p)
1543 qflx_evap_soi(p) = forc_rho(g)*(qsatg(c)+qsatgdt(c)*(t_grnd(c)-t_grnd_temp) - forc_q(g))/raw(p)
1544 else if ( (t_lake(c,1) > t_grnd(c) .and. t_grnd(c) > tdmax) .or. &
1545 (t_lake(c,1) < t_grnd(c) .and. t_lake(c,1) > tfrz .and. t_grnd(c) < tdmax) ) then
1546 ! Convective mixing will occur at surface
1547 t_grnd_temp = t_grnd(c)
1548 t_grnd(c) = t_lake(c,1)
1549 eflx_sh_grnd(p) = forc_rho(g)*cpair*(t_grnd(c)-thm(c))/rah(p)
1550 qflx_evap_soi(p) = forc_rho(g)*(qsatg(c)+qsatgdt(c)*(t_grnd(c)-t_grnd_temp) - forc_q(g))/raw(p)
1551 end if
1552
1553 ! Update htvp
1554 if(.not.pergro) then
1555 if (t_grnd(c) > tfrz) then
1556 htvp(c) = hvap
1557 else
1558 htvp(c) = hsub
1559 end if
1560 endif
1561
1562 ! Net longwave from ground to atmosphere
1563
1564 ! eflx_lwrad_out(p) = (1._kind_lake-emg)*forc_lwrad(g) + stftg3(p)*(-3._kind_lake*tgbef(c)+4._kind_lake*t_grnd(c))
1565 ! What is tgbef doing in this equation? Can't it be exact now? --Zack Subin, 4/14/09
1566 eflx_lwrad_out(p) = (1._kind_lake-emg)*forc_lwrad(g) + emg*sb*t_grnd(c)**4
1567
1568 ! Ground heat flux
1569
1570 eflx_soil_grnd(p) = sabg(p) + forc_lwrad(g) - eflx_lwrad_out(p) - &
1571 eflx_sh_grnd(p) - htvp(c)*qflx_evap_soi(p)
1572 !Why is this sabg(p) and not beta*sabg(p)??
1573 !I've kept this as the incorrect sabg so that the energy balance check will be correct.
1574 !This is the effective energy flux into the ground including the lake solar absorption
1575 !below the surface. The variable eflx_gnet will be used to pass the actual heat flux
1576 !from the ground interface into the lake.
1577
1578 taux(p) = -forc_rho(g)*forc_u(g)/ram(p)
1579 tauy(p) = -forc_rho(g)*forc_v(g)/ram(p)
1580
1581 eflx_sh_tot(p) = eflx_sh_grnd(p)
1582 qflx_evap_tot(p) = qflx_evap_soi(p)
1583 eflx_lh_tot(p) = htvp(c)*qflx_evap_soi(p)
1584 eflx_lh_grnd(p) = htvp(c)*qflx_evap_soi(p)
1585 if(debug_print) then
15861604 format('CLM_Lake ShalLakeFluxes: c=',i0,' sensible heat = ',f12.4,' latent heat =',f12.4, &
1587 ' ground temp = ', f12.4, ' h2osno = ', f12.4, ' at xlat_d=',f10.3,' xlon_d=',f10.3)
1588 print 1604, c, eflx_sh_tot(p), eflx_lh_tot(p), t_grnd(c), h2osno(c),xlat_d,xlon_d
1589 if (abs(eflx_sh_tot(p)) > 1500 .or. abs(eflx_lh_tot(p)) > 1500) then
15903018 format('CLM_Lake ShalLakeFluxes: WARNING: SH=',f12.4,' LH=',f12.4,' at xlat_d=',f10.3,' xlon_d=',f10.3)
1591 print 3018,eflx_sh_tot(p), eflx_lh_tot(p),xlat_d,xlon_d
1592 end if
1593 if (abs(eflx_sh_tot(p)) > 10000 .or. abs(eflx_lh_tot(p)) > 10000 &
1594 .or. abs(t_grnd(c)-288)>200 ) then
1595840 format('CLM_Lake ShalLakeFluxes: t_grnd is out of range: eflx_sh_tot(p)=',g20.12,' eflx_lh_tot(p)=',g20.12,' t_grnd(c)=',g20.12,' at p=',i0,' c=',i0,' xlat_d=',f10.3,' xlon_d=',f10.3)
1596 write(message,840) eflx_sh_tot(p),eflx_lh_tot(p),t_grnd(c),p,c,xlat_d,xlon_d
1597 ! errmsg=message
1598 ! errflg=1
1599 write(0,'(A)') trim(message)
1600 endif
1601 endif
1602 ! 2 m height air temperature
1603 t_ref2m(p) = thm(c) + temp1(p)*dth(p)*(1._kind_lake/temp12m(p) - 1._kind_lake/temp1(p))
1604
1605 ! 2 m height specific humidity
1606 q_ref2m(p) = forc_q(g) + temp2(p)*dqh(p)*(1._kind_lake/temp22m(p) - 1._kind_lake/temp2(p))
1607
1608 ! Energy residual used for melting snow
1609 ! Effectively moved to ShalLakeTemp
1610
1611 ! Prepare for lake layer temperature calculations below
1612 ! fin(c) = betaprime * sabg(p) + forc_lwrad(g) - (eflx_lwrad_out(p) + &
1613 ! eflx_sh_tot(p) + eflx_lh_tot(p))
1614 ! NOW this is just the net ground heat flux calculated below.
1615
1616 eflx_gnet(p) = betaprime(c) * sabg(p) + forc_lwrad(g) - (eflx_lwrad_out(p) + &
1617 eflx_sh_tot(p) + eflx_lh_tot(p))
1618 ! This is the actual heat flux from the ground interface into the lake, not including
1619 ! the light that penetrates the surface.
1620
1621 ! u2m = max(1.0_kind_lake,ustar(p)/vkc*log(2._kind_lake/z0mg(p)))
1622 ! u2 often goes below 1 m/s; it seems like the only reason for this minimum is to
1623 ! keep it from being zero in the ks equation below; 0.1 m/s is a better limit for
1624 ! stable conditions --ZS
1625 u2m = max(0.1_kind_lake,ustar(p)/vkc*log(2._kind_lake/z0mg(p)))
1626
1627 ws(c) = 1.2e-03_kind_lake * u2m
1628 ks(c) = 6.6_kind_lake*sqrt(abs(sin(lat(g))))*(u2m**(-1.84_kind_lake))
1629
1630 end do
1631
1632 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1633 ! End of surface flux relevant code in original BiogeophysicsLakeMod until history loop.
1634
1635 ! The following are needed for global average on history tape.
1636
1637 !dir$ concurrent
1638 !cdir nodep
1639 do fp = 1, num_shlakep
1640 p = filter_shlakep(fp)
1641 c = pcolumn(p)
1642 g = pgridcell(p)
1643 ! t_veg(p) = forc_t(g)
1644 !This is an odd choice, since elsewhere t_veg = t_grnd for bare ground.
1645 !Zack Subin, 4/09
1646 t_veg(p) = t_grnd(c)
1647 eflx_lwrad_net(p) = eflx_lwrad_out(p) - forc_lwrad(g)
1648 qflx_prec_grnd(p) = forc_rain(g) + forc_snow(g)
1649 end do
1650
1651 ustar_out(1) = ustar(1)
1652
1653
1654END SUBROUTINE shallakefluxes
1655
1656SUBROUTINE shallaketemperature(t_grnd,h2osno,sabg,dz,dz_lake,z,zi, & !i
1657 z_lake,ws,ks,snl,eflx_gnet,lakedepth, &
1658 lake_icefrac,snowdp, & !i&o
1659 eflx_sh_grnd,eflx_sh_tot,eflx_soil_grnd, & !o
1660 t_lake,t_soisno,h2osoi_liq, &
1661 h2osoi_ice,savedtke1, &
1662 watsat, tksatu, tkmg, tkdry, csol, dtime, &
1663 frac_iceold,qflx_snomelt,imelt,errmsg,errflg,xlat_d,xlon_d)
1664 !=======================================================================================================
1665 ! DESCRIPTION:
1666
1681 !
1682 ! Eddy + molecular diffusion:
1683 ! d ts d d ts 1 ds
1684 ! ---- = -- [(km + ke) ----] + -- --
1685 ! dt dz dz cw dz
1686 !
1687 ! where: ts = temperature (kelvin)
1688 ! t = time (s)
1689 ! z = depth (m)
1690 ! km = molecular diffusion coefficient (m**2/s)
1691 ! ke = eddy diffusion coefficient (m**2/s)
1692 ! cw = heat capacity (j/m**3/kelvin)
1693 ! s = heat source term (w/m**2)
1694 !
1695 ! Shallow lakes are allowed to have variable depth, set in _____.
1696 !
1697 ! For shallow lakes: ke > 0 if unfrozen,
1698 ! and convective mixing occurs WHETHER OR NOT frozen. (See e.g. Martynov...)
1699 !
1700 ! Use the Crank-Nicholson method to set up tridiagonal system of equations to
1701 ! solve for ts at time n+1, where the temperature equation for layer i is
1702 ! r_i = a_i [ts_i-1] n+1 + b_i [ts_i] n+1 + c_i [ts_i+1] n+1
1703 !
1704 ! The solution conserves energy as:
1705 !
1706 ! [For lake layers]
1707 ! cw*([ts( 1)] n+1 - [ts( 1)] n)*dz( 1)/dt + ... +
1708 ! cw*([ts(nlevlake)] n+1 - [ts(nlevlake)] n)*dz(nlevlake)/dt = fin
1709 ! But now there is phase change, so cv is not constant and there is
1710 ! latent heat.
1711 !
1712 ! where:
1713 ! [ts] n = old temperature (kelvin)
1714 ! [ts] n+1 = new temperature (kelvin)
1715 ! fin = heat flux into lake (w/m**2)
1716 ! = betaprime*sabg + forc_lwrad - eflx_lwrad_out - eflx_sh_tot - eflx_lh_tot
1717 ! (This is now the same as the ground heat flux.)
1718 ! + phi(1) + ... + phi(nlevlake) + phi(top soil level)
1719 ! betaprime = beta(islak) for no snow layers, and 1 for snow layers.
1720 ! This assumes all radiation is absorbed in the top snow layer and will need
1721 ! to be changed for CLM 4.
1722 !
1723 ! WARNING: This subroutine assumes lake columns have one and only one pft.
1724 !
1725 ! Outline:
1726 ! 1!) Initialization
1727 ! 2!) Lake density
1728 ! 3!) Diffusivity
1729 ! 4!) Heat source term from solar radiation penetrating lake
1730 ! 5!) Set thermal props and find initial energy content
1731 ! 6!) Set up vectors for tridiagonal matrix solution
1732 ! 7!) Solve tridiagonal and back-substitute
1733 ! 8!) (Optional) Do first energy check using temperature change at constant heat capacity.
1734 ! 9!) Phase change
1735 ! 9.5!) (Optional) Do second energy check using temperature change and latent heat, considering changed heat capacity.
1736 ! Also do soil water balance check.
1737 !10!) Convective mixing
1738 !11!) Do final energy check to detect small numerical errors (especially from convection)
1739 ! and dump small imbalance into sensible heat, or pass large errors to BalanceCheckMod for abort.
1740 !
1741 ! REVISION HISTORY:
1742 ! Created by Zack Subin, 2009.
1743 ! Reedited by Hongping Gu, 2010.
1744 ! Updated for CCPP by Sam Trahan, 2022.
1745 !=========================================================================================================
1746
1747
1748 implicit none
1749
1750 !in:
1751 real(kind_lake), intent(in) :: xlat_d
1752 real(kind_lake), intent(in) :: xlon_d
1753 integer, intent(inout) :: errflg
1754 real(kind_lake), intent(in) :: watsat(1,nlevsoil)
1755 real(kind_lake), intent(in) :: tksatu(1,nlevsoil)
1756 real(kind_lake), intent(in) :: tkmg(1,nlevsoil)
1757 real(kind_lake), intent(in) :: tkdry(1,nlevsoil)
1758 real(kind_lake), intent(in) :: csol(1,nlevsoil)
1759 character(*), intent(inout) :: errmsg
1760 real(kind_lake), intent(in) :: t_grnd(1)
1761 real(kind_lake), intent(inout) :: h2osno(1)
1762 real(kind_lake), intent(in) :: sabg(1)
1763 real(kind_lake), intent(in) :: dz(1,-nlevsnow + 1:nlevsoil)
1764 real(kind_lake), intent(in) :: dz_lake(1,nlevlake)
1765 real(kind_lake), intent(in) :: z(1,-nlevsnow+1:nlevsoil)
1766 real(kind_lake), intent(in) :: zi(1,-nlevsnow+0:nlevsoil)
1768 real(kind_lake), intent(in) :: z_lake(1,nlevlake)
1769 real(kind_lake), intent(in) :: ws(1)
1770 real(kind_lake), intent(in) :: ks(1)
1772 integer , intent(in) :: snl(1)
1773 real(kind_lake), intent(inout) :: eflx_gnet(1)
1774 real(kind_lake), intent(in) :: lakedepth(1)
1775
1776 ! real(kind_lake), intent(in) :: watsat(1,nlevsoil) ! volumetric soil water at saturation (porosity)
1777 real(kind_lake), intent(inout) :: snowdp(1)
1778 real(kind_lake), intent(in) :: dtime
1779 !out:
1780
1781 real(kind_lake), intent(out) :: eflx_sh_grnd(1)
1782 real(kind_lake), intent(out) :: eflx_sh_tot(1)
1783 real(kind_lake), intent(out) :: eflx_soil_grnd(1)
1785 !real(kind_lake), intent(out) :: qmelt(1) !< snow melt [mm/s] [temporary]
1786
1787 real(kind_lake), intent(inout) :: t_lake(1,nlevlake)
1788 real(kind_lake), intent(inout) :: t_soisno(1,-nlevsnow+1:nlevsoil)
1789 real(kind_lake), intent(inout) :: h2osoi_liq(1,-nlevsnow+1:nlevsoil)
1790 real(kind_lake), intent(inout) :: h2osoi_ice(1,-nlevsnow+1:nlevsoil)
1791 real(kind_lake), intent(inout) :: lake_icefrac(1,nlevlake)
1792 real(kind_lake), intent(out) :: savedtke1(1)
1793 real(kind_lake), intent(out) :: frac_iceold(1,-nlevsnow+1:nlevsoil)
1794 real(kind_lake), intent(out) :: qflx_snomelt(1)
1795 integer, intent(out) :: imelt(1,-nlevsnow+1:nlevsoil)
1796
1797
1798 ! OTHER LOCAL VARIABLES:
1799
1800 integer , parameter :: islak = 2 ! index of lake, 1 = deep lake, 2 = shallow lake
1801 real(kind_lake), parameter :: p0 = 1._kind_lake ! neutral value of turbulent prandtl number
1802 integer :: i,j,fc,fp,g,c,p ! do loop or array index
1803 real(kind_lake) :: eta(2) ! light extinction coefficient (/m): depends on lake type
1804 real(kind_lake) :: cwat ! specific heat capacity of water (j/m**3/kelvin)
1805 real(kind_lake) :: cice_eff ! effective heat capacity of ice (using density of
1806 ! water because layer depth is not adjusted when freezing
1807 real(kind_lake) :: cfus ! effective heat of fusion per unit volume
1808 ! using water density as above
1809 real(kind_lake) :: km ! molecular diffusion coefficient (m**2/s)
1810 real(kind_lake) :: tkice_eff ! effective conductivity since layer depth is constant
1811 real(kind_lake) :: a(lbc:ubc,-nlevsnow+1:nlevlake+nlevsoil) ! "a" vector for tridiagonal matrix
1812 real(kind_lake) :: b(lbc:ubc,-nlevsnow+1:nlevlake+nlevsoil) ! "b" vector for tridiagonal matrix
1813 real(kind_lake) :: c1(lbc:ubc,-nlevsnow+1:nlevlake+nlevsoil) ! "c" vector for tridiagonal matrix
1814 real(kind_lake) :: r(lbc:ubc,-nlevsnow+1:nlevlake+nlevsoil) ! "r" vector for tridiagonal solution
1815 real(kind_lake) :: rhow(lbc:ubc,nlevlake) ! density of water (kg/m**3)
1816 real(kind_lake) :: phi(lbc:ubc,nlevlake) ! solar radiation absorbed by layer (w/m**2)
1817 real(kind_lake) :: kme(lbc:ubc,nlevlake) ! molecular + eddy diffusion coefficient (m**2/s)
1818 real(kind_lake) :: rsfin ! relative flux of solar radiation into layer
1819 real(kind_lake) :: rsfout ! relative flux of solar radiation out of layer
1820 real(kind_lake) :: phi_soil(lbc:ubc) ! solar radiation into top soil layer (W/m**2)
1821 real(kind_lake) :: ri ! richardson number
1822 real(kind_lake) :: fin(lbc:ubc) ! net heat flux into lake at ground interface (w/m**2)
1823 real(kind_lake) :: ocvts(lbc:ubc) ! (cwat*(t_lake[n ])*dz
1824 real(kind_lake) :: ncvts(lbc:ubc) ! (cwat*(t_lake[n+1])*dz
1825 real(kind_lake) :: ke ! eddy diffusion coefficient (m**2/s)
1826 real(kind_lake) :: zin ! depth at top of layer (m)
1827 real(kind_lake) :: zout ! depth at bottom of layer (m)
1828 real(kind_lake) :: drhodz ! d [rhow] /dz (kg/m**4)
1829 real(kind_lake) :: n2 ! brunt-vaisala frequency (/s**2)
1830 real(kind_lake) :: num ! used in calculating ri
1831 real(kind_lake) :: den ! used in calculating ri
1832 real(kind_lake) :: tav_froz(lbc:ubc) ! used in aver temp for convectively mixed layers (C)
1833 real(kind_lake) :: tav_unfr(lbc:ubc) ! "
1834 real(kind_lake) :: nav(lbc:ubc) ! used in aver temp for convectively mixed layers
1835 real(kind_lake) :: phidum ! temporary value of phi
1836 real(kind_lake) :: iceav(lbc:ubc) ! used in calc aver ice for convectively mixed layers
1837 real(kind_lake) :: qav(lbc:ubc) ! used in calc aver heat content for conv. mixed layers
1838 integer :: jtop(lbc:ubc) ! top level for each column (no longer all 1)
1839 real(kind_lake) :: cv (lbc:ubc,-nlevsnow+1:nlevsoil) !heat capacity of soil/snow [J/(m2 K)]
1840 real(kind_lake) :: tk (lbc:ubc,-nlevsnow+1:nlevsoil) !thermal conductivity of soil/snow [W/(m K)]
1841 !(at interface below, except for j=0)
1842 real(kind_lake) :: cv_lake (lbc:ubc,1:nlevlake) !heat capacity [J/(m2 K)]
1843 real(kind_lake) :: tk_lake (lbc:ubc,1:nlevlake) !thermal conductivity at layer node [W/(m K)]
1844 real(kind_lake) :: cvx (lbc:ubc,-nlevsnow+1:nlevlake+nlevsoil) !heat capacity for whole column [J/(m2 K)]
1845 real(kind_lake) :: tkix(lbc:ubc,-nlevsnow+1:nlevlake+nlevsoil) !thermal conductivity at layer interfaces
1846 !for whole column [W/(m K)]
1847 real(kind_lake) :: tx(lbc:ubc,-nlevsnow+1:nlevlake+nlevsoil) ! temperature of whole column [K]
1848 real(kind_lake) :: tktopsoillay(lbc:ubc) ! thermal conductivity [W/(m K)]
1849 real(kind_lake) :: fnx(lbc:ubc,-nlevsnow+1:nlevlake+nlevsoil) !heat diffusion through the layer interface below [W/m2]
1850 real(kind_lake) :: phix(lbc:ubc,-nlevsnow+1:nlevlake+nlevsoil) !solar source term for whole column [W/m**2]
1851 real(kind_lake) :: zx(lbc:ubc,-nlevsnow+1:nlevlake+nlevsoil) !interface depth (+ below surface) for whole column [m]
1852 real(kind_lake) :: dzm !used in computing tridiagonal matrix [m]
1853 real(kind_lake) :: dzp !used in computing tridiagonal matrix [m]
1854 integer :: jprime ! j - nlevlake
1855 real(kind_lake) :: factx(lbc:ubc,-nlevsnow+1:nlevlake+nlevsoil) !coefficient used in computing tridiagonal matrix
1856 real(kind_lake) :: t_lake_bef(lbc:ubc,1:nlevlake) !beginning lake temp for energy conservation check [K]
1857 real(kind_lake) :: t_soisno_bef(lbc:ubc,-nlevsnow+1:nlevsoil) !beginning soil temp for E cons. check [K]
1858 real(kind_lake) :: lhabs(lbc:ubc) ! total per-column latent heat abs. from phase change (J/m^2)
1859 real(kind_lake) :: esum1(lbc:ubc) ! temp for checking energy (J/m^2)
1860 real(kind_lake) :: esum2(lbc:ubc) ! ""
1861 real(kind_lake) :: zsum(lbc:ubc) ! temp for putting ice at the top during convection (m)
1862 real(kind_lake) :: wsum(lbc:ubc) ! temp for checking water (kg/m^2)
1863 real(kind_lake) :: wsum_end(lbc:ubc) ! temp for checking water (kg/m^2)
1864 real(kind_lake) :: errsoi(1) ! soil/lake energy conservation error (W/m**2)
1865 real(kind_lake) :: eflx_snomelt(1) !snow melt heat flux (W/m**2)
1866 CHARACTER*256 :: message
1867 !
1868 ! Constants for lake temperature model
1869 !
1870 real(kind_lake), parameter :: beta(2) = & ! fraction solar rad absorbed at surface: depends on lake type
1871 (/0.4_kind_lake, 0.4_kind_lake/) ! (deep lake, shallow lake)
1872 real(kind_lake), parameter :: za(2) = & ! base of surface absorption layer (m): depends on lake type
1873 (/0.6_kind_lake, 0.6_kind_lake/)
1874 ! For now, keep beta and za for shallow lake the same as deep lake, until better data is found.
1875 ! It looks like eta is key and that larger values give better results for shallow lakes. Use
1876 ! empirical expression from Hakanson (below). This is still a very unconstrained parameter
1877 ! that deserves more attention.
1878 ! Some radiation will be allowed to reach the soil.
1879 !-----------------------------------------------------------------------
1880
1881
1882 ! 1!) Initialization
1883 ! Determine step size
1884
1885 ! Initialize constants
1886 cwat = cpliq*denh2o ! water heat capacity per unit volume
1887 cice_eff = cpice*denh2o !use water density because layer depth is not adjusted
1888 !for freezing
1889 cfus = hfus*denh2o ! latent heat per unit volume
1890 tkice_eff = tkice * denice/denh2o !effective conductivity since layer depth is constant
1891 km = tkwat/cwat ! a constant (molecular diffusivity)
1892
1893 ! Begin calculations
1894
1895 !dir$ concurrent
1896 !cdir nodep
1897 do fc = 1, num_shlakec
1898 c = filter_shlakec(fc)
1899
1900 ! Initialize Ebal quantities computed below
1901
1902 ocvts(c) = 0._kind_lake
1903 ncvts(c) = 0._kind_lake
1904 esum1(c) = 0._kind_lake
1905 esum2(c) = 0._kind_lake
1906
1907 end do
1908
1909 ! Initialize set of previous time-step variables as in DriverInit,
1910 ! which is currently not called over lakes. This has to be done
1911 ! here because phase change will occur in this routine.
1912 ! Ice fraction of snow at previous time step
1913
1914 do j = -nlevsnow+1,0
1915 !dir$ concurrent
1916 !cdir nodep
1917 do fc = 1, num_shlakec
1918 c = filter_shlakec(fc)
1919 if (j >= snl(c) + 1) then
1920 frac_iceold(c,j) = h2osoi_ice(c,j)/(h2osoi_liq(c,j)+h2osoi_ice(c,j))
1921 end if
1922 end do
1923 end do
1924
1925 ! Sum soil water.
1926 do j = 1, nlevsoil
1927 !dir$ concurrent
1928 !cdir nodep
1929 do fc = 1, num_shlakec
1930 c = filter_shlakec(fc)
1931 if (j == 1) wsum(c) = 0._kind_lake
1932 wsum(c) = wsum(c) + h2osoi_ice(c,j) + h2osoi_liq(c,j)
1933 end do
1934 end do
1935
1936 !dir$ concurrent
1937 !cdir nodep
1938 do fp = 1, num_shlakep
1939 p = filter_shlakep(fp)
1940 c = pcolumn(p)
1941
1942
1943 ! Prepare for lake layer temperature calculations below
1944
1945 ! fin(c) = betaprime * sabg(p) + forc_lwrad(g) - (eflx_lwrad_out(p) + &
1946 ! eflx_sh_tot(p) + eflx_lh_tot(p))
1947 ! fin(c) now passed from ShalLakeFluxes as eflx_gnet
1948 fin(c) = eflx_gnet(p)
1949
1950 end do
1951
1952 ! 2!) Lake density
1953
1954 do j = 1, nlevlake
1955 !dir$ concurrent
1956 !cdir nodep
1957 do fc = 1, num_shlakec
1958 c = filter_shlakec(fc)
1959 rhow(c,j) = (1._kind_lake - lake_icefrac(c,j)) * &
1960 1000._kind_lake*( 1.0_kind_lake - 1.9549e-05_kind_lake*(abs(t_lake(c,j)-277._kind_lake))**1.68_kind_lake ) &
1961 + lake_icefrac(c,j)*denice
1962 ! Allow for ice fraction; assume constant ice density.
1963 ! Is this the right weighted average?
1964 ! Using this average will make sure that surface ice is treated properly during
1965 ! convective mixing.
1966 end do
1967 end do
1968
1969 ! 3!) Diffusivity and implied thermal "conductivity" = diffusivity * cwat
1970 do j = 1, nlevlake-1
1971 !dir$ prefervector
1972 !dir$ concurrent
1973 !cdir nodep
1974 do fc = 1, num_shlakec
1975 c = filter_shlakec(fc)
1976 drhodz = (rhow(c,j+1)-rhow(c,j)) / (z_lake(c,j+1)-z_lake(c,j))
1977 n2 = grav / rhow(c,j) * drhodz
1978 ! Fixed sign error here: our z goes up going down into the lake, so no negative
1979 ! sign is needed to make this positive unlike in Hostetler. --ZS
1980 num = 40._kind_lake * n2 * (vkc*z_lake(c,j))**2
1981 den = max( (ws(c)**2) * exp(-2._kind_lake*ks(c)*z_lake(c,j)), 1.e-10_kind_lake )
1982 ri = ( -1._kind_lake + sqrt( max(1._kind_lake+num/den, 0._kind_lake) ) ) / 20._kind_lake
1983 if (t_grnd(c) > tfrz .and. t_lake(c,1) > tfrz .and. snl(c) == 0) then
1984 ! ke = vkc*ws(c)*z_lake(c,j)/p0 * exp(-ks(c)*z_lake(c,j)) / (1._kind_lake+37._kind_lake*ri*ri)
1985
1986 if( t_lake(c,1) > 277.15_kind_lake ) then
1987 if (lakedepth(c) > 15.0 ) then
1988 ke = 1.e+2_kind_lake*vkc*ws(c)*z_lake(c,j)/p0 * exp(-ks(c)*z_lake(c,j)) / (1._kind_lake+37._kind_lake*ri*ri)
1989 else
1990 ke = vkc*ws(c)*z_lake(c,j)/p0 * exp(-ks(c)*z_lake(c,j)) / (1._kind_lake+37._kind_lake*ri*ri)
1991 endif
1992 else
1993 if (lakedepth(c) > 15.0 ) then
1994 if (lakedepth(c) > 150.0 ) then
1995 ke = 1.e+5_kind_lake*vkc*ws(c)*z_lake(c,j)/p0 * exp(-ks(c)*z_lake(c,j)) / (1._kind_lake+37._kind_lake*ri*ri)
1996 else
1997 ke =1.e+4_kind_lake*vkc*ws(c)*z_lake(c,j)/p0 * exp(-ks(c)*z_lake(c,j)) / (1._kind_lake+37._kind_lake*ri*ri)
1998 end if
1999 else
2000 ke = vkc*ws(c)*z_lake(c,j)/p0 * exp(-ks(c)*z_lake(c,j)) / (1._kind_lake+37._kind_lake*ri*ri)
2001 endif
2002 end if
2003
2004 kme(c,j) = km + ke
2005 tk_lake(c,j) = kme(c,j)*cwat
2006 ! If there is some ice in this layer (this should rarely happen because the surface
2007 ! is unfrozen and it will be unstable), still use the cwat to get out the tk b/c the eddy
2008 ! diffusivity equation assumes water.
2009 else
2010 kme(c,j) = km
2011 tk_lake(c,j) = tkwat*tkice_eff / ( (1._kind_lake-lake_icefrac(c,j))*tkice_eff &
2012 + tkwat*lake_icefrac(c,j) )
2013 ! Assume the resistances add as for the calculation of conductivities at layer interfaces.
2014 end if
2015 end do
2016 end do
2017
2018 !dir$ concurrent
2019 !cdir nodep
2020 do fc = 1, num_shlakec
2021 c = filter_shlakec(fc)
2022
2023 j = nlevlake
2024 kme(c,nlevlake) = kme(c,nlevlake-1)
2025
2026 if (t_grnd(c) > tfrz .and. t_lake(c,1) > tfrz .and. snl(c) == 0) then
2027 tk_lake(c,j) = tk_lake(c,j-1)
2028 else
2029 tk_lake(c,j) = tkwat*tkice_eff / ( (1._kind_lake-lake_icefrac(c,j))*tkice_eff &
2030 + tkwat*lake_icefrac(c,j) )
2031 end if
2032
2033 ! Use in surface flux calculation for next timestep.
2034 savedtke1(c) = kme(c,1)*cwat ! Will only be used if unfrozen
2035 ! set number of column levels for use by Tridiagonal below
2036 jtop(c) = snl(c) + 1
2037 end do
2038
2039 ! 4!) Heat source term: unfrozen lakes only
2040 do j = 1, nlevlake
2041 !dir$ concurrent
2042 !cdir nodep
2043 do fp = 1, num_shlakep
2044 p = filter_shlakep(fp)
2045 c = pcolumn(p)
2046
2047 ! Set eta(:), the extinction coefficient, according to L Hakanson, Aquatic Sciences, 1995
2048 ! (regression of Secchi Depth with lake depth for small glacial basin lakes), and the
2049 ! Poole & Atkins expression for extinction coeffient of 1.7 / Secchi Depth (m).
2050 if(.not.use_etalake) then
2051 eta(:) = 1.1925_kind_lake*lakedepth(c)**(-0.424)
2052 else
2053 eta(:) = etalake
2054 endif
2055
2056 zin = z_lake(c,j) - 0.5_kind_lake*dz_lake(c,j)
2057 zout = z_lake(c,j) + 0.5_kind_lake*dz_lake(c,j)
2058 rsfin = exp( -eta(islak)*max( zin-za(islak),0._kind_lake ) )
2059 rsfout = exp( -eta(islak)*max( zout-za(islak),0._kind_lake ) )
2060
2061 ! Let rsfout for bottom layer go into soil.
2062 ! This looks like it should be robust even for pathological cases,
2063 ! like lakes thinner than za.
2064 if (t_grnd(c) > tfrz .and. t_lake(c,1) > tfrz .and. snl(c) == 0) then
2065 phidum = (rsfin-rsfout) * sabg(p) * (1._kind_lake-beta(islak))
2066 if (j == nlevlake) then
2067 phi_soil(c) = rsfout * sabg(p) * (1._kind_lake-beta(islak))
2068 end if
2069 else if (j == 1 .and. snl(c) == 0) then !if frozen but no snow layers
2070 phidum = sabg(p) * (1._kind_lake-beta(islak))
2071 else !radiation absorbed at surface
2072 phidum = 0._kind_lake
2073 if (j == nlevlake) phi_soil(c) = 0._kind_lake
2074 end if
2075 phi(c,j) = phidum
2076
2077 end do
2078 end do
2079
2080 ! 5!) Set thermal properties and check initial energy content.
2081
2082 ! For lake
2083 do j = 1, nlevlake
2084 !dir$ concurrent
2085 !cdir nodep
2086 do fc = 1, num_shlakec
2087 c = filter_shlakec(fc)
2088
2089 cv_lake(c,j) = dz_lake(c,j) * (cwat*(1._kind_lake-lake_icefrac(c,j)) + cice_eff*lake_icefrac(c,j))
2090 end do
2091 end do
2092
2093 ! For snow / soil
2094 call soilthermprop_lake (snl,dz,zi,z,t_soisno,h2osoi_liq,h2osoi_ice, &
2095 watsat, tksatu, tkmg, tkdry, csol, tk, cv, tktopsoillay,errmsg,errflg)
2096 if(errflg/=0) then
2097 ! State is no longer valid, so return error to caller
2098 ! FIXME: PUT THIS BACK return
2099 endif
2100
2101 ! Sum cv*t_lake for energy check
2102 ! Include latent heat term, and correction for changing heat capacity with phase change.
2103
2104 ! This will need to be over all soil / lake / snow layers. Lake is below.
2105 do j = 1, nlevlake
2106 !dir$ concurrent
2107 !cdir nodep
2108 do fc = 1, num_shlakec
2109 c = filter_shlakec(fc)
2110
2111 ! ocvts(c) = ocvts(c) + cv_lake(c,j)*t_lake(c,j) &
2112 ocvts(c) = ocvts(c) + cv_lake(c,j)*(t_lake(c,j)-tfrz) &
2113 + cfus*dz_lake(c,j)*(1._kind_lake-lake_icefrac(c,j)) !&
2114 ! + (cwat-cice_eff)*lake_icefrac(c)*tfrz*dz_lake(c,j) !enthalpy reconciliation term
2115 t_lake_bef(c,j) = t_lake(c,j)
2116 if(debug_print) then
2117 if (abs(xlat_d-52.1152).lt.0.1 .and. &
2118 abs(xlon_d-260.405).lt.0.1)then
2119 print *,' ocvts(c) at xlat_d,xlon_d',xlat_d,xlon_d
2120 print *,'j,dz_lake(c,j) ', j,dz_lake(c,j)
2121 print*,'cv_lake(c,j),lake_icefrac(c,j),t_lake(c,j),cfus,ocvts(c)', &
2122 cv_lake(c,j),lake_icefrac(c,j),t_lake(c,j),cfus,ocvts(c)
2123 endif
2124 endif
2125 end do
2126 end do
2127
2128 ! Now do for soil / snow layers
2129 do j = -nlevsnow + 1, nlevsoil
2130 !dir$ concurrent
2131 !cdir nodep
2132 do fc = 1, num_shlakec
2133 c = filter_shlakec(fc)
2134
2135 if (j >= jtop(c)) then
2136 ! ocvts(c) = ocvts(c) + cv(c,j)*t_soisno(c,j) &
2137 ocvts(c) = ocvts(c) + cv(c,j)*(t_soisno(c,j)-tfrz) &
2138 + hfus*h2osoi_liq(c,j) !&
2139 ! + (cpliq-cpice)*h2osoi_ice(c,j)*tfrz !enthalpy reconciliation term
2140 if(debug_print) then
2141 if (abs(xlat_d-52.1152).lt.0.1 .and. &
2142 abs(xlon_d-260.405).lt.0.1)then
2143 print *,' ocvts(c) at xlat_d,xlon_d',xlat_d,xlon_d
2144 print *,' j,jtop(c)',j,jtop(c),'h2osoi_liq(c,j) ',h2osoi_liq(c,j),'h2osoi_ice(c,j)',h2osoi_ice(c,j)
2145 print *,' cv(c,j),t_soisno(c,j),hfus,ocvts(c)',c,j,cv(c,j),t_soisno(c,j),hfus,ocvts(c)
2146 print *,' h2osno(c)',h2osno(c)
2147 endif
2148 endif
2149 if (j == 1 .and. h2osno(c) > 0._kind_lake .and. j == jtop(c)) then
2150 ocvts(c) = ocvts(c) - h2osno(c)*hfus
2151 end if
2152 t_soisno_bef(c,j) = t_soisno(c,j)
2153 if(abs(t_soisno(c,j)-288) > 150) then
215448 format('WARNING: At c=',i0,' level=',i0,' extreme t_soisno = ',f15.10)
2155 WRITE(message,48) c,j,t_soisno(c,j)
2156 ! errmsg=trim(message)
2157 ! errflg=1
2158 write(0,'(A)') trim(message)
2159 endif
2160 end if
2161 end do
2162 end do
2163
2164 !!!!!!!!!!!!!!!!!!!
2165 ! 6!) Set up vector r and vectors a, b, c1 that define tridiagonal matrix
2166
2167 ! Heat capacity and resistance of snow without snow layers (<1cm) is ignored during diffusion,
2168 ! but its capacity to absorb latent heat may be used during phase change.
2169
2170 ! Set up interface depths, zx, heat capacities, cvx, solar source terms, phix, and temperatures, tx.
2171 do j = -nlevsnow+1, nlevlake+nlevsoil
2172 !dir$ prefervector
2173 !dir$ concurrent
2174 !cdir nodep
2175 do fc = 1,num_shlakec
2176 c = filter_shlakec(fc)
2177
2178 jprime = j - nlevlake
2179
2180 if (j >= jtop(c)) then
2181 if (j < 1) then !snow layer
2182 zx(c,j) = z(c,j)
2183 cvx(c,j) = cv(c,j)
2184 phix(c,j) = 0._kind_lake
2185 tx(c,j) = t_soisno(c,j)
2186 else if (j <= nlevlake) then !lake layer
2187 zx(c,j) = z_lake(c,j)
2188 cvx(c,j) = cv_lake(c,j)
2189 phix(c,j) = phi(c,j)
2190 tx(c,j) = t_lake(c,j)
2191 else !soil layer
2192 zx(c,j) = zx(c,nlevlake) + dz_lake(c,nlevlake)*0.5_kind_lake + z(c,jprime)
2193 cvx(c,j) = cv(c,jprime)
2194 if (j == nlevlake + 1) then !top soil layer
2195 phix(c,j) = phi_soil(c)
2196 else !middle or bottom soil layer
2197 phix(c,j) = 0._kind_lake
2198 end if
2199 tx(c,j) = t_soisno(c,jprime)
2200 end if
2201 end if
2202
2203 end do
2204 end do
2205
2206 ! Determine interface thermal conductivities, tkix
2207
2208 do j = -nlevsnow+1, nlevlake+nlevsoil
2209 !dir$ prefervector
2210 !dir$ concurrent
2211 !cdir nodep
2212 do fc = 1,num_shlakec
2213 c = filter_shlakec(fc)
2214
2215 jprime = j - nlevlake
2216
2217 if (j >= jtop(c)) then
2218 if (j < 0) then !non-bottom snow layer
2219 tkix(c,j) = tk(c,j)
2220 else if (j == 0) then !bottom snow layer
2221 dzp = zx(c,j+1) - zx(c,j)
2222 tkix(c,j) = tk_lake(c,1)*tk(c,j)*dzp / &
2223 (tk(c,j)*z_lake(c,1) + tk_lake(c,1)*(-z(c,j)) )
2224 ! tk(c,0) is the conductivity at the middle of that layer, as defined in SoilThermProp_Lake
2225 else if (j < nlevlake) then !non-bottom lake layer
2226 tkix(c,j) = ( tk_lake(c,j)*tk_lake(c,j+1) * (dz_lake(c,j+1)+dz_lake(c,j)) ) &
2227 / ( tk_lake(c,j)*dz_lake(c,j+1) + tk_lake(c,j+1)*dz_lake(c,j) )
2228 else if (j == nlevlake) then !bottom lake layer
2229 dzp = zx(c,j+1) - zx(c,j)
2230 tkix(c,j) = (tktopsoillay(c)*tk_lake(c,j)*dzp / &
2231 (tktopsoillay(c)*dz_lake(c,j)*0.5_kind_lake + tk_lake(c,j)*z(c,1) ) )
2232 ! tktopsoillay is the conductivity at the middle of that layer, as defined in SoilThermProp_Lake
2233 else !soil layer
2234 tkix(c,j) = tk(c,jprime)
2235 end if
2236 end if
2237
2238 end do
2239 end do
2240
2241
2242 ! Determine heat diffusion through the layer interface and factor used in computing
2243 ! tridiagonal matrix and set up vector r and vectors a, b, c1 that define tridiagonal
2244 ! matrix and solve system
2245
2246 do j = -nlevsnow+1, nlevlake+nlevsoil
2247 !dir$ prefervector
2248 !dir$ concurrent
2249 !cdir nodep
2250 do fc = 1,num_shlakec
2251 c = filter_shlakec(fc)
2252 if (j >= jtop(c)) then
2253 if (j < nlevlake+nlevsoil) then !top or interior layer
2254 factx(c,j) = dtime/cvx(c,j)
2255 fnx(c,j) = tkix(c,j)*(tx(c,j+1)-tx(c,j))/(zx(c,j+1)-zx(c,j))
2256 else !bottom soil layer
2257 factx(c,j) = dtime/cvx(c,j)
2258 fnx(c,j) = 0._kind_lake !not used
2259 end if
2260 end if
2261 enddo
2262 end do
2263
2264 do j = -nlevsnow+1,nlevlake+nlevsoil
2265 !dir$ prefervector
2266 !dir$ concurrent
2267 !cdir nodep
2268 do fc = 1,num_shlakec
2269 c = filter_shlakec(fc)
2270 if (j >= jtop(c)) then
2271 if (j == jtop(c)) then !top layer
2272 dzp = zx(c,j+1)-zx(c,j)
2273 a(c,j) = 0._kind_lake
2274 b(c,j) = 1+(1._kind_lake-cnfac)*factx(c,j)*tkix(c,j)/dzp
2275 c1(c,j) = -(1._kind_lake-cnfac)*factx(c,j)*tkix(c,j)/dzp
2276 r(c,j) = tx(c,j) + factx(c,j)*( fin(c) + phix(c,j) + cnfac*fnx(c,j) )
2277 else if (j < nlevlake+nlevsoil) then !middle layer
2278 dzm = (zx(c,j)-zx(c,j-1))
2279 dzp = (zx(c,j+1)-zx(c,j))
2280 a(c,j) = - (1._kind_lake-cnfac)*factx(c,j)* tkix(c,j-1)/dzm
2281 b(c,j) = 1._kind_lake+ (1._kind_lake-cnfac)*factx(c,j)*(tkix(c,j)/dzp + tkix(c,j-1)/dzm)
2282 c1(c,j) = - (1._kind_lake-cnfac)*factx(c,j)* tkix(c,j)/dzp
2283 r(c,j) = tx(c,j) + cnfac*factx(c,j)*( fnx(c,j) - fnx(c,j-1) ) + factx(c,j)*phix(c,j)
2284 else !bottom soil layer
2285 dzm = (zx(c,j)-zx(c,j-1))
2286 a(c,j) = - (1._kind_lake-cnfac)*factx(c,j)*tkix(c,j-1)/dzm
2287 b(c,j) = 1._kind_lake+ (1._kind_lake-cnfac)*factx(c,j)*tkix(c,j-1)/dzm
2288 c1(c,j) = 0._kind_lake
2289 r(c,j) = tx(c,j) - cnfac*factx(c,j)*fnx(c,j-1)
2290 end if
2291 end if
2292 enddo
2293 end do
2294 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2295
2296
2297 ! 7!) Solve for tdsolution
2298
2299 call tridiagonal(lbc, ubc, -nlevsnow + 1, nlevlake + nlevsoil, jtop, num_shlakec, filter_shlakec, &
2300 a, b, c1, r, tx)
2301
2302 ! Set t_soisno and t_lake
2303 do j = -nlevsnow+1, nlevlake + nlevsoil
2304 !dir$ concurrent
2305 !cdir nodep
2306 do fc = 1, num_shlakec
2307 c = filter_shlakec(fc)
2308
2309 jprime = j - nlevlake
2310
2311 ! Don't do anything with invalid snow layers.
2312 if (j >= jtop(c)) then
2313 if (j < 1) then !snow layer
2314 t_soisno(c,j) = tx(c,j)
2315 else if (j <= nlevlake) then !lake layer
2316 t_lake(c,j) = tx(c,j)
2317 else !soil layer
2318 t_soisno(c,jprime) = tx(c,j)
2319 end if
2320 end if
2321 end do
2322 end do
2323
2324 !!!!!!!!!!!!!!!!!!!!!!!
2325
2326 ! 8!) Sum energy content and total energy into lake for energy check. Any errors will be from the
2327 ! Tridiagonal solution.
2328
2329 if_debug_energy: if (lakedebug) then
2330 do j = 1, nlevlake
2331 !dir$ concurrent
2332 !cdir nodep
2333 do fc = 1, num_shlakec
2334 c = filter_shlakec(fc)
2335
2336 esum1(c) = esum1(c) + (t_lake(c,j)-t_lake_bef(c,j))*cv_lake(c,j)
2337 esum2(c) = esum2(c) + (t_lake(c,j)-tfrz)*cv_lake(c,j)
2338 end do
2339 end do
2340
2341 do j = -nlevsnow+1, nlevsoil
2342 !dir$ concurrent
2343 !cdir nodep
2344 do fc = 1, num_shlakec
2345 c = filter_shlakec(fc)
2346
2347 if (j >= jtop(c)) then
2348 esum1(c) = esum1(c) + (t_soisno(c,j)-t_soisno_bef(c,j))*cv(c,j)
2349 esum2(c) = esum2(c) + (t_soisno(c,j)-tfrz)*cv(c,j)
2350 end if
2351 end do
2352 end do
2353
2354 !dir$ concurrent
2355 !cdir nodep
2356 do fp = 1, num_shlakep
2357 p = filter_shlakep(fp)
2358 c = pcolumn(p)
2359 ! Again assuming only one pft per column
2360 ! esum1(c) = esum1(c) + lhabs(c)
2361 errsoi(c) = esum1(c)/dtime - eflx_soil_grnd(p)
2362 ! eflx_soil_grnd includes all the solar radiation absorbed in the lake,
2363 ! unlike eflx_gnet
2364 if(abs(errsoi(c)) > .001_kind_lake) then ! 1.e-5_kind_lake) then
2365 WRITE( message,* )'Primary soil energy conservation error in shlake &
2366 &column during Tridiagonal Solution,', 'error (W/m^2):', c, errsoi(c)
2367 errmsg=trim(message)
2368 errflg=1
2369 return
2370 end if
2371 end do
2372 ! This has to be done before convective mixing because the heat capacities for each layer
2373 ! will get scrambled.
2374
2375 end if if_debug_energy
2376
2377 !!!!!!!!!!!!!!!!!!!!!!!
2378
2379 ! 9!) Phase change
2380 call phasechange_lake (snl,h2osno,dz,dz_lake, & !i
2381 t_soisno,h2osoi_liq,h2osoi_ice, & !i&o
2382 lake_icefrac,t_lake, snowdp, & !i&o
2383 qflx_snomelt,eflx_snomelt,imelt, & !o
2384 cv, cv_lake, & !i&o
2385 lhabs) !o
2386
2387 !!!!!!!!!!!!!!!!!!!!!!!
2388
2389 ! 9.5!) Second energy check and water check. Now check energy balance before and after phase
2390 ! change, considering the possibility of changed heat capacity during phase change, by
2391 ! using initial heat capacity in the first step, final heat capacity in the second step,
2392 ! and differences from tfrz only to avoid enthalpy correction for (cpliq-cpice)*melt*tfrz.
2393 ! Also check soil water sum.
2394
2395 if_debug_balance: if (lakedebug) then
2396 do j = 1, nlevlake
2397 !dir$ concurrent
2398 !cdir nodep
2399 do fc = 1, num_shlakec
2400 c = filter_shlakec(fc)
2401
2402 esum2(c) = esum2(c) - (t_lake(c,j)-tfrz)*cv_lake(c,j)
2403 end do
2404 end do
2405
2406 do j = -nlevsnow+1, nlevsoil
2407 !dir$ concurrent
2408 !cdir nodep
2409 do fc = 1, num_shlakec
2410 c = filter_shlakec(fc)
2411
2412 if (j >= jtop(c)) then
2413 esum2(c) = esum2(c) - (t_soisno(c,j)-tfrz)*cv(c,j)
2414 end if
2415 end do
2416 end do
2417
2418 !dir$ concurrent
2419 !cdir nodep
2420 do fp = 1, num_shlakep
2421 p = filter_shlakep(fp)
2422 c = pcolumn(p)
2423 ! Again assuming only one pft per column
2424 esum2(c) = esum2(c) - lhabs(c)
2425 errsoi(c) = esum2(c)/dtime
2426 if(abs(errsoi(c)) > 1.e-5_kind_lake) then
2427 write(message,*)'Primary soil energy conservation error in shlake column during Phase Change, error (W/m^2):', &
2428 c, errsoi(c)
2429 errmsg=trim(message)
2430 errflg=1
2431 return
2432 end if
2433 end do
2434
2435 ! Check soil water
2436 ! Sum soil water.
2437 do j = 1, nlevsoil
2438 !dir$ concurrent
2439 !cdir nodep
2440 do fc = 1, num_shlakec
2441 c = filter_shlakec(fc)
2442 if (j == 1) wsum_end(c) = 0._kind_lake
2443 wsum_end(c) = wsum_end(c) + h2osoi_ice(c,j) + h2osoi_liq(c,j)
2444 if (j == nlevsoil) then
2445 if (abs(wsum(c)-wsum_end(c))>1.e-7_kind_lake) then
2446 write(message,*)'Soil water balance error during phase change in ShalLakeTemperature.', &
2447 'column, error (kg/m^2):', c, wsum_end(c)-wsum(c)
2448 errmsg=trim(message)
2449 errflg=1
2450 return
2451 end if
2452 end if
2453 end do
2454 end do
2455
2456 endif if_debug_balance
2457
2458 !!!!!!!!!!!!!!!!!!!!!!!!!!
2459 ! 10!) Convective mixing: make sure fracice*dz is conserved, heat content c*dz*T is conserved, and
2460 ! all ice ends up at the top. Done over all lakes even if frozen.
2461 ! Either an unstable density profile or ice in a layer below an incompletely frozen layer will trigger.
2462
2463 !Recalculate density
2464 do j = 1, nlevlake
2465 !dir$ concurrent
2466 !cdir nodep
2467 do fc = 1, num_shlakec
2468 c = filter_shlakec(fc)
2469 rhow(c,j) = (1._kind_lake - lake_icefrac(c,j)) * &
2470 1000._kind_lake*( 1.0_kind_lake - 1.9549e-05_kind_lake*(abs(t_lake(c,j)-277._kind_lake))**1.68_kind_lake ) &
2471 + lake_icefrac(c,j)*denice
2472 end do
2473 end do
2474
2475 do j = 1, nlevlake-1
2476 !dir$ concurrent
2477 !cdir nodep
2478 do fc = 1, num_shlakec
2479 c = filter_shlakec(fc)
2480 qav(c) = 0._kind_lake
2481 nav(c) = 0._kind_lake
2482 iceav(c) = 0._kind_lake
2483 end do
2484
2485 do i = 1, j+1
2486 !dir$ concurrent
2487 !cdir nodep
2488 do fc = 1, num_shlakec
2489 c = filter_shlakec(fc)
2490 if (rhow(c,j) > rhow(c,j+1) .or. &
2491 (lake_icefrac(c,j) < 1._kind_lake .and. lake_icefrac(c,j+1) > 0._kind_lake) ) then
2492 if(debug_print) then
2493 if (i==1) then
2494 print *, 'Convective Ice Mixing in column ', c, 'lake_icefrac(c,j) ',lake_icefrac(c,j),lake_icefrac(c,j+1)
2495 endif
2496 endif
2497 qav(c) = qav(c) + dz_lake(c,i)*(t_lake(c,i)-tfrz) * &
2498 ((1._kind_lake - lake_icefrac(c,i))*cwat + lake_icefrac(c,i)*cice_eff)
2499 ! tav(c) = tav(c) + t_lake(c,i)*dz_lake(c,i)
2500 iceav(c) = iceav(c) + lake_icefrac(c,i)*dz_lake(c,i)
2501 nav(c) = nav(c) + dz_lake(c,i)
2502 end if
2503 end do
2504 end do
2505
2506 !dir$ concurrent
2507 !cdir nodep
2508 do fc = 1, num_shlakec
2509 c = filter_shlakec(fc)
2510 if (rhow(c,j) > rhow(c,j+1) .or. &
2511 (lake_icefrac(c,j) < 1._kind_lake .and. lake_icefrac(c,j+1) > 0._kind_lake) ) then
2512 qav(c) = qav(c)/nav(c)
2513 iceav(c) = iceav(c)/nav(c)
2514 !If the average temperature is above freezing, put the extra energy into the water.
2515 !If it is below freezing, take it away from the ice.
2516 if (qav(c) > 0._kind_lake) then
2517 tav_froz(c) = 0._kind_lake !Celsius
2518 tav_unfr(c) = qav(c) / ((1._kind_lake - iceav(c))*cwat)
2519 else if (qav(c) < 0._kind_lake) then
2520 tav_froz(c) = qav(c) / (iceav(c)*cice_eff)
2521 tav_unfr(c) = 0._kind_lake !Celsius
2522 else
2523 tav_froz(c) = 0._kind_lake
2524 tav_unfr(c) = 0._kind_lake
2525 end if
2526 end if
2527 end do
2528
2529 do i = 1, j+1
2530 !dir$ concurrent
2531 !cdir nodep
2532 do fc = 1, num_shlakec
2533 c = filter_shlakec(fc)
2534 if (nav(c) > 0._kind_lake) then
2535 ! if(0==1) then
2536
2537 !Put all the ice at the top.!
2538 !If the average temperature is above freezing, put the extra energy into the water.
2539 !If it is below freezing, take it away from the ice.
2540 !For the layer with both ice & water, be careful to use the average temperature
2541 !that preserves the correct total heat content given what the heat capacity of that
2542 !layer will actually be.
2543 if (i == 1) zsum(c) = 0._kind_lake
2544 if ((zsum(c)+dz_lake(c,i))/nav(c) <= iceav(c)) then
2545 t_lake(c,i) = tav_froz(c) + tfrz
2546 !tgs - 30jul19 - the next line is a bug and should be commented
2547 !out. This bug prevents lake ice form completely melting.
2548 ! lake_icefrac(c,i) = 1._kind_lake
2549 else if (zsum(c)/nav(c) < iceav(c)) then
2550 !tgs - change ice fraction
2551 lake_icefrac(c,i) = (iceav(c)*nav(c) - zsum(c)) / dz_lake(c,i)
2552 ! Find average value that preserves correct heat content.
2553 t_lake(c,i) = ( lake_icefrac(c,i)*tav_froz(c)*cice_eff &
2554 + (1._kind_lake - lake_icefrac(c,i))*tav_unfr(c)*cwat ) &
2555 / ( lake_icefrac(c,i)*cice_eff + (1-lake_icefrac(c,i))*cwat ) + tfrz
2556 else
2557 !tgs - remove ice
2558 lake_icefrac(c,i) = 0._kind_lake
2559 t_lake(c,i) = tav_unfr(c) + tfrz
2560 end if
2561 zsum(c) = zsum(c) + dz_lake(c,i)
2562
2563 rhow(c,i) = (1._kind_lake - lake_icefrac(c,i)) * &
2564 1000._kind_lake*( 1.0_kind_lake - 1.9549e-05_kind_lake*(abs(t_lake(c,i)-277._kind_lake))**1.68_kind_lake ) &
2565 + lake_icefrac(c,i)*denice
2566 if (debug_print .and. lake_icefrac(c,j) > 0.)print *,'rhow(c,i),lake_icefrac(c,i),t_lake(c,i)', &
2567 i,rhow(c,i),lake_icefrac(c,i),t_lake(c,i),denice
2568 end if
2569 end do
2570 end do
2571 end do
2572
2573 !!!!!!!!!!!!!!!!!!!!!!!
2574 ! 11!) Re-evaluate thermal properties and sum energy content.
2575 ! For lake
2576 do j = 1, nlevlake
2577 !dir$ concurrent
2578 !cdir nodep
2579 do fc = 1, num_shlakec
2580 c = filter_shlakec(fc)
2581
2582 cv_lake(c,j) = dz_lake(c,j) * (cwat*(1._kind_lake-lake_icefrac(c,j)) + cice_eff*lake_icefrac(c,j))
2583 if (debug_print .and. lake_icefrac(c,j) > 0.) then
2584 print *,'Lake Ice Fraction, c, level:', c, j, lake_icefrac(c,j)
2585 endif
2586 end do
2587 end do
2588 ! For snow / soil
2589 ! call SoilThermProp_Lake(lbc, ubc, num_shlakec, filter_shlakec, tk, cv, tktopsoillay)
2590 call soilthermprop_lake (snl,dz,zi,z,t_soisno,h2osoi_liq,h2osoi_ice, &
2591 watsat, tksatu, tkmg, tkdry, csol, tk, cv, tktopsoillay,errmsg,errflg)
2592
2593
2594 ! Do as above to sum energy content
2595 do j = 1, nlevlake
2596 !dir$ concurrent
2597 !cdir nodep
2598 do fc = 1, num_shlakec
2599 c = filter_shlakec(fc)
2600
2601 ! ncvts(c) = ncvts(c) + cv_lake(c,j)*t_lake(c,j) &
2602 ncvts(c) = ncvts(c) + cv_lake(c,j)*(t_lake(c,j)-tfrz) &
2603 + cfus*dz_lake(c,j)*(1._kind_lake-lake_icefrac(c,j)) !&
2604 ! + (cwat-cice_eff)*lake_icefrac(c)*tfrz*dz_lake(c,j) !enthalpy reconciliation term
2605 fin(c) = fin(c) + phi(c,j)
2606 if(debug_print) then
2607 if (abs(xlat_d-52.1152).lt.0.1 .and. &
2608 abs(xlon_d-260.405).lt.0.1)then
2609 print *,' ncvts(c) at xlat_d,xlon_d',xlat_d,xlon_d
2610 print *,' new cv_lake(c,j),t_lake(c,j),cfus,lake_icefrac(c,j),ncvts(c),fin(c)', &
2611 j,cv_lake(c,j),t_lake(c,j),cfus,lake_icefrac(c,j),ncvts(c),fin(c)
2612 print *,' new dz_lake(c,j),fin(c),phi(c,j)',c,dz_lake(c,j),fin(c),phi(c,j)
2613 endif
2614 endif
2615 end do
2616 end do
2617
2618 do j = -nlevsnow + 1, nlevsoil
2619 !dir$ concurrent
2620 !cdir nodep
2621 do fc = 1, num_shlakec
2622 c = filter_shlakec(fc)
2623
2624 if (j >= jtop(c)) then
2625 ! ncvts(c) = ncvts(c) + cv(c,j)*t_soisno(c,j) &
2626 ncvts(c) = ncvts(c) + cv(c,j)*(t_soisno(c,j)-tfrz) &
2627 + hfus*h2osoi_liq(c,j) !&
2628 ! + (cpliq-cpice)*h2osoi_ice(c,j)*tfrz !enthalpy reconciliation term
2629 if(debug_print) then
2630 if (abs(xlat_d-52.1152).lt.0.1 .and. &
2631 abs(xlon_d-260.405).lt.0.1)then
2632 print *,' ncvts(c) at xlat_d,xlon_d',xlat_d,xlon_d
2633 print *,'new j,jtop(c)',j,jtop(c),'h2osoi_liq(c,j) ',h2osoi_liq(c,j),'h2osoi_ice(c,j)',h2osoi_ice(c,j)
2634 print *,'new cv(c,j),t_soisno(c,j),hfus,ncvts(c)',c,j,cv(c,j),t_soisno(c,j),hfus,ncvts(c)
2635 print *,'new h2osno(c)',h2osno(c)
2636 endif
2637 endif
2638 if (j == 1 .and. h2osno(c) > 0._kind_lake .and. j == jtop(c)) then
2639 ncvts(c) = ncvts(c) - h2osno(c)*hfus
2640 end if
2641 end if
2642 if (j == 1) fin(c) = fin(c) + phi_soil(c)
2643 end do
2644 end do
2645
2646
2647 ! Check energy conservation.
2648
2649 do fp = 1, num_shlakep
2650 p = filter_shlakep(fp)
2651 c = pcolumn(p)
2652 errsoi(c) = (ncvts(c)-ocvts(c)) / dtime - fin(c)
2653 if(debug_print) then
2654 if (abs(xlat_d-52.1152).lt.0.1 .and. &
2655 abs(xlon_d-260.405).lt.0.1)then
2656 print *,'xlat_d,xlon_d',xlat_d,xlon_d
2657 print *,'errsoi(c),fin(c),ncvts(c),ocvts(c),dtime,lake_icefrac(c,:),h2osno(c)', &
2658 errsoi(c),fin(c),ncvts(c),ocvts(c),dtime,lake_icefrac(c,:),h2osno(c)
2659 endif
2660 endif
2661 if( .not.lakedebug ) then
2662 if (abs(errsoi(c)) < 10._kind_lake) then
2663 eflx_sh_tot(p) = eflx_sh_tot(p) - errsoi(c)
2664 eflx_sh_grnd(p) = eflx_sh_grnd(p) - errsoi(c)
2665 eflx_soil_grnd(p) = eflx_soil_grnd(p) + errsoi(c)
2666 eflx_gnet(p) = eflx_gnet(p) + errsoi(c)
2667 if(debug_print) then
2668 if (abs(errsoi(c)) > 1.e-1_kind_lake) then
2669 print *,'errsoi incorporated at xlat_d,xlon_d',xlat_d,xlon_d
2670 print *,'errsoi incorporated into sensible heat in ShalLakeTemperature: c, (W/m^2):', c, errsoi(c)
2671 end if
2672 endif
2673 errsoi(c) = 0._kind_lake
2674 endif
2675 elseif ( lakedebug) then
2676 if (abs(errsoi(c)) < 1._kind_lake) then
2677 eflx_sh_tot(p) = eflx_sh_tot(p) - errsoi(c)
2678 eflx_sh_grnd(p) = eflx_sh_grnd(p) - errsoi(c)
2679 eflx_soil_grnd(p) = eflx_soil_grnd(p) + errsoi(c)
2680 eflx_gnet(p) = eflx_gnet(p) + errsoi(c)
2681 if (abs(errsoi(c)) > 1.e-1_kind_lake) then
2682 print *,'errsoi incorporated into sensible heat in ShalLakeTemperature: c, (W/m^2):', c, errsoi(c)
2683 end if
2684 errsoi(c) = 0._kind_lake
2685 else
2686 print *,'Soil Energy Balance Error at column, ', c, 'G, fintotal, column E tendency = ', &
2687 eflx_gnet(p), fin(c), (ncvts(c)-ocvts(c)) / dtime,'xlat_d,xlon_d',xlat_d,xlon_d
2688 print *,'errsoi(c),ncvts(c),ocvts(c)',errsoi(c),ncvts(c),ocvts(c),'xlat_d,xlon_d',xlat_d,xlon_d
2689 print *,'lake_icefrac(c,:),h2osno(c)', lake_icefrac(c,:),h2osno(c)
2690 print *,'t_lake(c,:),t_soisno(c,:)',t_lake(c,:),t_soisno(c,:)
2691 end if
2692 end if ! LAKEDEBUG
2693 end do
2694 ! This loop assumes only one point per column.
2695
2696 end subroutine shallaketemperature
2697
2698 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2699 !-----------------------------------------------------------------------
2700 !BOP
2701 !
2702 ! ROUTINE: SoilThermProp_Lake
2703 !
2704 ! INTERFACE:
2705 ! DESCRIPTION:
2720 subroutine soilthermprop_lake (snl,dz,zi,z,t_soisno,h2osoi_liq,h2osoi_ice, &
2721 watsat, tksatu, tkmg, tkdry, csol, tk, cv, tktopsoillay,errmsg,errflg)
2722
2723 implicit none
2724 !in
2725
2726 integer, intent(inout) :: errflg
2727 character(*), intent(inout) :: errmsg
2728 integer , intent(in) :: snl(1)
2729 ! real(kind_lake), intent(in) :: h2osno(1) !< snow water (mm H2O)
2730 real(kind_lake), intent(in) :: watsat(1,nlevsoil)
2731 real(kind_lake), intent(in) :: tksatu(1,nlevsoil)
2732 real(kind_lake), intent(in) :: tkmg(1,nlevsoil)
2733 real(kind_lake), intent(in) :: tkdry(1,nlevsoil)
2734 real(kind_lake), intent(in) :: csol(1,nlevsoil)
2735 real(kind_lake), intent(in) :: dz(1,-nlevsnow+1:nlevsoil)
2736 real(kind_lake), intent(in) :: zi(1,-nlevsnow+0:nlevsoil)
2737 real(kind_lake), intent(in) :: z(1,-nlevsnow+1:nlevsoil)
2738 real(kind_lake), intent(in) :: t_soisno(1,-nlevsnow+1:nlevsoil)
2739 real(kind_lake), intent(in) :: h2osoi_liq(1,-nlevsnow+1:nlevsoil)
2740 real(kind_lake), intent(in) :: h2osoi_ice(1,-nlevsnow+1:nlevsoil)
2741
2742 !out
2743 real(kind_lake), intent(out) :: cv(lbc:ubc,-nlevsnow+1:nlevsoil)
2744 real(kind_lake), intent(out) :: tk(lbc:ubc,-nlevsnow+1:nlevsoil)
2745 real(kind_lake), intent(out) :: tktopsoillay(lbc:ubc)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2747 ! !CALLED FROM:
2748 ! subroutine ShalLakeTemperature in this module.
2749 !
2750 ! !REVISION HISTORY:
2751 ! 15 September 1999: Yongjiu Dai; Initial code
2752 ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision
2753 ! 2/13/02, Peter Thornton: migrated to new data structures
2754 ! 7/01/03, Mariana Vertenstein: migrated to vector code
2755 ! 4/09, Zack Subin, adjustment for ShalLake code.
2756 ! June 2022, Sam Trahan updated for CCPP
2757 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2758 ! !LOCAL VARIABLES:
2759 !
2760 ! local pointers to original implicit in scalars
2761 !
2762 ! integer , pointer :: clandunit(:) ! column's landunit
2763 ! integer , pointer :: ityplun(:) ! landunit type
2764 !
2765 !EOP
2766
2767
2768 ! OTHER LOCAL VARIABLES:
2769
2770 integer :: l,c,j ! indices
2771 integer :: fc ! lake filtered column indices
2772 real(kind_lake) :: bw ! partial density of water (ice + liquid)
2773 real(kind_lake) :: dksat ! thermal conductivity for saturated soil (j/(k s m))
2774 real(kind_lake) :: dke ! kersten number
2775 real(kind_lake) :: fl ! fraction of liquid or unfrozen water to total water
2776 real(kind_lake) :: satw ! relative total water content of soil.
2777 real(kind_lake) :: thk(lbc:ubc,-nlevsnow+1:nlevsoil) ! thermal conductivity of layer
2778 character*256 :: message
2779
2780 real(kind_lake) :: denom
2781
2782 ! Thermal conductivity of soil from Farouki (1981)
2783
2784 do j = -nlevsnow+1,nlevsoil
2785 !dir$ concurrent
2786 !cdir nodep
2787 do fc = 1, num_shlakec
2788 c = filter_shlakec(fc)
2789
2790 ! Only examine levels from 1->nlevsoil
2791 if (j >= 1) then
2792 ! l = clandunit(c)
2793 ! if (ityplun(l) /= istwet .AND. ityplun(l) /= istice) then
2794 ! This could be altered later for allowing this to be over glaciers.
2795
2796 ! Soil should be saturated.
2797 if (lakedebug) then
2798 satw = (h2osoi_liq(c,j)/denh2o + h2osoi_ice(c,j)/denice)/(dz(c,j)*watsat(c,j))
2799 ! satw = min(1._kind_lake, satw)
2800 if (satw < 0.999_kind_lake) then
2801 write(message,*)'WARNING: soil layer unsaturated in SoilThermProp_Lake, satw, j = ', satw, j
2802 ! errmsg=trim(message)
2803 ! errflg=1
2804 write(0,'(A)') trim(message)
2805 end if
2806 ! Could use denice because if it starts out frozen, the volume of water will go below sat.,
2807 ! since we're not yet doing excess ice.
2808 ! But take care of this in HydrologyLake.
2809 endif
2810 satw = 1._kind_lake
2811 denom = (h2osoi_ice(c,j)+h2osoi_liq(c,j))
2812 if(denom>zero_h2o) then
2813 fl = h2osoi_liq(c,j)/denom
2814 else
2815 write(message,'(A,I0)') 'WARNING: zero h2osoi_ice+h2osoi_liq at j = ', j
2816 ! errmsg=trim(message)
2817 ! errflg=1
2818 fl = 0
2819 write(0,'(A)') trim(message)
2820 endif
2821 if (t_soisno(c,j) >= tfrz) then ! Unfrozen soil
2822 dke = max(0._kind_lake, log10(satw) + 1.0_kind_lake)
2823 dksat = tksatu(c,j)
2824 else ! Frozen soil
2825 dke = satw
2826 dksat = tkmg(c,j)*0.249_kind_lake**(fl*watsat(c,j))*2.29_kind_lake**watsat(c,j)
2827 endif
2828 thk(c,j) = dke*dksat + (1._kind_lake-dke)*tkdry(c,j)
2829 ! else
2830 ! thk(c,j) = tkwat
2831 ! if (t_soisno(c,j) < tfrz) thk(c,j) = tkice
2832 ! endif
2833 endif
2834
2835 ! Thermal conductivity of snow, which from Jordan (1991) pp. 18
2836 ! Only examine levels from snl(c)+1 -> 0 where snl(c) < 1
2837 if (snl(c)+1 < 1 .AND. (j >= snl(c)+1) .AND. (j <= 0)) then
2838 bw = (h2osoi_ice(c,j)+h2osoi_liq(c,j))/dz(c,j)
2839 thk(c,j) = tkairc + (7.75e-5_kind_lake *bw + 1.105e-6_kind_lake*bw*bw)*(tkice-tkairc)
2840 end if
2841
2842 end do
2843 end do
2844
2845 ! Thermal conductivity at the layer interface
2846
2847 ! Have to correct for the fact that bottom snow layer and top soil layer border lake.
2848 ! For the first case, the snow layer conductivity for the middle of the layer will be returned.
2849 ! Because the interfaces are below the soil layers, the conductivity for the top soil layer
2850 ! will have to be returned separately.
2851 do j = -nlevsnow+1,nlevsoil
2852 !dir$ concurrent
2853 !cdir nodep
2854 do fc = 1,num_shlakec
2855 c = filter_shlakec(fc)
2856 if (j >= snl(c)+1 .AND. j <= nlevsoil-1 .AND. j /= 0) then
2857 tk(c,j) = thk(c,j)*thk(c,j+1)*(z(c,j+1)-z(c,j)) &
2858 /(thk(c,j)*(z(c,j+1)-zi(c,j))+thk(c,j+1)*(zi(c,j)-z(c,j)))
2859 else if (j == 0) then
2860 tk(c,j) = thk(c,j)
2861 else if (j == nlevsoil) then
2862 tk(c,j) = 0._kind_lake
2863 end if
2864 ! For top soil layer.
2865 if (j == 1) tktopsoillay(c) = thk(c,j)
2866 end do
2867 end do
2868
2869 ! Soil heat capacity, from de Vires (1963)
2870
2871 do j = 1, nlevsoil
2872 !dir$ concurrent
2873 !cdir nodep
2874 do fc = 1,num_shlakec
2875 c = filter_shlakec(fc)
2876 ! l = clandunit(c)
2877 ! if (ityplun(l) /= istwet .AND. ityplun(l) /= istice) then
2878 cv(c,j) = csol(c,j)*(1-watsat(c,j))*dz(c,j) + &
2879 (h2osoi_ice(c,j)*cpice + h2osoi_liq(c,j)*cpliq)
2880 ! else
2881 ! cv(c,j) = (h2osoi_ice(c,j)*cpice + h2osoi_liq(c,j)*cpliq)
2882 ! endif
2883 ! if (j == 1) then
2884 ! if (snl(c)+1 == 1 .AND. h2osno(c) > 0._kind_lake) then
2885 ! cv(c,j) = cv(c,j) + cpice*h2osno(c)
2886 ! end if
2887 ! end if
2888 ! Won't worry about heat capacity for thin snow on lake with no snow layers.
2889 enddo
2890 end do
2891
2892 ! Snow heat capacity
2893
2894 do j = -nlevsnow+1,0
2895 !dir$ concurrent
2896 !cdir nodep
2897 do fc = 1,num_shlakec
2898 c = filter_shlakec(fc)
2899 if (snl(c)+1 < 1 .and. j >= snl(c)+1) then
2900 cv(c,j) = cpliq*h2osoi_liq(c,j) + cpice*h2osoi_ice(c,j)
2901 end if
2902 end do
2903 end do
2904
2905 end subroutine soilthermprop_lake
2906
2907
2908 !-----------------------------------------------------------------------
2909 !BOP
2910 !
2911 ! ROUTINE: PhaseChange_Lake
2912 !
2913 ! !INTERFACE:
2914
2915 ! DESCRIPTION:
2932 subroutine phasechange_lake (snl,h2osno,dz,dz_lake, & !i
2933 t_soisno,h2osoi_liq,h2osoi_ice, & !i&o
2934 lake_icefrac,t_lake, snowdp, & !i&o
2935 qflx_snomelt,eflx_snomelt,imelt, & !o
2936 cv, cv_lake, & !i&o
2937 lhabs) !o
2938 !=============================================================================================
2939 !CALLED FROM:
2940 ! subroutine ShalLakeTemperature in this module
2941 !
2942 !REVISION HISTORY:
2943 ! - 04/2009 Zack Subin: Initial code
2944 ! - June 2022 Sam Trahan: Modified for CCPP
2945 !==============================================================================================
2946 ! !USES:
2947 !
2948 ! !ARGUMENTS:
2949 implicit none
2950 !in:
2951
2952 integer , intent(in) :: snl(1)
2953 real(kind_lake), intent(inout) :: h2osno(1)
2954 real(kind_lake), intent(in) :: dz(1,-nlevsnow+1:nlevsoil)
2955 real(kind_lake), intent(in) :: dz_lake(1,nlevlake)
2956 ! Needed in case snow height is less than critical value.
2957
2958 !inout:
2959
2960 real(kind_lake), intent(inout) :: snowdp(1)
2961 real(kind_lake), intent(inout) :: t_soisno(1,-nlevsnow+1:nlevsoil)
2962 real(kind_lake), intent(inout) :: h2osoi_liq(1,-nlevsnow+1:nlevsoil)
2963 real(kind_lake), intent(inout) :: h2osoi_ice(1,-nlevsnow+1:nlevsoil)
2964 real(kind_lake), intent(inout) :: lake_icefrac(1,nlevlake)
2965 real(kind_lake), intent(inout) :: t_lake(1,nlevlake)
2966 !out:
2967
2968 real(kind_lake), intent(out) :: qflx_snomelt(1)
2969 real(kind_lake), intent(out) :: eflx_snomelt(1)
2970 integer, intent(out) :: imelt(1,-nlevsnow+1:nlevsoil)
2971 !What's the sign of this? Is it just output?
2972 real(kind_lake), intent(inout) :: cv(lbc:ubc,-nlevsnow+1:nlevsoil)
2973 real(kind_lake), intent(inout) :: cv_lake (lbc:ubc,1:nlevlake)
2974 real(kind_lake), intent(out):: lhabs(lbc:ubc)
2975
2976
2977 ! OTHER LOCAL VARIABLES:
2978
2979 integer :: j,c,g !do loop index
2980 integer :: fc !lake filtered column indices
2981 real(kind_lake) :: heatavail !available energy for melting or freezing (J/m^2)
2982 real(kind_lake) :: heatrem !energy residual or loss after melting or freezing
2983 real(kind_lake) :: melt !actual melting (+) or freezing (-) [kg/m2]
2984 real(kind_lake), parameter :: smallnumber = 1.e-7_kind_lake !to prevent tiny residuals from rounding error
2985 logical :: dophasechangeflag
2986 !-----------------------------------------------------------------------
2987
2988 ! Initialization
2989
2990 !dir$ concurrent
2991 !cdir nodep
2992 do fc = 1,num_shlakec
2993 c = filter_shlakec(fc)
2994
2995 qflx_snomelt(c) = 0._kind_lake
2996 eflx_snomelt(c) = 0._kind_lake
2997 lhabs(c) = 0._kind_lake
2998 end do
2999
3000 do j = -nlevsnow+1,0
3001 !dir$ concurrent
3002 !cdir nodep
3003 do fc = 1,num_shlakec
3004 c = filter_shlakec(fc)
3005
3006 if (j >= snl(c) + 1) imelt(c,j) = 0
3007 end do
3008 end do
3009
3010 ! Check for case of snow without snow layers and top lake layer temp above freezing.
3011
3012 !dir$ concurrent
3013 !cdir nodep
3014 do fc = 1,num_shlakec
3015 c = filter_shlakec(fc)
3016
3017 if (snl(c) == 0 .and. h2osno(c) > 0._kind_lake .and. t_lake(c,1) > tfrz) then
3018 heatavail = (t_lake(c,1) - tfrz) * cv_lake(c,1)
3019 melt = min(h2osno(c), heatavail/hfus)
3020 heatrem = max(heatavail - melt*hfus, 0._kind_lake)
3021 !catch small negative value to keep t at tfrz
3022 t_lake(c,1) = tfrz + heatrem/(cv_lake(c,1))
3023 snowdp(c) = snowdp(c)*(1._kind_lake - melt/h2osno(c))
3024 h2osno(c) = h2osno(c) - melt
3025 lhabs(c) = lhabs(c) + melt*hfus
3026 qflx_snomelt(c) = qflx_snomelt(c) + melt
3027 ! Prevent tiny residuals
3028 if (h2osno(c) < smallnumber) h2osno(c) = 0._kind_lake
3029 if (snowdp(c) < smallnumber) snowdp(c) = 0._kind_lake
3030 end if
3031 end do
3032
3033 ! Lake phase change
3034
3035 do j = 1,nlevlake
3036 !dir$ concurrent
3037 !cdir nodep
3038 do fc = 1,num_shlakec
3039 c = filter_shlakec(fc)
3040
3041 dophasechangeflag = .false.
3042 if (t_lake(c,j) > tfrz .and. lake_icefrac(c,j) > 0._kind_lake) then ! melting
3043 dophasechangeflag = .true.
3044 heatavail = (t_lake(c,j) - tfrz) * cv_lake(c,j)
3045 melt = min(lake_icefrac(c,j)*denh2o*dz_lake(c,j), heatavail/hfus)
3046 !denh2o is used because layer thickness is not adjusted for freezing
3047 heatrem = max(heatavail - melt*hfus, 0._kind_lake)
3048 !catch small negative value to keep t at tfrz
3049 else if (t_lake(c,j) < tfrz .and. lake_icefrac(c,j) < 1._kind_lake) then !freezing
3050 dophasechangeflag = .true.
3051 heatavail = (t_lake(c,j) - tfrz) * cv_lake(c,j)
3052 melt = max(-(1._kind_lake-lake_icefrac(c,j))*denh2o*dz_lake(c,j), heatavail/hfus)
3053 !denh2o is used because layer thickness is not adjusted for freezing
3054 heatrem = min(heatavail - melt*hfus, 0._kind_lake)
3055 !catch small positive value to keep t at tfrz
3056 end if
3057 ! Update temperature and ice fraction.
3058 if (dophasechangeflag) then
3059 lake_icefrac(c,j) = lake_icefrac(c,j) - melt/(denh2o*dz_lake(c,j))
3060 lhabs(c) = lhabs(c) + melt*hfus
3061 ! Update heat capacity
3062 cv_lake(c,j) = cv_lake(c,j) + melt*(cpliq-cpice)
3063 t_lake(c,j) = tfrz + heatrem/cv_lake(c,j)
3064 ! Prevent tiny residuals
3065 if (lake_icefrac(c,j) > 1._kind_lake - smallnumber) lake_icefrac(c,j) = 1._kind_lake
3066 if (lake_icefrac(c,j) < smallnumber) lake_icefrac(c,j) = 0._kind_lake
3067 end if
3068 end do
3069 end do
3070
3071 ! Snow & soil phase change
3072
3073 do j = -nlevsnow+1,nlevsoil
3074 !dir$ concurrent
3075 !cdir nodep
3076 do fc = 1,num_shlakec
3077 c = filter_shlakec(fc)
3078 dophasechangeflag = .false.
3079
3080 if (j >= snl(c) + 1) then
3081
3082 if (t_soisno(c,j) > tfrz .and. h2osoi_ice(c,j) > 0._kind_lake) then ! melting
3083 dophasechangeflag = .true.
3084 heatavail = (t_soisno(c,j) - tfrz) * cv(c,j)
3085 melt = min(h2osoi_ice(c,j), heatavail/hfus)
3086 heatrem = max(heatavail - melt*hfus, 0._kind_lake)
3087 !catch small negative value to keep t at tfrz
3088 if (j <= 0) then !snow
3089 imelt(c,j) = 1
3090 qflx_snomelt(c) = qflx_snomelt(c) + melt
3091 end if
3092 else if (t_soisno(c,j) < tfrz .and. h2osoi_liq(c,j) > 0._kind_lake) then !freezing
3093 dophasechangeflag = .true.
3094 heatavail = (t_soisno(c,j) - tfrz) * cv(c,j)
3095 melt = max(-h2osoi_liq(c,j), heatavail/hfus)
3096 heatrem = min(heatavail - melt*hfus, 0._kind_lake)
3097 !catch small positive value to keep t at tfrz
3098 if (j <= 0) then !snow
3099 imelt(c,j) = 2
3100 qflx_snomelt(c) = qflx_snomelt(c) + melt
3101 ! Does this works for both signs of melt in SnowHydrology? I think
3102 ! qflx_snomelt(c) is just output.
3103 end if
3104 end if
3105
3106 ! Update temperature and soil components.
3107 if (dophasechangeflag) then
3108 h2osoi_ice(c,j) = h2osoi_ice(c,j) - melt
3109 h2osoi_liq(c,j) = h2osoi_liq(c,j) + melt
3110 lhabs(c) = lhabs(c) + melt*hfus
3111 ! Update heat capacity
3112 cv(c,j) = cv(c,j) + melt*(cpliq-cpice)
3113 t_soisno(c,j) = tfrz + heatrem/cv(c,j)
3114 ! Prevent tiny residuals
3115 if (h2osoi_ice(c,j) < smallnumber) h2osoi_ice(c,j) = 0._kind_lake
3116 if (h2osoi_liq(c,j) < smallnumber) h2osoi_liq(c,j) = 0._kind_lake
3117 end if
3118
3119 end if
3120 end do
3121 end do
3122
3123 ! Update eflx_snomelt(c)
3124 !dir$ concurrent
3125 !cdir nodep
3126 do fc = 1,num_shlakec
3127 c = filter_shlakec(fc)
3128 eflx_snomelt(c) = qflx_snomelt(c)*hfus
3129 end do
3130 !!!
3131
3132 end subroutine phasechange_lake
3133
3134 ! DESCRIPTION:
3147 subroutine shallakehydrology(dz_lake,forc_rain,forc_snow, & !i
3148 begwb,qflx_evap_tot,forc_t,do_capsnow, &
3149 t_grnd,qflx_evap_soi, &
3150 qflx_snomelt,imelt,frac_iceold, & !i add by guhp
3151 z,dz,zi,snl,h2osno,snowdp,lake_icefrac,t_lake, & !i&o
3152 endwb,snowage,snowice,snowliq,t_snow, & !o
3153 t_soisno,h2osoi_ice,h2osoi_liq,h2osoi_vol, &
3154 qflx_drain,qflx_surf,qflx_infl,qflx_qrgwl, &
3155 qcharge,qflx_prec_grnd,qflx_snowcap, &
3156 qflx_snowcap_col,qflx_snow_grnd_pft, &
3157 qflx_snow_grnd_col,qflx_rain_grnd, &
3158 qflx_evap_tot_col,soilalpha,zwt,fcov, &
3159 rootr_column,qflx_evap_grnd,qflx_sub_snow, &
3160 qflx_dew_snow,qflx_dew_grnd,qflx_rain_grnd_col, &
3161 watsat, tksatu, tkmg, tkdry, csol, &
3162 dtime,errmsg,errflg)
3163
3164 !==================================================================================
3165 !
3166 ! WARNING: This subroutine assumes lake columns have one and only one pft.
3167 !
3168 ! Sequence is:
3169 ! ShalLakeHydrology:
3170 ! Do needed tasks from Hydrology1, Biogeophysics2, & top of Hydrology2.
3171 ! -> SnowWater: change of snow mass and snow water onto soil
3172 ! -> SnowCompaction: compaction of snow layers
3173 ! -> CombineSnowLayers: combine snow layers that are thinner than minimum
3174 ! -> DivideSnowLayers: subdivide snow layers that are thicker than maximum
3175 ! Add water to soil if melting has left it with open pore space.
3176 ! Cleanup and do water balance.
3177 ! If snow layers are found above a lake with unfrozen top layer, whose top
3178 ! layer has enough heat to melt all the snow ice without freezing, do so
3179 ! and eliminate the snow layers.
3180 !
3181 ! !REVISION HISTORY:
3182 ! Created by Zack Subin, 2009
3183 !
3184 !============================================================================================
3185
3186 ! USES:
3187 !
3188 implicit none
3189
3190 ! in:
3191
3192 integer, intent(inout) :: errflg
3193 character(*), intent(inout) :: errmsg
3194
3195 real(kind_lake) :: watsat(1,nlevsoil)
3196 real(kind_lake) :: tksatu(1,nlevsoil)
3197 real(kind_lake) :: tkmg(1,nlevsoil)
3198 real(kind_lake) :: tkdry(1,nlevsoil)
3199 real(kind_lake) :: csol(1,nlevsoil)
3200
3201 ! integer , intent(in) :: clandunit(1) !< column's landunit
3202 ! integer , intent(in) :: ityplun(1) !< landunit type
3203 real(kind_lake), intent(in) :: dtime
3204 real(kind_lake), intent(in) :: dz_lake(1,nlevlake)
3205 real(kind_lake), intent(in) :: forc_rain(1)
3206 real(kind_lake), intent(in) :: forc_snow(1)
3207 real(kind_lake), intent(in) :: qflx_evap_tot(1)
3208 real(kind_lake), intent(in) :: forc_t(1)
3209
3210 !real(kind_lake), intent(in),optional :: flfall(1) !< fraction of liquid water within falling precipitation (unused)
3211
3212 logical , intent(in) :: do_capsnow(1)
3213 real(kind_lake), intent(in) :: t_grnd(1)
3214 real(kind_lake), intent(in) :: qflx_evap_soi(1)
3215 real(kind_lake), intent(in) :: qflx_snomelt(1)
3216 integer, intent(in) :: imelt(1,-nlevsnow+1:nlevsoil)
3217
3218 !inout:
3219
3220 real(kind_lake), intent(inout) :: begwb(1)
3221
3222 ! inout:
3223
3224
3225 real(kind_lake), intent(inout) :: z(1,-nlevsnow+1:nlevsoil)
3226 real(kind_lake), intent(inout) :: dz(1,-nlevsnow+1:nlevsoil)
3227 real(kind_lake), intent(inout) :: zi(1,-nlevsnow+0:nlevsoil)
3228 integer , intent(inout) :: snl(1)
3229 real(kind_lake), intent(inout) :: h2osno(1)
3230 real(kind_lake), intent(inout) :: snowdp(1)
3231 real(kind_lake), intent(inout) :: lake_icefrac(1,nlevlake)
3232 real(kind_lake), intent(inout) :: t_lake(1,nlevlake)
3233
3234 real(kind_lake), intent(inout) :: frac_iceold(1,-nlevsnow+1:nlevsoil)
3235 ! out:
3236
3237
3238 real(kind_lake), intent(out) :: endwb(1)
3239 real(kind_lake), intent(out) :: snowage(1)
3240 real(kind_lake), intent(out) :: snowice(1)
3241 real(kind_lake), intent(out) :: snowliq(1)
3242 real(kind_lake), intent(out) :: t_snow(1)
3243 real(kind_lake), intent(out) :: t_soisno(1,-nlevsnow+1:nlevsoil)
3244 real(kind_lake), intent(out) :: h2osoi_ice(1,-nlevsnow+1:nlevsoil)
3245 real(kind_lake), intent(out) :: h2osoi_liq(1,-nlevsnow+1:nlevsoil)
3246 real(kind_lake), intent(out) :: h2osoi_vol(1,-nlevsnow+1:nlevsoil)
3247 real(kind_lake), intent(out) :: qflx_drain(1)
3248 real(kind_lake), intent(out) :: qflx_surf(1)
3249 real(kind_lake), intent(out) :: qflx_infl(1)
3250 real(kind_lake), intent(out) :: qflx_qrgwl(1)
3251 real(kind_lake), intent(out) :: qcharge(1)
3252 real(kind_lake), intent(out) :: qflx_prec_grnd(1)
3253 real(kind_lake), intent(out) :: qflx_snowcap(1)
3254 real(kind_lake), intent(out) :: qflx_snowcap_col(1)
3255 real(kind_lake), intent(out) :: qflx_snow_grnd_pft(1)
3256 real(kind_lake), intent(out) :: qflx_snow_grnd_col(1)
3257 real(kind_lake), intent(out) :: qflx_rain_grnd(1)
3258 real(kind_lake), intent(out) :: qflx_evap_tot_col(1)
3259 real(kind_lake) ,intent(out) :: soilalpha(1)
3260 real(kind_lake), intent(out) :: zwt(1)
3261 real(kind_lake), intent(out) :: fcov(1)
3262 real(kind_lake), intent(out) :: rootr_column(1,1:nlevsoil)
3263 real(kind_lake), intent(out) :: qflx_evap_grnd(1)
3264 real(kind_lake), intent(out) :: qflx_sub_snow(1)
3265 real(kind_lake), intent(out) :: qflx_dew_snow(1)
3266 real(kind_lake), intent(out) :: qflx_dew_grnd(1)
3267 real(kind_lake), intent(out) :: qflx_rain_grnd_col(1)
3268
3269 ! Block of biogeochem currently not used.
3270 real(kind_lake), pointer :: sucsat(:,:) ! minimum soil suction (mm)
3271 real(kind_lake), pointer :: bsw(:,:) ! Clapp and Hornberger "b"
3272 real(kind_lake), pointer :: bsw2(:,:) ! Clapp and Hornberger "b" for CN code
3273 real(kind_lake), pointer :: psisat(:,:) ! soil water potential at saturation for CN code (MPa)
3274 real(kind_lake), pointer :: vwcsat(:,:) ! volumetric water content at saturation for CN code (m3/m3)
3275 real(kind_lake), pointer :: wf(:) ! soil water as frac. of whc for top 0.5 m
3276 real(kind_lake), pointer :: soilpsi(:,:) ! soil water potential in each soil layer (MPa)
3277
3278 ! OTHER LOCAL VARIABLES:
3279
3280 integer :: p,fp,g,l,c,j,fc,jtop ! indices
3281 integer :: num_shlakesnowc ! number of column snow points
3282 integer :: filter_shlakesnowc(ubc-lbc+1) ! column filter for snow points
3283 integer :: num_shlakenosnowc ! number of column non-snow points
3284 integer :: filter_shlakenosnowc(ubc-lbc+1) ! column filter for non-snow points
3285 integer :: newnode ! flag when new snow node is set, (1=yes, 0=no)
3286 real(kind_lake) :: dz_snowf ! layer thickness rate change due to precipitation [mm/s]
3287 real(kind_lake) :: bifall ! bulk density of newly fallen dry snow [kg/m3]
3288 real(kind_lake) :: fracsnow(lbp:ubp) ! frac of precipitation that is snow
3289 real(kind_lake) :: fracrain(lbp:ubp) ! frac of precipitation that is rain
3290 real(kind_lake) :: qflx_prec_grnd_snow(lbp:ubp) ! snow precipitation incident on ground [mm/s]
3291 real(kind_lake) :: qflx_prec_grnd_rain(lbp:ubp) ! rain precipitation incident on ground [mm/s]
3292 real(kind_lake) :: qflx_evap_soi_lim ! temporary evap_soi limited by top snow layer content [mm/s]
3293 real(kind_lake) :: h2osno_temp ! temporary h2osno [kg/m^2]
3294 real(kind_lake) :: sumsnowice(lbc:ubc) ! sum of snow ice if snow layers found above unfrozen lake [kg/m&2]
3295 logical :: unfrozen(lbc:ubc) ! true if top lake layer is unfrozen with snow layers above
3296 real(kind_lake) :: heatrem ! used in case above [J/m^2]
3297 real(kind_lake) :: heatsum(lbc:ubc) ! used in case above [J/m^2]
3298 real(kind_lake) :: qflx_top_soil(1) !net water input into soil from top (mm/s)
3299 character*256 :: message
3300
3301 real(kind_lake),allocatable :: snow_water(:) ! temporary sum of snow water for Bal Check [kg/m^2]
3302 !-----------------------------------------------------------------------
3303
3304 ! Determine step size
3305
3306 ! Add soil water to water balance.
3307 do j = 1, nlevsoil
3308 !dir$ concurrent
3309 !cdir nodep
3310 do fc = 1, num_shlakec
3311 c = filter_shlakec(fc)
3312 begwb(c) = begwb(c) + h2osoi_ice(c,j) + h2osoi_liq(c,j)
3313 end do
3314 end do
3315
3316 !!!!!!!!!!!!!!!!!!!!!!!!!!!
3317
3318 ! Do precipitation onto ground, etc., from Hydrology1.
3319
3320 !dir$ concurrent
3321 !cdir nodep
3322 do fp = 1, num_shlakep
3323 p = filter_shlakep(fp)
3324 g = pgridcell(p)
3325 ! l = plandunit(p)
3326 c = pcolumn(p)
3327
3328 ! Precipitation onto ground (kg/(m2 s))
3329 ! ! PET, 1/18/2005: Added new terms for mass balance correction
3330 ! ! due to dynamic pft weight shifting (column-level h2ocan_loss)
3331 ! ! Because the fractionation between rain and snow is indeterminate if
3332 ! ! rain + snow = 0, I am adding this very small flux only to the rain
3333 ! ! components.
3334 ! Not relevant unless PFTs are added to lake later.
3335 ! if (frac_veg_nosno(p) == 0) then
3336 qflx_prec_grnd_snow(p) = forc_snow(g)
3337 qflx_prec_grnd_rain(p) = forc_rain(g) !+ h2ocan_loss(c)
3338 ! else
3339 ! qflx_prec_grnd_snow(p) = qflx_through_snow(p) + (qflx_candrip(p) * fracsnow(p))
3340 ! qflx_prec_grnd_rain(p) = qflx_through_rain(p) + (qflx_candrip(p) * fracrain(p)) + h2ocan_loss(c)
3341 ! end if
3342 qflx_prec_grnd(p) = qflx_prec_grnd_snow(p) + qflx_prec_grnd_rain(p)
3343
3344 if (do_capsnow(c)) then
3345 qflx_snowcap(p) = qflx_prec_grnd_snow(p) + qflx_prec_grnd_rain(p)
3346 qflx_snow_grnd_pft(p) = 0._kind_lake
3347 qflx_rain_grnd(p) = 0._kind_lake
3348 else
3349 qflx_snowcap(p) = 0._kind_lake
3350 qflx_snow_grnd_pft(p) = qflx_prec_grnd_snow(p) ! ice onto ground (mm/s)
3351 qflx_rain_grnd(p) = qflx_prec_grnd_rain(p) ! liquid water onto ground (mm/s)
3352 end if
3353 ! Assuming one PFT; needed for below
3354 qflx_snow_grnd_col(c) = qflx_snow_grnd_pft(p)
3355 qflx_rain_grnd_col(c) = qflx_rain_grnd(p)
3356
3357 end do ! (end pft loop)
3358
3359 ! Determine snow height and snow water
3360
3361 !dir$ concurrent
3362 !cdir nodep
3363 do fc = 1, num_shlakec
3364 c = filter_shlakec(fc)
3365 ! l = clandunit(c)
3366 g = cgridcell(c)
3367
3368 ! Use Alta relationship, Anderson(1976); LaChapelle(1961),
3369 ! U.S.Department of Agriculture Forest Service, Project F,
3370 ! Progress Rep. 1, Alta Avalanche Study Center:Snow Layer Densification.
3371
3372 if (do_capsnow(c)) then
3373 dz_snowf = 0._kind_lake
3374 else
3375 if (forc_t(g) > tfrz + 2._kind_lake) then
3376 bifall=50._kind_lake + 1.7_kind_lake*(17.0_kind_lake)**1.5_kind_lake
3377 else if (forc_t(g) > tfrz - 15._kind_lake) then
3378 bifall=50._kind_lake + 1.7_kind_lake*(forc_t(g) - tfrz + 15._kind_lake)**1.5_kind_lake
3379 else
3380 bifall=50._kind_lake
3381 end if
3382 dz_snowf = qflx_snow_grnd_col(c)/bifall
3383 snowdp(c) = snowdp(c) + dz_snowf*dtime
3384 h2osno(c) = h2osno(c) + qflx_snow_grnd_col(c)*dtime ! snow water equivalent (mm)
3385 end if
3386
3387 ! if (itype(l)==istwet .and. t_grnd(c)>tfrz) then
3388 ! h2osno(c)=0._kind_lake
3389 ! snowdp(c)=0._kind_lake
3390 ! snowage(c)=0._kind_lake
3391 ! end if
3392 ! Take care of this later in function.
3393
3394 ! When the snow accumulation exceeds 10 mm, initialize snow layer
3395 ! Currently, the water temperature for the precipitation is simply set
3396 ! as the surface air temperature
3397
3398 newnode = 0 ! flag for when snow node will be initialized
3399 if (snl(c) == 0 .and. qflx_snow_grnd_col(c) > 0.0_kind_lake .and. snowdp(c) >= 0.01_kind_lake) then
3400 newnode = 1
3401 snl(c) = -1
3402 dz(c,0) = snowdp(c) ! meter
3403 z(c,0) = -0.5_kind_lake*dz(c,0)
3404 zi(c,-1) = -dz(c,0)
3405 snowage(c) = 0._kind_lake ! snow age
3406 t_soisno(c,0) = min(tfrz, forc_t(g)) ! K
3407 h2osoi_ice(c,0) = h2osno(c) ! kg/m2
3408 h2osoi_liq(c,0) = 0._kind_lake ! kg/m2
3409 frac_iceold(c,0) = 1._kind_lake
3410 end if
3411
3412 ! The change of ice partial density of surface node due to precipitation.
3413 ! Only ice part of snowfall is added here, the liquid part will be added
3414 ! later.
3415
3416 if (snl(c) < 0 .and. newnode == 0) then
3417 h2osoi_ice(c,snl(c)+1) = h2osoi_ice(c,snl(c)+1)+dtime*qflx_snow_grnd_col(c)
3418 dz(c,snl(c)+1) = dz(c,snl(c)+1)+dz_snowf*dtime
3419 end if
3420
3421 end do
3422
3423 ! Calculate sublimation and dew, adapted from HydrologyLake and Biogeophysics2.
3424
3425 !dir$ concurrent
3426 !cdir nodep
3427 do fp = 1,num_shlakep
3428 p = filter_shlakep(fp)
3429 c = pcolumn(p)
3430 jtop = snl(c)+1
3431
3432 ! Use column variables here
3433 qflx_evap_grnd(c) = 0._kind_lake
3434 qflx_sub_snow(c) = 0._kind_lake
3435 qflx_dew_snow(c) = 0._kind_lake
3436 qflx_dew_grnd(c) = 0._kind_lake
3437
3438 if (jtop <= 0) then ! snow layers
3439 j = jtop
3440 ! Assign ground evaporation to sublimation from soil ice or to dew
3441 ! on snow or ground
3442
3443 if (qflx_evap_soi(p) >= 0._kind_lake) then
3444 ! for evaporation partitioning between liquid evap and ice sublimation,
3445 ! use the ratio of liquid to (liquid+ice) in the top layer to determine split
3446 ! Since we're not limiting evap over lakes, but still can't remove more from top
3447 ! snow layer than there is there, create temp. limited evap_soi.
3448 qflx_evap_soi_lim = min(qflx_evap_soi(p), (h2osoi_liq(c,j)+h2osoi_ice(c,j))/dtime)
3449 if ((h2osoi_liq(c,j)+h2osoi_ice(c,j)) > 0._kind_lake) then
3450 qflx_evap_grnd(c) = max(qflx_evap_soi_lim*(h2osoi_liq(c,j)/(h2osoi_liq(c,j)+h2osoi_ice(c,j))), 0._kind_lake)
3451 else
3452 qflx_evap_grnd(c) = 0._kind_lake
3453 end if
3454 qflx_sub_snow(c) = qflx_evap_soi_lim - qflx_evap_grnd(c)
3455 else
3456 if (t_grnd(c) < tfrz) then
3457 qflx_dew_snow(c) = abs(qflx_evap_soi(p))
3458 else
3459 qflx_dew_grnd(c) = abs(qflx_evap_soi(p))
3460 end if
3461 end if
3462 ! Update the pft-level qflx_snowcap
3463 ! This was moved in from Hydrology2 to keep all pft-level
3464 ! calculations out of Hydrology2
3465 if (do_capsnow(c)) qflx_snowcap(p) = qflx_snowcap(p) + qflx_dew_snow(c) + qflx_dew_grnd(c)
3466
3467 else ! No snow layers: do as in HydrologyLake but with actual clmtype variables
3468 if (qflx_evap_soi(p) >= 0._kind_lake) then
3469 ! Sublimation: do not allow for more sublimation than there is snow
3470 ! after melt. Remaining surface evaporation used for infiltration.
3471 qflx_sub_snow(c) = min(qflx_evap_soi(p), h2osno(c)/dtime)
3472 qflx_evap_grnd(c) = qflx_evap_soi(p) - qflx_sub_snow(c)
3473 else
3474 if (t_grnd(c) < tfrz-0.1_kind_lake) then
3475 qflx_dew_snow(c) = abs(qflx_evap_soi(p))
3476 else
3477 qflx_dew_grnd(c) = abs(qflx_evap_soi(p))
3478 end if
3479 end if
3480
3481 ! Update snow pack for dew & sub.
3482 h2osno_temp = h2osno(c)
3483 if (do_capsnow(c)) then
3484 h2osno(c) = h2osno(c) - qflx_sub_snow(c)*dtime
3485 qflx_snowcap(p) = qflx_snowcap(p) + qflx_dew_snow(c) + qflx_dew_grnd(c)
3486 else
3487 h2osno(c) = h2osno(c) + (-qflx_sub_snow(c)+qflx_dew_snow(c))*dtime
3488 end if
3489 if (h2osno_temp > 0._kind_lake) then
3490 snowdp(c) = snowdp(c) * h2osno(c) / h2osno_temp
3491 else
3492 snowdp(c) = h2osno(c)/snow_bd !Assume a constant snow bulk density = 250.
3493 end if
3494
3495 if (pergro) then
3496 if (abs(h2osno(c)) < 1.e-10_kind_lake) h2osno(c) = 0._kind_lake
3497 else
3498 h2osno(c) = max(h2osno(c), 0._kind_lake)
3499 endif
3500
3501 end if
3502
3503 qflx_snowcap_col(c) = qflx_snowcap(p)
3504
3505 end do
3506
3507
3508 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3509 ! Determine initial snow/no-snow filters (will be modified possibly by
3510 ! routines CombineSnowLayers and DivideSnowLayers below
3511
3512 call buildsnowfilter(lbc, ubc, num_shlakec, filter_shlakec,snl, & !i
3513 num_shlakesnowc, filter_shlakesnowc, num_shlakenosnowc, filter_shlakenosnowc) !o
3514
3515 ! Determine the change of snow mass and the snow water onto soil
3516
3517 call snowwater(lbc, ubc, num_shlakesnowc, filter_shlakesnowc, & !i
3518 num_shlakenosnowc, filter_shlakenosnowc, & !i
3519 snl,do_capsnow,qflx_snomelt,qflx_rain_grnd, & !i
3520 qflx_sub_snow,qflx_evap_grnd, & !i
3521 qflx_dew_snow,qflx_dew_grnd,dz,dtime, & !i
3522 h2osoi_ice,h2osoi_liq, & !i&o
3523 qflx_top_soil) !o
3524
3525
3526 ! Determine soil hydrology
3527 ! Here this consists only of making sure that soil is saturated even as it melts and 10%
3528 ! of pore space opens up. Conversely, if excess ice is melting and the liquid water exceeds the
3529 ! saturation value, then remove water.
3530
3531 do j = 1,nlevsoil
3532 !dir$ concurrent
3533 !cdir nodep
3534 do fc = 1, num_shlakec
3535 c = filter_shlakec(fc)
3536
3537 if (h2osoi_vol(c,j) < watsat(c,j)) then
3538 h2osoi_liq(c,j) = (watsat(c,j)*dz(c,j) - h2osoi_ice(c,j)/denice)*denh2o
3539 ! h2osoi_vol will be updated below, and this water addition will come from qflx_qrgwl
3540 else if (h2osoi_liq(c,j) > watsat(c,j)*denh2o*dz(c,j)) then
3541 h2osoi_liq(c,j) = watsat(c,j)*denh2o*dz(c,j)
3542 end if
3543
3544 end do
3545 end do
3546 !!!!!!!!!!
3547
3548 ! if (.not. is_perpetual()) then
3549 if (1==1) then
3550
3551 ! Natural compaction and metamorphosis.
3552
3553 call snowcompaction(lbc, ubc, num_shlakesnowc, filter_shlakesnowc, &!i
3554 snl,imelt,frac_iceold,t_soisno, &!i
3555 h2osoi_ice,h2osoi_liq,dtime, &!i
3556 dz) !&o
3557
3558 ! Combine thin snow elements
3559
3560 call combinesnowlayers(lbc, ubc, & !i
3561 num_shlakesnowc, filter_shlakesnowc, & !i&o
3562 snl,h2osno,snowdp,dz,zi, & !i&o
3563 t_soisno,h2osoi_ice,h2osoi_liq, & !i&o
3564 z) !o
3565
3566
3567 ! Divide thick snow elements
3568
3569 call dividesnowlayers(lbc, ubc, & !i
3570 num_shlakesnowc, filter_shlakesnowc, & !i&o
3571 snl,dz,zi,t_soisno, & !i&o
3572 h2osoi_ice,h2osoi_liq, & !i&o
3573 z) !o
3574
3575
3576 else
3577
3578 do fc = 1, num_shlakesnowc
3579 c = filter_shlakesnowc(fc)
3580 h2osno(c) = 0._kind_lake
3581 end do
3582 do j = -nlevsnow+1,0
3583 do fc = 1, num_shlakesnowc
3584 c = filter_shlakesnowc(fc)
3585 if (j >= snl(c)+1) then
3586 h2osno(c) = h2osno(c) + h2osoi_ice(c,j) + h2osoi_liq(c,j)
3587 end if
3588 end do
3589 end do
3590
3591 end if
3592
3593 ! Check for snow layers above lake with unfrozen top layer. Mechanically,
3594 ! the snow will fall into the lake and melt or turn to ice. If the top layer has
3595 ! sufficient heat to melt the snow without freezing, then that will be done.
3596 ! Otherwise, the top layer will undergo freezing, but only if the top layer will
3597 ! not freeze completely. Otherwise, let the snow layers persist and melt by diffusion.
3598 !dir$ concurrent
3599 !cdir nodep
3600 do fc = 1, num_shlakec
3601 c = filter_shlakec(fc)
3602
3603 if (t_lake(c,1) > tfrz .and. lake_icefrac(c,1) == 0._kind_lake .and. snl(c) < 0) then
3604 unfrozen(c) = .true.
3605 else
3606 unfrozen(c) = .false.
3607 end if
3608 end do
3609
3610 do j = -nlevsnow+1,0
3611 !dir$ concurrent
3612 !cdir nodep
3613 do fc = 1, num_shlakec
3614 c = filter_shlakec(fc)
3615
3616 if (unfrozen(c)) then
3617 if (j == -nlevsnow+1) then
3618 sumsnowice(c) = 0._kind_lake
3619 heatsum(c) = 0._kind_lake
3620 end if
3621 if (j >= snl(c)+1) then
3622 sumsnowice(c) = sumsnowice(c) + h2osoi_ice(c,j)
3623 heatsum(c) = heatsum(c) + h2osoi_ice(c,j)*cpice*(tfrz - t_soisno(c,j)) &
3624 + h2osoi_liq(c,j)*cpliq*(tfrz - t_soisno(c,j))
3625 end if
3626 end if
3627 end do
3628 end do
3629
3630 !dir$ concurrent
3631 !cdir nodep
3632 do fc = 1, num_shlakec
3633 c = filter_shlakec(fc)
3634
3635 if (unfrozen(c)) then
3636 heatsum(c) = heatsum(c) + sumsnowice(c)*hfus
3637 heatrem = (t_lake(c,1) - tfrz)*cpliq*denh2o*dz_lake(c,1) - heatsum(c)
3638
3639 if (heatrem + denh2o*dz_lake(c,1)*hfus > 0._kind_lake) then
3640 ! Remove snow and subtract the latent heat from the top layer.
3641 h2osno(c) = 0._kind_lake
3642 snl(c) = 0
3643 ! The rest of the bookkeeping for the removed snow will be done below.
3644 if (debug_print) then
3645 print *,'Snow layers removed above unfrozen lake for column, snowice:', &
3646 c, sumsnowice(c)
3647 endif
3648 if (heatrem > 0._kind_lake) then ! simply subtract the heat from the layer
3649 t_lake(c,1) = t_lake(c,1) - heatrem/(cpliq*denh2o*dz_lake(c,1))
3650 else !freeze part of the layer
3651 t_lake(c,1) = tfrz
3652 lake_icefrac(c,1) = -heatrem/(denh2o*dz_lake(c,1)*hfus)
3653 end if
3654 end if
3655 end if
3656 end do
3657 !!!!!!!!!!!!
3658
3659 ! Set snow age to zero if no snow
3660
3661 !dir$ concurrent
3662 !cdir nodep
3663 do fc = 1, num_shlakesnowc
3664 c = filter_shlakesnowc(fc)
3665 if (snl(c) == 0) then
3666 snowage(c) = 0._kind_lake
3667 end if
3668 end do
3669
3670 ! Set empty snow layers to zero
3671
3672 do j = -nlevsnow+1,0
3673 !dir$ concurrent
3674 !cdir nodep
3675 do fc = 1, num_shlakesnowc
3676 c = filter_shlakesnowc(fc)
3677 if (j <= snl(c) .and. snl(c) > -nlevsnow) then
3678 h2osoi_ice(c,j) = 0._kind_lake
3679 h2osoi_liq(c,j) = 0._kind_lake
3680 t_soisno(c,j) = 0._kind_lake
3681 dz(c,j) = 0._kind_lake
3682 z(c,j) = 0._kind_lake
3683 zi(c,j-1) = 0._kind_lake
3684 end if
3685 end do
3686 end do
3687
3688 ! Build new snow filter
3689
3690 call buildsnowfilter(lbc, ubc, num_shlakec, filter_shlakec, snl,& !i
3691 num_shlakesnowc, filter_shlakesnowc, num_shlakenosnowc, filter_shlakenosnowc) !o
3692
3693 ! Vertically average t_soisno and sum of h2osoi_liq and h2osoi_ice
3694 ! over all snow layers for history output
3695
3696 !dir$ concurrent
3697 !cdir nodep
3698 do fc = 1, num_shlakesnowc
3699 c = filter_shlakesnowc(fc)
3700 t_snow(c) = 0._kind_lake
3701 snowice(c) = 0._kind_lake
3702 snowliq(c) = 0._kind_lake
3703 end do
3704 !dir$ concurrent
3705 !cdir nodep
3706 do fc = 1, num_shlakenosnowc
3707 c = filter_shlakenosnowc(fc)
3708 t_snow(c) = spval
3709 snowice(c) = spval
3710 snowliq(c) = spval
3711 end do
3712
3713 do j = -nlevsnow+1, 0
3714 !dir$ concurrent
3715 !cdir nodep
3716 do fc = 1, num_shlakesnowc
3717 c = filter_shlakesnowc(fc)
3718 if (j >= snl(c)+1) then
3719 t_snow(c) = t_snow(c) + t_soisno(c,j)
3720 snowice(c) = snowice(c) + h2osoi_ice(c,j)
3721 snowliq(c) = snowliq(c) + h2osoi_liq(c,j)
3722 end if
3723 end do
3724 end do
3725
3726 ! Determine ending water balance and volumetric soil water
3727
3728 !dir$ concurrent
3729 !cdir nodep
3730 do fc = 1, num_shlakec
3731
3732 c = filter_shlakec(fc)
3733 if (snl(c) < 0) t_snow(c) = t_snow(c)/abs(snl(c))
3734 endwb(c) = h2osno(c)
3735 end do
3736
3737 do j = 1, nlevsoil
3738 !dir$ concurrent
3739 !cdir nodep
3740 do fc = 1, num_shlakec
3741 c = filter_shlakec(fc)
3742 endwb(c) = endwb(c) + h2osoi_ice(c,j) + h2osoi_liq(c,j)
3743 h2osoi_vol(c,j) = h2osoi_liq(c,j)/(dz(c,j)*denh2o) + h2osoi_ice(c,j)/(dz(c,j)*denice)
3744 end do
3745 end do
3746
3747 check_add_snow_water: if(lakedebug) then
3748 allocate(snow_water(lbc:ubc))
3749 ! Check to make sure snow water adds up correctly.
3750 do j = -nlevsnow+1,0
3751 !dir$ concurrent
3752 !cdir nodep
3753 do fc = 1, num_shlakec
3754 c = filter_shlakec(fc)
3755
3756 jtop = snl(c)+1
3757 if(j == jtop) snow_water(c) = 0._kind_lake
3758 if(j >= jtop) then
3759 snow_water(c) = snow_water(c) + h2osoi_ice(c,j) + h2osoi_liq(c,j)
3760 if(j == 0 .and. abs(snow_water(c)-h2osno(c))>1.e-7_kind_lake) then
3761 write(message,*)'h2osno does not equal sum of snow layers in ShalLakeHydrology:', &
3762 'column, h2osno, sum of snow layers =', c, h2osno(c), snow_water(c)
3763 ! errmsg=trim(message)
3764 ! errflg=1
3765 write(0,'(A)') trim(message)
3766 end if
3767 end if
3768 end do
3769 end do
3770 deallocate(snow_water)
3771 end if check_add_snow_water
3772
3773 !!!!!!!!!!!!!
3774 ! Do history variables and set special landunit runoff (adapted from end of HydrologyLake)
3775 !dir$ concurrent
3776 !cdir nodep
3777 do fp = 1,num_shlakep
3778 p = filter_shlakep(fp)
3779 c = pcolumn(p)
3780 g = pgridcell(p)
3781
3782 qflx_infl(c) = 0._kind_lake
3783 qflx_surf(c) = 0._kind_lake
3784 qflx_drain(c) = 0._kind_lake
3785 rootr_column(c,:) = spval
3786 soilalpha(c) = spval
3787 zwt(c) = spval
3788 fcov(c) = spval
3789 qcharge(c) = spval
3790 ! h2osoi_vol(c,:) = spval
3791
3792 ! Insure water balance using qflx_qrgwl
3793 qflx_qrgwl(c) = forc_rain(g) + forc_snow(g) - qflx_evap_tot(p) - (endwb(c)-begwb(c))/dtime
3794 if (debug_print) then
3795 print *,'c, rain, snow, evap, endwb, begwb, qflx_qrgwl:', &
3796 c, forc_rain(g), forc_snow(g), qflx_evap_tot(p), endwb(c), begwb(c), qflx_qrgwl(c)
3797 endif
3798
3799 ! The pft average must be done here for output to history tape
3800 qflx_evap_tot_col(c) = qflx_evap_tot(p)
3801 end do
3802
3803 end subroutine shallakehydrology
3804
3805! DESCRIPTION:
3808 subroutine qsat (T, p, es, esdT, qs, qsdT)
3809 !
3810 ! Reference: Polynomial approximations from:
3811 ! Piotr J. Flatau, et al.,1992: Polynomial fits to saturation
3812 ! vapor pressure. Journal of Applied Meteorology, 31, 1507-1513.
3813 !
3814 ! USES:
3815 !
3816 ! ARGUMENTS:
3817 implicit none
3818 real(kind_lake), intent(in) :: t
3819 real(kind_lake), intent(in) :: p
3820 real(kind_lake), intent(out) :: es
3821 real(kind_lake), intent(out) :: esdt
3822 real(kind_lake), intent(out) :: qs
3823 real(kind_lake), intent(out) :: qsdt
3824 !
3825 ! !CALLED FROM:
3826 ! subroutine Biogeophysics1 in module Biogeophysics1Mod
3827 ! subroutine BiogeophysicsLake in module BiogeophysicsLakeMod
3828 ! subroutine CanopyFluxesMod CanopyFluxesMod
3829 !
3830 ! !REVISION HISTORY:
3831 ! 15 September 1999: Yongjiu Dai; Initial code
3832 ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision
3833 !
3834 !EOP
3835 !
3836 ! !LOCAL VARIABLES:
3837 !
3838 real(kind_lake) :: t_limit
3839 real(kind_lake) :: td,vp,vp1,vp2
3840 !
3841 ! For water vapor (temperature range 0C-100C)
3842 !
3843 real(kind_lake), parameter :: a0 = 6.11213476
3844 real(kind_lake), parameter :: a1 = 0.444007856
3845 real(kind_lake), parameter :: a2 = 0.143064234e-01
3846 real(kind_lake), parameter :: a3 = 0.264461437e-03
3847 real(kind_lake), parameter :: a4 = 0.305903558e-05
3848 real(kind_lake), parameter :: a5 = 0.196237241e-07
3849 real(kind_lake), parameter :: a6 = 0.892344772e-10
3850 real(kind_lake), parameter :: a7 = -0.373208410e-12
3851 real(kind_lake), parameter :: a8 = 0.209339997e-15
3852 !
3853 ! For derivative:water vapor
3854 !
3855 real(kind_lake), parameter :: b0 = 0.444017302
3856 real(kind_lake), parameter :: b1 = 0.286064092e-01
3857 real(kind_lake), parameter :: b2 = 0.794683137e-03
3858 real(kind_lake), parameter :: b3 = 0.121211669e-04
3859 real(kind_lake), parameter :: b4 = 0.103354611e-06
3860 real(kind_lake), parameter :: b5 = 0.404125005e-09
3861 real(kind_lake), parameter :: b6 = -0.788037859e-12
3862 real(kind_lake), parameter :: b7 = -0.114596802e-13
3863 real(kind_lake), parameter :: b8 = 0.381294516e-16
3864 !
3865 ! For ice (temperature range -75C-0C)
3866 !
3867 real(kind_lake), parameter :: c0 = 6.11123516
3868 real(kind_lake), parameter :: c1 = 0.503109514
3869 real(kind_lake), parameter :: c2 = 0.188369801e-01
3870 real(kind_lake), parameter :: c3 = 0.420547422e-03
3871 real(kind_lake), parameter :: c4 = 0.614396778e-05
3872 real(kind_lake), parameter :: c5 = 0.602780717e-07
3873 real(kind_lake), parameter :: c6 = 0.387940929e-09
3874 real(kind_lake), parameter :: c7 = 0.149436277e-11
3875 real(kind_lake), parameter :: c8 = 0.262655803e-14
3876 !
3877 ! For derivative:ice
3878 !
3879 real(kind_lake), parameter :: d0 = 0.503277922
3880 real(kind_lake), parameter :: d1 = 0.377289173e-01
3881 real(kind_lake), parameter :: d2 = 0.126801703e-02
3882 real(kind_lake), parameter :: d3 = 0.249468427e-04
3883 real(kind_lake), parameter :: d4 = 0.313703411e-06
3884 real(kind_lake), parameter :: d5 = 0.257180651e-08
3885 real(kind_lake), parameter :: d6 = 0.133268878e-10
3886 real(kind_lake), parameter :: d7 = 0.394116744e-13
3887 real(kind_lake), parameter :: d8 = 0.498070196e-16
3888 !-----------------------------------------------------------------------
3889
3890 t_limit = t - tfrz
3891 if (t_limit > 100.0) t_limit=100.0
3892 if (t_limit < -75.0) t_limit=-75.0
3893
3894 td = t_limit
3895 if (td >= 0.0) then
3896 es = a0 + td*(a1 + td*(a2 + td*(a3 + td*(a4 &
3897 + td*(a5 + td*(a6 + td*(a7 + td*a8)))))))
3898 esdt = b0 + td*(b1 + td*(b2 + td*(b3 + td*(b4 &
3899 + td*(b5 + td*(b6 + td*(b7 + td*b8)))))))
3900 else
3901 es = c0 + td*(c1 + td*(c2 + td*(c3 + td*(c4 &
3902 + td*(c5 + td*(c6 + td*(c7 + td*c8)))))))
3903 esdt = d0 + td*(d1 + td*(d2 + td*(d3 + td*(d4 &
3904 + td*(d5 + td*(d6 + td*(d7 + td*d8)))))))
3905 endif
3906
3907 es = es * 100. ! pa
3908 esdt = esdt * 100. ! pa/K
3909
3910 vp = 1.0 / (p - one_minus_con_eps*es)
3911 vp1 = 0.622 * vp
3912 vp2 = vp1 * vp
3913
3914 qs = es * vp1 ! kg/kg
3915 qsdt = esdt * vp2 * p ! 1 / K
3916
3917 end subroutine qsat
3918
3919
3920 subroutine tridiagonal (lbc, ubc, lbj, ubj, jtop, numf, filter, &
3921 a, b, c, r, u)
3922 !
3923 ! DESCRIPTION:
3924
3925 !
3926 ! ARGUMENTS:
3927 implicit none
3928 integer , intent(in) :: lbc, ubc
3929 integer , intent(in) :: lbj, ubj
3930 integer , intent(in) :: jtop(lbc:ubc)
3931 integer , intent(in) :: numf
3932 integer , intent(in) :: filter(1:numf)
3933 real(kind_lake), intent(in) :: a(lbc:ubc, lbj:ubj)
3934 real(kind_lake), intent(in) :: b(lbc:ubc, lbj:ubj)
3935 real(kind_lake), intent(in) :: c(lbc:ubc, lbj:ubj)
3936 real(kind_lake), intent(in) :: r(lbc:ubc, lbj:ubj)
3937 real(kind_lake), intent(inout) :: u(lbc:ubc, lbj:ubj)
3938 !
3939 ! !CALLED FROM:
3940 ! subroutine BiogeophysicsLake in module BiogeophysicsLakeMod
3941 ! subroutine SoilTemperature in module SoilTemperatureMod
3942 ! subroutine SoilWater in module HydrologyMod
3943 !
3944 ! !REVISION HISTORY:
3945 ! 15 September 1999: Yongjiu Dai; Initial code
3946 ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision
3947 ! 1 July 2003: Mariana Vertenstein; modified for vectorization
3948 !
3949 !EOP
3950 !
3951 ! !OTHER LOCAL VARIABLES:
3952 !
3953 integer :: j,ci,fc !indices
3954 real(kind_lake) :: gam(lbc:ubc,lbj:ubj) !temporary
3955 real(kind_lake) :: bet(lbc:ubc) !temporary
3956 !-----------------------------------------------------------------------
3957
3958 ! Solve the matrix
3959
3960 !dir$ concurrent
3961 !cdir nodep
3962 do fc = 1,numf
3963 ci = filter(fc)
3964 bet(ci) = b(ci,jtop(ci))
3965 end do
3966
3967 do j = lbj, ubj
3968 !dir$ prefervector
3969 !dir$ concurrent
3970 !cdir nodep
3971 do fc = 1,numf
3972 ci = filter(fc)
3973 if (j >= jtop(ci)) then
3974 if (j == jtop(ci)) then
3975 u(ci,j) = r(ci,j) / bet(ci)
3976 else
3977 gam(ci,j) = c(ci,j-1) / bet(ci)
3978 bet(ci) = b(ci,j) - a(ci,j) * gam(ci,j)
3979 u(ci,j) = (r(ci,j) - a(ci,j)*u(ci,j-1)) / bet(ci)
3980 end if
3981 end if
3982 end do
3983 end do
3984
3985 !Cray X1 unroll directive used here as work-around for compiler issue 2003/10/20
3986 !dir$ unroll 0
3987 do j = ubj-1,lbj,-1
3988 !dir$ prefervector
3989 !dir$ concurrent
3990 !cdir nodep
3991 do fc = 1,numf
3992 ci = filter(fc)
3993 if (j >= jtop(ci)) then
3994 u(ci,j) = u(ci,j) - gam(ci,j+1) * u(ci,j+1)
3995 end if
3996 end do
3997 end do
3998
3999 end subroutine tridiagonal
4000
4001
4002 ! DESCRIPTION:
4013 subroutine snowwater(lbc, ubc, num_snowc, filter_snowc, & !i
4014 num_nosnowc, filter_nosnowc, & !i
4015 snl,do_capsnow,qflx_snomelt,qflx_rain_grnd, & !i
4016 qflx_sub_snow,qflx_evap_grnd, & !i
4017 qflx_dew_snow,qflx_dew_grnd,dz,dtime, & !i
4018 h2osoi_ice,h2osoi_liq, & !i&o
4019 qflx_top_soil) !o
4020 !===============================================================================
4021 ! !REVISION HISTORY:
4022 ! 15 September 1999: Yongjiu Dai; Initial code
4023 ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision
4024 ! 15 November 2000: Mariana Vertenstein
4025 ! 2/26/02, Peter Thornton: Migrated to new data structures.
4026 !=============================================================================
4027 ! !USES:
4028 ! use clmtype
4029
4030 implicit none
4031
4032 !in:
4033 integer, intent(in) :: lbc, ubc
4034 integer, intent(in) :: num_snowc
4035 integer, intent(in) :: filter_snowc(ubc-lbc+1)
4036 integer, intent(in) :: num_nosnowc
4037 integer, intent(in) :: filter_nosnowc(ubc-lbc+1)
4038
4039 integer , intent(in) :: snl(1)
4040 logical , intent(in) :: do_capsnow(1)
4041 real(kind_lake), intent(in) :: dtime
4042 real(kind_lake), intent(in) :: qflx_snomelt(1)
4043 real(kind_lake), intent(in) :: qflx_rain_grnd(1)
4044 real(kind_lake), intent(in) :: qflx_sub_snow(1)
4045 real(kind_lake), intent(in) :: qflx_evap_grnd(1)
4046 real(kind_lake), intent(in) :: qflx_dew_snow(1)
4047 real(kind_lake), intent(in) :: qflx_dew_grnd(1)
4048 real(kind_lake), intent(in) :: dz(1,-nlevsnow+1:nlevsoil)
4049
4050
4051 !inout:
4052
4053 real(kind_lake), intent(inout) :: h2osoi_ice(1,-nlevsnow+1:nlevsoil)
4054 real(kind_lake), intent(inout) :: h2osoi_liq(1,-nlevsnow+1:nlevsoil)
4055
4056 !out:
4057
4058 real(kind_lake), intent(out) :: qflx_top_soil(1)
4059
4060
4061 ! OTHER LOCAL VARIABLES:
4062
4063 integer :: c, j, fc !do loop/array indices
4064 real(kind_lake) :: qin(lbc:ubc) !water flow into the elmement (mm/s)
4065 real(kind_lake) :: qout(lbc:ubc) !water flow out of the elmement (mm/s)
4066 real(kind_lake) :: wgdif !ice mass after minus sublimation
4067 real(kind_lake) :: vol_liq(lbc:ubc,-nlevsnow+1:0) !partial volume of liquid water in layer
4068 real(kind_lake) :: vol_ice(lbc:ubc,-nlevsnow+1:0) !partial volume of ice lens in layer
4069 real(kind_lake) :: eff_porosity(lbc:ubc,-nlevsnow+1:0) !effective porosity = porosity - vol_ice
4070 !-----------------------------------------------------------------------
4071 ! Renew the mass of ice lens (h2osoi_ice) and liquid (h2osoi_liq) in the
4072 ! surface snow layer resulting from sublimation (frost) / evaporation (condense)
4073
4074 !dir$ concurrent
4075 !cdir nodep
4076 do fc = 1,num_snowc
4077 c = filter_snowc(fc)
4078 if (do_capsnow(c)) then
4079 wgdif = h2osoi_ice(c,snl(c)+1) - qflx_sub_snow(c)*dtime
4080 h2osoi_ice(c,snl(c)+1) = wgdif
4081 if (wgdif < 0.) then
4082 h2osoi_ice(c,snl(c)+1) = 0.
4083 h2osoi_liq(c,snl(c)+1) = h2osoi_liq(c,snl(c)+1) + wgdif
4084 end if
4085 h2osoi_liq(c,snl(c)+1) = h2osoi_liq(c,snl(c)+1) - qflx_evap_grnd(c) * dtime
4086 else
4087 wgdif = h2osoi_ice(c,snl(c)+1) + (qflx_dew_snow(c) - qflx_sub_snow(c)) * dtime
4088 h2osoi_ice(c,snl(c)+1) = wgdif
4089 if (wgdif < 0.) then
4090 h2osoi_ice(c,snl(c)+1) = 0.
4091 h2osoi_liq(c,snl(c)+1) = h2osoi_liq(c,snl(c)+1) + wgdif
4092 end if
4093 h2osoi_liq(c,snl(c)+1) = h2osoi_liq(c,snl(c)+1) + &
4094 (qflx_rain_grnd(c) + qflx_dew_grnd(c) - qflx_evap_grnd(c)) * dtime
4095 end if
4096 h2osoi_liq(c,snl(c)+1) = max(0._kind_lake, h2osoi_liq(c,snl(c)+1))
4097 end do
4098
4099 ! Porosity and partial volume
4100
4101 do j = -nlevsnow+1, 0
4102 !dir$ concurrent
4103 !cdir nodep
4104 do fc = 1, num_snowc
4105 c = filter_snowc(fc)
4106 if (j >= snl(c)+1) then
4107 vol_ice(c,j) = min(1._kind_lake, h2osoi_ice(c,j)/(dz(c,j)*denice))
4108 eff_porosity(c,j) = 1. - vol_ice(c,j)
4109 vol_liq(c,j) = min(eff_porosity(c,j),h2osoi_liq(c,j)/(dz(c,j)*denh2o))
4110 end if
4111 end do
4112 end do
4113
4114 ! Capillary forces within snow are usually two or more orders of magnitude
4115 ! less than those of gravity. Only gravity terms are considered.
4116 ! the genernal expression for water flow is "K * ss**3", however,
4117 ! no effective parameterization for "K". Thus, a very simple consideration
4118 ! (not physically based) is introduced:
4119 ! when the liquid water of layer exceeds the layer's holding
4120 ! capacity, the excess meltwater adds to the underlying neighbor layer.
4121
4122 qin(:) = 0._kind_lake
4123
4124 do j = -nlevsnow+1, 0
4125 !dir$ concurrent
4126 !cdir nodep
4127 do fc = 1, num_snowc
4128 c = filter_snowc(fc)
4129 if (j >= snl(c)+1) then
4130 h2osoi_liq(c,j) = h2osoi_liq(c,j) + qin(c)
4131 if (j <= -1) then
4132 ! No runoff over snow surface, just ponding on surface
4133 if (eff_porosity(c,j) < wimp .OR. eff_porosity(c,j+1) < wimp) then
4134 qout(c) = 0._kind_lake
4135 else
4136 qout(c) = max(0._kind_lake,(vol_liq(c,j)-ssi*eff_porosity(c,j))*dz(c,j))
4137 qout(c) = min(qout(c),(1.-vol_ice(c,j+1)-vol_liq(c,j+1))*dz(c,j+1))
4138 end if
4139 else
4140 qout(c) = max(0._kind_lake,(vol_liq(c,j) - ssi*eff_porosity(c,j))*dz(c,j))
4141 end if
4142 qout(c) = qout(c)*1000.
4143 h2osoi_liq(c,j) = h2osoi_liq(c,j) - qout(c)
4144 qin(c) = qout(c)
4145 end if
4146 end do
4147 end do
4148
4149 !dir$ concurrent
4150 !cdir nodep
4151 do fc = 1, num_snowc
4152 c = filter_snowc(fc)
4153 ! Qout from snow bottom
4154 qflx_top_soil(c) = qout(c) / dtime
4155 end do
4156
4157 !dir$ concurrent
4158 !cdir nodep
4159 do fc = 1, num_nosnowc
4160 c = filter_nosnowc(fc)
4161 qflx_top_soil(c) = qflx_rain_grnd(c) + qflx_snomelt(c)
4162 end do
4163
4164 end subroutine snowwater
4165
4173 subroutine snowcompaction(lbc, ubc, num_snowc, filter_snowc, &!i
4174 snl,imelt,frac_iceold,t_soisno, &!i
4175 h2osoi_ice,h2osoi_liq,dtime, &!i
4176 dz) !i&o
4177
4178
4179 !================================================================================
4180 ! CALLED FROM:
4181 ! subroutine Hydrology2 in module Hydrology2Mod
4182 !
4183 ! REVISION HISTORY:
4184 ! 15 September 1999: Yongjiu Dai; Initial code
4185 ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision
4186 ! 2/28/02, Peter Thornton: Migrated to new data structures
4187 !==============================================================================
4188 ! USES:
4189 ! use clmtype
4190 !
4191 ! !ARGUMENTS:
4192 implicit none
4193
4194 !in:
4195 integer, intent(in) :: lbc, ubc
4196 integer, intent(in) :: num_snowc
4197 integer, intent(in) :: filter_snowc(ubc-lbc+1)
4198 integer, intent(in) :: snl(1)
4199 integer, intent(in) :: imelt(1,-nlevsnow+1:nlevsoil)
4200 real(kind_lake), intent(in) :: dtime
4201 real(kind_lake), intent(in) :: frac_iceold(1,-nlevsnow+1:nlevsoil)
4202 real(kind_lake), intent(in) :: t_soisno(1,-nlevsnow+1:nlevsoil)
4203 real(kind_lake), intent(in) :: h2osoi_ice(1,-nlevsnow+1:nlevsoil)
4204 real(kind_lake), intent(in) :: h2osoi_liq(1,-nlevsnow+1:nlevsoil)
4205
4206 !inout:
4207
4208 real(kind_lake), intent(inout) :: dz(1,-nlevsnow+1:nlevsoil)
4209
4210 ! OTHER LOCAL VARIABLES:
4211
4212 integer :: j, c, fc ! indices
4213 real(kind_lake), parameter :: c2 = 23.e-3 ! [m3/kg]
4214 real(kind_lake), parameter :: c3 = 2.777e-6 ! [1/s]
4215 real(kind_lake), parameter :: c4 = 0.04 ! [1/K]
4216 real(kind_lake), parameter :: c5 = 2.0 !
4217 real(kind_lake), parameter :: dm = 100.0 ! Upper Limit on Destructive Metamorphism Compaction [kg/m3]
4218 real(kind_lake), parameter :: eta0 = 9.e+5 ! The Viscosity Coefficient Eta0 [kg-s/m2]
4219 real(kind_lake) :: burden(lbc:ubc) ! pressure of overlying snow [kg/m2]
4220 real(kind_lake) :: ddz1 ! Rate of settling of snowpack due to destructive metamorphism.
4221 real(kind_lake) :: ddz2 ! Rate of compaction of snowpack due to overburden.
4222 real(kind_lake) :: ddz3 ! Rate of compaction of snowpack due to melt [1/s]
4223 real(kind_lake) :: dexpf ! expf=exp(-c4*(273.15-t_soisno)).
4224 real(kind_lake) :: fi ! Fraction of ice relative to the total water content at current time step
4225 real(kind_lake) :: td ! t_soisno - tfrz [K]
4226 real(kind_lake) :: pdzdtc ! Nodal rate of change in fractional-thickness due to compaction [fraction/s]
4227 real(kind_lake) :: void ! void (1 - vol_ice - vol_liq)
4228 real(kind_lake) :: wx ! water mass (ice+liquid) [kg/m2]
4229 real(kind_lake) :: bi ! partial density of ice [kg/m3]
4230
4231 !-----------------------------------------------------------------------
4232
4233
4234 ! Begin calculation - note that the following column loops are only invoked if snl(c) < 0
4235
4236 burden(:) = 0._kind_lake
4237
4238 do j = -nlevsnow+1, 0
4239 !dir$ concurrent
4240 !cdir nodep
4241 do fc = 1, num_snowc
4242 c = filter_snowc(fc)
4243 if (j >= snl(c)+1) then
4244
4245 wx = h2osoi_ice(c,j) + h2osoi_liq(c,j)
4246 void = 1. - (h2osoi_ice(c,j)/denice + h2osoi_liq(c,j)/denh2o) / dz(c,j)
4247
4248 ! Allow compaction only for non-saturated node and higher ice lens node.
4249 if (void > 0.001 .and. h2osoi_ice(c,j) > .1) then
4250 bi = h2osoi_ice(c,j) / dz(c,j)
4251 fi = h2osoi_ice(c,j) / wx
4252 td = tfrz-t_soisno(c,j)
4253 dexpf = exp(-c4*td)
4254
4255 ! Settling as a result of destructive metamorphism
4256
4257 ddz1 = -c3*dexpf
4258 if (bi > dm) ddz1 = ddz1*exp(-46.0e-3*(bi-dm))
4259
4260 ! Liquid water term
4261
4262 if (h2osoi_liq(c,j) > 0.01*dz(c,j)) ddz1=ddz1*c5
4263
4264 ! Compaction due to overburden
4265
4266 ddz2 = -burden(c)*exp(-0.08*td - c2*bi)/eta0
4267
4268 ! Compaction occurring during melt
4269
4270 if (imelt(c,j) == 1) then
4271 ddz3 = - 1./dtime * max(0._kind_lake,(frac_iceold(c,j) - fi)/frac_iceold(c,j))
4272 else
4273 ddz3 = 0._kind_lake
4274 end if
4275
4276 ! Time rate of fractional change in dz (units of s-1)
4277
4278 pdzdtc = ddz1 + ddz2 + ddz3
4279
4280 ! The change in dz due to compaction
4281
4282 dz(c,j) = dz(c,j) * (1.+pdzdtc*dtime)
4283 end if
4284
4285 ! Pressure of overlying snow
4286
4287 burden(c) = burden(c) + wx
4288
4289 end if
4290 end do
4291 end do
4292
4293 end subroutine snowcompaction
4294
4298 subroutine combinesnowlayers(lbc, ubc, & !i
4299 num_snowc, filter_snowc, & !i&o
4300 snl,h2osno,snowdp,dz,zi, & !i&o
4301 t_soisno,h2osoi_ice,h2osoi_liq, & !i&o
4302 z) !o
4303 !==========================================================================
4304 ! DESCRIPTION:
4305 ! Combine snow layers that are less than a minimum thickness or mass
4306 ! If the snow element thickness or mass is less than a prescribed minimum,
4307 ! then it is combined with a neighboring element. The subroutine
4308 ! clm\_combo.f90 then executes the combination of mass and energy.
4309 ! CALLED FROM:
4310 ! subroutine Hydrology2 in module Hydrology2Mod
4311 !
4312 ! REVISION HISTORY:
4313 ! 15 September 1999: Yongjiu Dai; Initial code
4314 ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision
4315 ! 2/28/02, Peter Thornton: Migrated to new data structures.
4316 !=========================================================================
4317 ! !USES:
4318 ! use clmtype
4319 !
4320 ! !ARGUMENTS:
4321 implicit none
4322 !in:
4323 integer, intent(in) :: lbc, ubc
4324 ! integer, intent(in) :: clandunit(1) !landunit index for each column
4325 ! integer, intent(in) :: ityplun(1) !landunit type
4326
4327 !inout:
4328 integer, intent(inout) :: num_snowc
4329 integer, intent(inout) :: filter_snowc(ubc-lbc+1)
4330 integer , intent(inout) :: snl(1)
4331 real(kind_lake), intent(inout) :: h2osno(1)
4332 real(kind_lake), intent(inout) :: snowdp(1)
4333 real(kind_lake), intent(inout) :: dz(1,-nlevsnow+1:nlevsoil)
4334 real(kind_lake), intent(inout) :: zi(1,-nlevsnow+0:nlevsoil)
4335 real(kind_lake), intent(inout) :: t_soisno(1,-nlevsnow+1:nlevsoil)
4336 real(kind_lake), intent(inout) :: h2osoi_ice(1,-nlevsnow+1:nlevsoil)
4337 real(kind_lake), intent(inout) :: h2osoi_liq(1,-nlevsnow+1:nlevsoil)
4338
4339 !out:
4340
4341 real(kind_lake), intent(out) :: z(1,-nlevsnow+1:nlevsoil)
4342 !
4343 !EOP
4344 !
4345 ! !OTHER LOCAL VARIABLES:
4346 !
4347 integer :: c, fc ! column indices
4348 integer :: i,k ! loop indices
4349 integer :: j,l ! node indices
4350 integer :: msn_old(lbc:ubc) ! number of top snow layer
4351 integer :: mssi(lbc:ubc) ! node index
4352 integer :: neibor ! adjacent node selected for combination
4353 real(kind_lake):: zwice(lbc:ubc) ! total ice mass in snow
4354 real(kind_lake):: zwliq (lbc:ubc) ! total liquid water in snow
4355 real(kind_lake), parameter :: dzmin(5) = & ! minimum of top snow layer
4356 (/0.010, 0.015, 0.025, 0.055, 0.115/)
4357 !-----------------------------------------------------------------------
4358
4359 ! Check the mass of ice lens of snow, when the total is less than a small value,
4360 ! combine it with the underlying neighbor.
4361
4362 !dir$ concurrent
4363 !cdir nodep
4364 do fc = 1, num_snowc
4365 c = filter_snowc(fc)
4366 msn_old(c) = snl(c)
4367 end do
4368
4369 ! The following loop is NOT VECTORIZED
4370
4371 do fc = 1, num_snowc
4372 c = filter_snowc(fc)
4373 ! l = clandunit(c)
4374 do j = msn_old(c)+1,0
4375 if (h2osoi_ice(c,j) <= .1) then
4376 ! if (ityplun(l) == istsoil) then
4377 ! h2osoi_liq(c,j+1) = h2osoi_liq(c,j+1) + h2osoi_liq(c,j)
4378 ! h2osoi_ice(c,j+1) = h2osoi_ice(c,j+1) + h2osoi_ice(c,j)
4379 ! else if (ityplun(l) /= istsoil .and. j /= 0) then
4380 h2osoi_liq(c,j+1) = h2osoi_liq(c,j+1) + h2osoi_liq(c,j)
4381 h2osoi_ice(c,j+1) = h2osoi_ice(c,j+1) + h2osoi_ice(c,j)
4382 ! end if
4383
4384 ! shift all elements above this down one.
4385 if (j > snl(c)+1 .and. snl(c) < -1) then
4386 do i = j, snl(c)+2, -1
4387 t_soisno(c,i) = t_soisno(c,i-1)
4388 h2osoi_liq(c,i) = h2osoi_liq(c,i-1)
4389 h2osoi_ice(c,i) = h2osoi_ice(c,i-1)
4390 dz(c,i) = dz(c,i-1)
4391 end do
4392 end if
4393 snl(c) = snl(c) + 1
4394 end if
4395 end do
4396 end do
4397
4398 !dir$ concurrent
4399 !cdir nodep
4400 do fc = 1, num_snowc
4401 c = filter_snowc(fc)
4402 h2osno(c) = 0._kind_lake
4403 snowdp(c) = 0._kind_lake
4404 zwice(c) = 0._kind_lake
4405 zwliq(c) = 0._kind_lake
4406 end do
4407
4408 do j = -nlevsnow+1,0
4409 !dir$ concurrent
4410 !cdir nodep
4411 do fc = 1, num_snowc
4412 c = filter_snowc(fc)
4413 if (j >= snl(c)+1) then
4414 h2osno(c) = h2osno(c) + h2osoi_ice(c,j) + h2osoi_liq(c,j)
4415 snowdp(c) = snowdp(c) + dz(c,j)
4416 zwice(c) = zwice(c) + h2osoi_ice(c,j)
4417 zwliq(c) = zwliq(c) + h2osoi_liq(c,j)
4418 end if
4419 end do
4420 end do
4421
4422 ! Check the snow depth - all snow gone
4423 ! The liquid water assumes ponding on soil surface.
4424
4425 !dir$ concurrent
4426 !cdir nodep
4427 do fc = 1, num_snowc
4428 c = filter_snowc(fc)
4429 ! l = clandunit(c)
4430 if (snowdp(c) < 0.01 .and. snowdp(c) > 0.) then
4431 snl(c) = 0
4432 h2osno(c) = zwice(c)
4433 if (h2osno(c) <= 0.) snowdp(c) = 0._kind_lake
4434 ! if (ityplun(l) == istsoil) h2osoi_liq(c,1) = h2osoi_liq(c,1) + zwliq(c) !change by guhp
4435 end if
4436 end do
4437
4438 ! Check the snow depth - snow layers combined
4439 ! The following loop IS NOT VECTORIZED
4440
4441 do fc = 1, num_snowc
4442 c = filter_snowc(fc)
4443
4444 ! Two or more layers
4445
4446 if (snl(c) < -1) then
4447
4448 msn_old(c) = snl(c)
4449 mssi(c) = 1
4450
4451 do i = msn_old(c)+1,0
4452 if (dz(c,i) < dzmin(mssi(c))) then
4453
4454 if (i == snl(c)+1) then
4455 ! If top node is removed, combine with bottom neighbor.
4456 neibor = i + 1
4457 else if (i == 0) then
4458 ! If the bottom neighbor is not snow, combine with the top neighbor.
4459 neibor = i - 1
4460 else
4461 ! If none of the above special cases apply, combine with the thinnest neighbor
4462 neibor = i + 1
4463 if ((dz(c,i-1)+dz(c,i)) < (dz(c,i+1)+dz(c,i))) neibor = i-1
4464 end if
4465
4466 ! Node l and j are combined and stored as node j.
4467 if (neibor > i) then
4468 j = neibor
4469 l = i
4470 else
4471 j = i
4472 l = neibor
4473 end if
4474
4475 call combo (dz(c,j), h2osoi_liq(c,j), h2osoi_ice(c,j), &
4476 t_soisno(c,j), dz(c,l), h2osoi_liq(c,l), h2osoi_ice(c,l), t_soisno(c,l) )
4477
4478 ! Now shift all elements above this down one.
4479 if (j-1 > snl(c)+1) then
4480 do k = j-1, snl(c)+2, -1
4481 t_soisno(c,k) = t_soisno(c,k-1)
4482 h2osoi_ice(c,k) = h2osoi_ice(c,k-1)
4483 h2osoi_liq(c,k) = h2osoi_liq(c,k-1)
4484 dz(c,k) = dz(c,k-1)
4485 end do
4486 end if
4487
4488 ! Decrease the number of snow layers
4489 snl(c) = snl(c) + 1
4490 if (snl(c) >= -1) EXIT
4491
4492 else
4493
4494 ! The layer thickness is greater than the prescribed minimum value
4495 mssi(c) = mssi(c) + 1
4496
4497 end if
4498 end do
4499
4500 end if
4501
4502 end do
4503
4504 ! Reset the node depth and the depth of layer interface
4505
4506 do j = 0, -nlevsnow+1, -1
4507 !dir$ concurrent
4508 !cdir nodep
4509 do fc = 1, num_snowc
4510 c = filter_snowc(fc)
4511 if (j >= snl(c) + 1) then
4512 z(c,j) = zi(c,j) - 0.5*dz(c,j)
4513 zi(c,j-1) = zi(c,j) - dz(c,j)
4514 end if
4515 end do
4516 end do
4517
4518 end subroutine combinesnowlayers
4519
4520! DESCRIPTION:
4522 subroutine dividesnowlayers(lbc, ubc, & !i
4523 num_snowc, filter_snowc, & !i&o
4524 snl,dz,zi,t_soisno, & !i&o
4525 h2osoi_ice,h2osoi_liq, & !i&o
4526 z) !o
4527
4528
4529 !============================================================================
4530 ! !CALLED FROM:
4531 ! subroutine Hydrology2 in module Hydrology2Mod
4532 !
4533 ! !REVISION HISTORY:
4534 ! 15 September 1999: Yongjiu Dai; Initial code
4535 ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision
4536 ! 2/28/02, Peter Thornton: Migrated to new data structures.
4537 !============================================================================
4538 ! !USES:
4539 ! use clmtype
4540 !
4541 ! !ARGUMENTS:
4542 implicit none
4543
4544 !in:
4545 integer, intent(in) :: lbc, ubc
4546
4547 !inout:
4548
4549 integer, intent(inout) :: num_snowc
4550 integer, intent(inout) :: filter_snowc(ubc-lbc+1)
4551 integer , intent(inout) :: snl(1)
4552 real(kind_lake), intent(inout) :: dz(1,-nlevsnow+1:nlevsoil)
4553 real(kind_lake), intent(inout) :: zi(1,-nlevsnow+0:nlevsoil)
4554 real(kind_lake), intent(inout) :: t_soisno(1,-nlevsnow+1:nlevsoil)
4555 real(kind_lake), intent(inout) :: h2osoi_ice(1,-nlevsnow+1:nlevsoil)
4556 real(kind_lake), intent(inout) :: h2osoi_liq(1,-nlevsnow+1:nlevsoil)
4557
4558 !out:
4559
4560 real(kind_lake), intent(out) :: z(1,-nlevsnow+1:nlevsoil)
4561
4562
4563
4564 ! OTHER LOCAL VARIABLES:
4565
4566 integer :: j, c, fc ! indices
4567 real(kind_lake) :: drr ! thickness of the combined [m]
4568 integer :: msno ! number of snow layer 1 (top) to msno (bottom)
4569 real(kind_lake) :: dzsno(lbc:ubc,nlevsnow) ! Snow layer thickness [m]
4570 real(kind_lake) :: swice(lbc:ubc,nlevsnow) ! Partial volume of ice [m3/m3]
4571 real(kind_lake) :: swliq(lbc:ubc,nlevsnow) ! Partial volume of liquid water [m3/m3]
4572 real(kind_lake) :: tsno(lbc:ubc ,nlevsnow) ! Nodel temperature [K]
4573 real(kind_lake) :: zwice ! temporary
4574 real(kind_lake) :: zwliq ! temporary
4575 real(kind_lake) :: propor ! temporary
4576 !-----------------------------------------------------------------------
4577
4578 ! Begin calculation - note that the following column loops are only invoked
4579 ! for snow-covered columns
4580
4581 do j = 1,nlevsnow
4582 !dir$ concurrent
4583 !cdir nodep
4584 do fc = 1, num_snowc
4585 c = filter_snowc(fc)
4586 if (j <= abs(snl(c))) then
4587 dzsno(c,j) = dz(c,j+snl(c))
4588 swice(c,j) = h2osoi_ice(c,j+snl(c))
4589 swliq(c,j) = h2osoi_liq(c,j+snl(c))
4590 tsno(c,j) = t_soisno(c,j+snl(c))
4591 end if
4592 end do
4593 end do
4594
4595 !dir$ concurrent
4596 !cdir nodep
4597 do fc = 1, num_snowc
4598 c = filter_snowc(fc)
4599
4600 msno = abs(snl(c))
4601
4602 if (msno == 1) then
4603 ! Specify a new snow layer
4604 if (dzsno(c,1) > 0.03) then
4605 msno = 2
4606 dzsno(c,1) = dzsno(c,1)*0.5
4607 swice(c,1) = swice(c,1)*0.5
4608 swliq(c,1) = swliq(c,1)*0.5
4609 dzsno(c,2) = dzsno(c,1)
4610 swice(c,2) = swice(c,1)
4611 swliq(c,2) = swliq(c,1)
4612 tsno(c,2) = tsno(c,1)
4613 end if
4614 end if
4615
4616 if (msno > 1) then
4617 if (dzsno(c,1) > 0.02) then
4618 drr = dzsno(c,1) - 0.02
4619 propor = drr/dzsno(c,1)
4620 zwice = propor*swice(c,1)
4621 zwliq = propor*swliq(c,1)
4622 propor = 0.02/dzsno(c,1)
4623 swice(c,1) = propor*swice(c,1)
4624 swliq(c,1) = propor*swliq(c,1)
4625 dzsno(c,1) = 0.02
4626
4627 call combo (dzsno(c,2), swliq(c,2), swice(c,2), tsno(c,2), drr, &
4628 zwliq, zwice, tsno(c,1))
4629
4630 ! Subdivide a new layer
4631 if (msno <= 2 .and. dzsno(c,2) > 0.07) then
4632 msno = 3
4633 dzsno(c,2) = dzsno(c,2)*0.5
4634 swice(c,2) = swice(c,2)*0.5
4635 swliq(c,2) = swliq(c,2)*0.5
4636 dzsno(c,3) = dzsno(c,2)
4637 swice(c,3) = swice(c,2)
4638 swliq(c,3) = swliq(c,2)
4639 tsno(c,3) = tsno(c,2)
4640 end if
4641 end if
4642 end if
4643
4644 if (msno > 2) then
4645 if (dzsno(c,2) > 0.05) then
4646 drr = dzsno(c,2) - 0.05
4647 propor = drr/dzsno(c,2)
4648 zwice = propor*swice(c,2)
4649 zwliq = propor*swliq(c,2)
4650 propor = 0.05/dzsno(c,2)
4651 swice(c,2) = propor*swice(c,2)
4652 swliq(c,2) = propor*swliq(c,2)
4653 dzsno(c,2) = 0.05
4654
4655 call combo (dzsno(c,3), swliq(c,3), swice(c,3), tsno(c,3), drr, &
4656 zwliq, zwice, tsno(c,2))
4657
4658 ! Subdivided a new layer
4659 if (msno <= 3 .and. dzsno(c,3) > 0.18) then
4660 msno = 4
4661 dzsno(c,3) = dzsno(c,3)*0.5
4662 swice(c,3) = swice(c,3)*0.5
4663 swliq(c,3) = swliq(c,3)*0.5
4664 dzsno(c,4) = dzsno(c,3)
4665 swice(c,4) = swice(c,3)
4666 swliq(c,4) = swliq(c,3)
4667 tsno(c,4) = tsno(c,3)
4668 end if
4669 end if
4670 end if
4671
4672 if (msno > 3) then
4673 if (dzsno(c,3) > 0.11) then
4674 drr = dzsno(c,3) - 0.11
4675 propor = drr/dzsno(c,3)
4676 zwice = propor*swice(c,3)
4677 zwliq = propor*swliq(c,3)
4678 propor = 0.11/dzsno(c,3)
4679 swice(c,3) = propor*swice(c,3)
4680 swliq(c,3) = propor*swliq(c,3)
4681 dzsno(c,3) = 0.11
4682
4683 call combo (dzsno(c,4), swliq(c,4), swice(c,4), tsno(c,4), drr, &
4684 zwliq, zwice, tsno(c,3))
4685
4686 ! Subdivided a new layer
4687 if (msno <= 4 .and. dzsno(c,4) > 0.41) then
4688 msno = 5
4689 dzsno(c,4) = dzsno(c,4)*0.5
4690 swice(c,4) = swice(c,4)*0.5
4691 swliq(c,4) = swliq(c,4)*0.5
4692 dzsno(c,5) = dzsno(c,4)
4693 swice(c,5) = swice(c,4)
4694 swliq(c,5) = swliq(c,4)
4695 tsno(c,5) = tsno(c,4)
4696 end if
4697 end if
4698 end if
4699
4700 if (msno > 4) then
4701 if (dzsno(c,4) > 0.23) then
4702 drr = dzsno(c,4) - 0.23
4703 propor = drr/dzsno(c,4)
4704 zwice = propor*swice(c,4)
4705 zwliq = propor*swliq(c,4)
4706 propor = 0.23/dzsno(c,4)
4707 swice(c,4) = propor*swice(c,4)
4708 swliq(c,4) = propor*swliq(c,4)
4709 dzsno(c,4) = 0.23
4710
4711 call combo (dzsno(c,5), swliq(c,5), swice(c,5), tsno(c,5), drr, &
4712 zwliq, zwice, tsno(c,4))
4713 end if
4714 end if
4715
4716 snl(c) = -msno
4717
4718 end do
4719
4720 do j = -nlevsnow+1,0
4721 !dir$ concurrent
4722 !cdir nodep
4723 do fc = 1, num_snowc
4724 c = filter_snowc(fc)
4725 if (j >= snl(c)+1) then
4726 dz(c,j) = dzsno(c,j-snl(c))
4727 h2osoi_ice(c,j) = swice(c,j-snl(c))
4728 h2osoi_liq(c,j) = swliq(c,j-snl(c))
4729 t_soisno(c,j) = tsno(c,j-snl(c))
4730 end if
4731 end do
4732 end do
4733
4734 do j = 0, -nlevsnow+1, -1
4735 !dir$ concurrent
4736 !cdir nodep
4737 do fc = 1, num_snowc
4738 c = filter_snowc(fc)
4739 if (j >= snl(c)+1) then
4740 z(c,j) = zi(c,j) - 0.5*dz(c,j)
4741 zi(c,j-1) = zi(c,j) - dz(c,j)
4742 end if
4743 end do
4744 end do
4745
4746 end subroutine dividesnowlayers
4747
4750 subroutine combo(dz, wliq, wice, t, dz2, wliq2, wice2, t2)
4751 !
4752 ! DESCRIPTION:
4755 ! The combined temperature is based on the equation:
4756 ! the sum of the enthalpies of the two elements =
4757 ! that of the combined element.
4758 !
4759 ! !USES:
4760 !
4761 ! !ARGUMENTS:
4762 implicit none
4763 real(kind_lake), intent(in) :: dz2
4764 real(kind_lake), intent(in) :: wliq2
4765 real(kind_lake), intent(in) :: wice2
4766 real(kind_lake), intent(in) :: t2
4767 real(kind_lake), intent(inout) :: dz
4768 real(kind_lake), intent(inout) :: wliq
4769 real(kind_lake), intent(inout) :: wice
4770 real(kind_lake), intent(inout) :: t
4771 !
4772 ! !CALLED FROM:
4773 ! subroutine CombineSnowLayers in this module
4774 ! subroutine DivideSnowLayers in this module
4775 !
4776 ! !REVISION HISTORY:
4777 ! 15 September 1999: Yongjiu Dai; Initial code
4778 ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision
4779 ! June 2022: Sam Trahan; modified for CCPP
4780 !
4781 !EOP
4782 !
4783 ! !LOCAL VARIABLES:
4784 !
4785 real(kind_lake) :: dzc ! Total thickness of nodes 1 and 2 (dzc=dz+dz2).
4786 real(kind_lake) :: wliqc ! Combined liquid water [kg/m2]
4787 real(kind_lake) :: wicec ! Combined ice [kg/m2]
4788 real(kind_lake) :: tc ! Combined node temperature [K]
4789 real(kind_lake) :: h ! enthalpy of element 1 [J/m2]
4790 real(kind_lake) :: h2 ! enthalpy of element 2 [J/m2]
4791 real(kind_lake) :: hc ! temporary
4792 !-----------------------------------------------------------------------
4793
4794 dzc = dz+dz2
4795 wicec = (wice+wice2)
4796 wliqc = (wliq+wliq2)
4797 h = (cpice*wice+cpliq*wliq) * (t-tfrz)+hfus*wliq
4798 h2= (cpice*wice2+cpliq*wliq2) * (t2-tfrz)+hfus*wliq2
4799
4800 hc = h + h2
4801 if(hc < 0.)then
4802 tc = tfrz + hc/(cpice*wicec + cpliq*wliqc)
4803 else if (hc.le.hfus*wliqc) then
4804 tc = tfrz
4805 else
4806 tc = tfrz + (hc - hfus*wliqc) / (cpice*wicec + cpliq*wliqc)
4807 end if
4808
4809 dz = dzc
4810 wice = wicec
4811 wliq = wliqc
4812 t = tc
4813
4814 end subroutine combo
4815
4817 subroutine buildsnowfilter(lbc, ubc, num_nolakec, filter_nolakec,snl, & !i
4818 num_snowc, filter_snowc, & !o
4819 num_nosnowc, filter_nosnowc) !o
4820 !
4821 ! DESCRIPTION:
4823 !
4824 ! !USES:
4825 ! use clmtype
4826 !
4827 ! !ARGUMENTS:
4828 implicit none
4829 integer, intent(in) :: lbc, ubc
4830 integer, intent(in) :: num_nolakec
4831 integer, intent(in) :: filter_nolakec(ubc-lbc+1)
4832 integer, intent(in) :: snl(1)
4833 integer, intent(out) :: num_snowc
4834 integer, intent(out) :: filter_snowc(ubc-lbc+1)
4835 integer, intent(out) :: num_nosnowc
4836 integer, intent(out) :: filter_nosnowc(ubc-lbc+1)
4837 !
4838 ! !CALLED FROM:
4839 ! subroutine Hydrology2 in Hydrology2Mod
4840 ! subroutine CombineSnowLayers in this module
4841 !
4842 ! !REVISION HISTORY:
4843 ! 2003 July 31: Forrest Hoffman
4844 ! 2022 June: Sam Trahan modified for CCPP
4845 !
4846 ! !LOCAL VARIABLES:
4847 ! local pointers to implicit in arguments
4848 !
4849 !EOP
4850 !
4851 ! !OTHER LOCAL VARIABLES:
4852 integer :: fc, c
4853 !-----------------------------------------------------------------------
4854
4855
4856 ! Build snow/no-snow filters for other subroutines
4857
4858 num_snowc = 0
4859 num_nosnowc = 0
4860 do fc = 1, num_nolakec
4861 c = filter_nolakec(fc)
4862 if (snl(c) < 0) then
4863 num_snowc = num_snowc + 1
4864 filter_snowc(num_snowc) = c
4865 else
4866 num_nosnowc = num_nosnowc + 1
4867 filter_nosnowc(num_nosnowc) = c
4868 end if
4869 end do
4870
4871 end subroutine buildsnowfilter
4872
4873
4874 ! DESCRIPTION:
4881subroutine frictionvelocity(pgridcell,forc_hgt,forc_hgt_u, & !i
4882 forc_hgt_t,forc_hgt_q, & !i
4883 lbp, ubp, fn, filterp, & !i
4884 displa, z0m, z0h, z0q, & !i
4885 obu, iter, ur, um, & !i
4886 ustar,temp1, temp2, temp12m, temp22m, & !o
4887 u10,fv, & !o
4888 fm) !i&o
4889
4890 !=============================================================================
4891 ! REVISION HISTORY:
4892 ! 15 September 1999: Yongjiu Dai; Initial code
4893 ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision
4894 ! 12/19/01, Peter Thornton
4895 ! Added arguments to eliminate passing clm derived type into this function.
4896 ! Created by Mariana Vertenstein
4897 ! June 2022: Sam Trahan modified for CCPP
4898 !============================================================================
4899 ! !USES:
4900 ! use clmtype
4901 !!use clm_atmlnd, only : clm_a2l
4902 !
4903 ! !ARGUMENTS:
4904 implicit none
4905
4906 !in:
4907
4908 integer , intent(in) :: pgridcell(1)
4909 real(kind_lake), intent(in) :: forc_hgt(1)
4910 real(kind_lake), intent(in) :: forc_hgt_u(1)
4911 real(kind_lake), intent(in) :: forc_hgt_t(1)
4912 real(kind_lake), intent(in) :: forc_hgt_q(1)
4913 integer , intent(in) :: lbp, ubp
4914 integer , intent(in) :: fn
4915 integer , intent(in) :: filterp(fn)
4916 real(kind_lake), intent(in) :: displa(lbp:ubp)
4917 real(kind_lake), intent(in) :: z0m(lbp:ubp)
4918 real(kind_lake), intent(in) :: z0h(lbp:ubp)
4919 real(kind_lake), intent(in) :: z0q(lbp:ubp)
4920 real(kind_lake), intent(in) :: obu(lbp:ubp)
4921 integer, intent(in) :: iter
4922 real(kind_lake), intent(in) :: ur(lbp:ubp)
4923 real(kind_lake), intent(in) :: um(lbp:ubp)
4924
4925 !out:
4926
4927 real(kind_lake), intent(out) :: ustar(lbp:ubp)
4928 real(kind_lake), intent(out) :: temp1(lbp:ubp)
4929 real(kind_lake), intent(out) :: temp12m(lbp:ubp)
4930 real(kind_lake), intent(out) :: temp2(lbp:ubp)
4931 real(kind_lake), intent(out) :: temp22m(lbp:ubp)
4932 real(kind_lake), intent(out) :: u10(1)
4933 real(kind_lake), intent(out) :: fv(1)
4934
4935 !inout:
4936 real(kind_lake), intent(inout) :: fm(lbp:ubp)
4937
4938 ! OTHER LOCAL VARIABLES:
4939
4940 real(kind_lake), parameter :: zetam = 1.574_kind_lake ! transition point of flux-gradient relation (wind profile)
4941 real(kind_lake), parameter :: zetat = 0.465_kind_lake ! transition point of flux-gradient relation (temp. profile)
4942 integer :: f ! pft-filter index
4943 integer :: p ! pft index
4944 integer :: g ! gridcell index
4945 real(kind_lake):: zldis(lbp:ubp) ! reference height "minus" zero displacement heght [m]
4946 real(kind_lake):: zeta(lbp:ubp) ! dimensionless height used in Monin-Obukhov theory
4947
4948 !------------------------------------------------------------------------------
4949
4950
4951 ! Adjustment factors for unstable (moz < 0) or stable (moz > 0) conditions.
4952
4953 if_not_pergro: if(.not.pergro) then
4954
4955 !dir$ concurrent
4956 !cdir nodep
4957 do f = 1, fn
4958 p = filterp(f)
4959 g = pgridcell(p)
4960
4961 ! Wind profile
4962
4963 zldis(p) = forc_hgt_u(g)-displa(p)
4964 zeta(p) = zldis(p)/obu(p)
4965 if (zeta(p) < -zetam) then
4966 ustar(p) = vkc*um(p)/(log(-zetam*obu(p)/z0m(p))&
4967 - stabilityfunc1(-zetam) &
4968 + stabilityfunc1(z0m(p)/obu(p)) &
4969 + 1.14_kind_lake*((-zeta(p))**0.333_kind_lake-(zetam)**0.333_kind_lake))
4970 else if (zeta(p) < 0._kind_lake) then
4971 ustar(p) = vkc*um(p)/(log(zldis(p)/z0m(p))&
4972 - stabilityfunc1(zeta(p))&
4973 + stabilityfunc1(z0m(p)/obu(p)))
4974 else if (zeta(p) <= 1._kind_lake) then
4975 ustar(p) = vkc*um(p)/(log(zldis(p)/z0m(p)) + 5._kind_lake*zeta(p) -5._kind_lake*z0m(p)/obu(p))
4976 else
4977 ustar(p) = vkc*um(p)/(log(obu(p)/z0m(p))+5._kind_lake-5._kind_lake*z0m(p)/obu(p) &
4978 +(5._kind_lake*log(zeta(p))+zeta(p)-1._kind_lake))
4979 end if
4980
4981 ! Temperature profile
4982
4983 zldis(p) = forc_hgt_t(g)-displa(p)
4984 zeta(p) = zldis(p)/obu(p)
4985 if (zeta(p) < -zetat) then
4986 temp1(p) = vkc/(log(-zetat*obu(p)/z0h(p))&
4987 - stabilityfunc2(-zetat) &
4988 + stabilityfunc2(z0h(p)/obu(p)) &
4989 + 0.8_kind_lake*((zetat)**(-0.333_kind_lake)-(-zeta(p))**(-0.333_kind_lake)))
4990 else if (zeta(p) < 0._kind_lake) then
4991 temp1(p) = vkc/(log(zldis(p)/z0h(p)) &
4992 - stabilityfunc2(zeta(p)) &
4993 + stabilityfunc2(z0h(p)/obu(p)))
4994 else if (zeta(p) <= 1._kind_lake) then
4995 temp1(p) = vkc/(log(zldis(p)/z0h(p)) + 5._kind_lake*zeta(p) - 5._kind_lake*z0h(p)/obu(p))
4996 else
4997 temp1(p) = vkc/(log(obu(p)/z0h(p)) + 5._kind_lake - 5._kind_lake*z0h(p)/obu(p) &
4998 + (5._kind_lake*log(zeta(p))+zeta(p)-1._kind_lake))
4999 end if
5000
5001 ! Humidity profile
5002
5003 if (forc_hgt_q(g) == forc_hgt_t(g) .and. z0q(p) == z0h(p)) then
5004 temp2(p) = temp1(p)
5005 else
5006 zldis(p) = forc_hgt_q(g)-displa(p)
5007 zeta(p) = zldis(p)/obu(p)
5008 if (zeta(p) < -zetat) then
5009 temp2(p) = vkc/(log(-zetat*obu(p)/z0q(p)) &
5010 - stabilityfunc2(-zetat) &
5011 + stabilityfunc2(z0q(p)/obu(p)) &
5012 + 0.8_kind_lake*((zetat)**(-0.333_kind_lake)-(-zeta(p))**(-0.333_kind_lake)))
5013 else if (zeta(p) < 0._kind_lake) then
5014 temp2(p) = vkc/(log(zldis(p)/z0q(p)) &
5015 - stabilityfunc2(zeta(p)) &
5016 + stabilityfunc2(z0q(p)/obu(p)))
5017 else if (zeta(p) <= 1._kind_lake) then
5018 temp2(p) = vkc/(log(zldis(p)/z0q(p)) + 5._kind_lake*zeta(p)-5._kind_lake*z0q(p)/obu(p))
5019 else
5020 temp2(p) = vkc/(log(obu(p)/z0q(p)) + 5._kind_lake - 5._kind_lake*z0q(p)/obu(p) &
5021 + (5._kind_lake*log(zeta(p))+zeta(p)-1._kind_lake))
5022 end if
5023 endif
5024
5025 ! Temperature profile applied at 2-m
5026
5027 zldis(p) = 2.0_kind_lake + z0h(p)
5028 zeta(p) = zldis(p)/obu(p)
5029 if (zeta(p) < -zetat) then
5030 temp12m(p) = vkc/(log(-zetat*obu(p)/z0h(p))&
5031 - stabilityfunc2(-zetat) &
5032 + stabilityfunc2(z0h(p)/obu(p)) &
5033 + 0.8_kind_lake*((zetat)**(-0.333_kind_lake)-(-zeta(p))**(-0.333_kind_lake)))
5034 else if (zeta(p) < 0._kind_lake) then
5035 temp12m(p) = vkc/(log(zldis(p)/z0h(p)) &
5036 - stabilityfunc2(zeta(p)) &
5037 + stabilityfunc2(z0h(p)/obu(p)))
5038 else if (zeta(p) <= 1._kind_lake) then
5039 temp12m(p) = vkc/(log(zldis(p)/z0h(p)) + 5._kind_lake*zeta(p) - 5._kind_lake*z0h(p)/obu(p))
5040 else
5041 temp12m(p) = vkc/(log(obu(p)/z0h(p)) + 5._kind_lake - 5._kind_lake*z0h(p)/obu(p) &
5042 + (5._kind_lake*log(zeta(p))+zeta(p)-1._kind_lake))
5043 end if
5044
5045 ! Humidity profile applied at 2-m
5046
5047 if (z0q(p) == z0h(p)) then
5048 temp22m(p) = temp12m(p)
5049 else
5050 zldis(p) = 2.0_kind_lake + z0q(p)
5051 zeta(p) = zldis(p)/obu(p)
5052 if (zeta(p) < -zetat) then
5053 temp22m(p) = vkc/(log(-zetat*obu(p)/z0q(p)) - &
5054 stabilityfunc2(-zetat) + stabilityfunc2(z0q(p)/obu(p)) &
5055 + 0.8_kind_lake*((zetat)**(-0.333_kind_lake)-(-zeta(p))**(-0.333_kind_lake)))
5056 else if (zeta(p) < 0._kind_lake) then
5057 temp22m(p) = vkc/(log(zldis(p)/z0q(p)) - &
5058 stabilityfunc2(zeta(p))+stabilityfunc2(z0q(p)/obu(p)))
5059 else if (zeta(p) <= 1._kind_lake) then
5060 temp22m(p) = vkc/(log(zldis(p)/z0q(p)) + 5._kind_lake*zeta(p)-5._kind_lake*z0q(p)/obu(p))
5061 else
5062 temp22m(p) = vkc/(log(obu(p)/z0q(p)) + 5._kind_lake - 5._kind_lake*z0q(p)/obu(p) &
5063 + (5._kind_lake*log(zeta(p))+zeta(p)-1._kind_lake))
5064 end if
5065 end if
5066 end do
5067 endif if_not_pergro
5068
5069
5070if_pergro: if (pergro) then
5071
5072 !===============================================================================
5073 ! The following only applies when PERGRO is defined
5074 !===============================================================================
5075
5076 !dir$ concurrent
5077 !cdir nodep
5078 do f = 1, fn
5079 p = filterp(f)
5080 g = pgridcell(p)
5081
5082 zldis(p) = forc_hgt_u(g)-displa(p)
5083 zeta(p) = zldis(p)/obu(p)
5084 if (zeta(p) < -zetam) then ! zeta < -1
5085 ustar(p) = vkc * um(p) / log(-zetam*obu(p)/z0m(p))
5086 else if (zeta(p) < 0._kind_lake) then ! -1 <= zeta < 0
5087 ustar(p) = vkc * um(p) / log(zldis(p)/z0m(p))
5088 else if (zeta(p) <= 1._kind_lake) then ! 0 <= ztea <= 1
5089 ustar(p)=vkc * um(p)/log(zldis(p)/z0m(p))
5090 else ! 1 < zeta, phi=5+zeta
5091 ustar(p)=vkc * um(p)/log(obu(p)/z0m(p))
5092 endif
5093
5094 zldis(p) = forc_hgt_t(g)-displa(p)
5095 zeta(p) = zldis(p)/obu(p)
5096 if (zeta(p) < -zetat) then
5097 temp1(p)=vkc/log(-zetat*obu(p)/z0h(p))
5098 else if (zeta(p) < 0._kind_lake) then
5099 temp1(p)=vkc/log(zldis(p)/z0h(p))
5100 else if (zeta(p) <= 1._kind_lake) then
5101 temp1(p)=vkc/log(zldis(p)/z0h(p))
5102 else
5103 temp1(p)=vkc/log(obu(p)/z0h(p))
5104 end if
5105
5106 zldis(p) = forc_hgt_q(g)-displa(p)
5107 zeta(p) = zldis(p)/obu(p)
5108 if (zeta(p) < -zetat) then
5109 temp2(p)=vkc/log(-zetat*obu(p)/z0q(p))
5110 else if (zeta(p) < 0._kind_lake) then
5111 temp2(p)=vkc/log(zldis(p)/z0q(p))
5112 else if (zeta(p) <= 1._kind_lake) then
5113 temp2(p)=vkc/log(zldis(p)/z0q(p))
5114 else
5115 temp2(p)=vkc/log(obu(p)/z0q(p))
5116 end if
5117
5118 zldis(p) = 2.0_kind_lake + z0h(p)
5119 zeta(p) = zldis(p)/obu(p)
5120 if (zeta(p) < -zetat) then
5121 temp12m(p)=vkc/log(-zetat*obu(p)/z0h(p))
5122 else if (zeta(p) < 0._kind_lake) then
5123 temp12m(p)=vkc/log(zldis(p)/z0h(p))
5124 else if (zeta(p) <= 1._kind_lake) then
5125 temp12m(p)=vkc/log(zldis(p)/z0h(p))
5126 else
5127 temp12m(p)=vkc/log(obu(p)/z0h(p))
5128 end if
5129
5130 zldis(p) = 2.0_kind_lake + z0q(p)
5131 zeta(p) = zldis(p)/obu(p)
5132 if (zeta(p) < -zetat) then
5133 temp22m(p)=vkc/log(-zetat*obu(p)/z0q(p))
5134 else if (zeta(p) < 0._kind_lake) then
5135 temp22m(p)=vkc/log(zldis(p)/z0q(p))
5136 else if (zeta(p) <= 1._kind_lake) then
5137 temp22m(p)=vkc/log(zldis(p)/z0q(p))
5138 else
5139 temp22m(p)=vkc/log(obu(p)/z0q(p))
5140 end if
5141 end do
5142
5143 endif if_pergro
5144
5145 end subroutine frictionvelocity
5146
5147 ! !IROUTINE: StabilityFunc
5148 !
5149 ! !INTERFACE:
5150 real(kind_lake) function stabilityfunc1(zeta)
5151 !
5152 ! DESCRIPTION:
5154 !
5155 ! !USES:
5156 ! use shr_const_mod, only: SHR_CONST_PI
5157 !Zack Subin, 7/8/08
5158 !
5159 ! !ARGUMENTS:
5160 implicit none
5161 real(kind_lake), intent(in) :: zeta
5162 !
5163 ! !CALLED FROM:
5164 ! subroutine FrictionVelocity in this module
5165 !
5166 ! !REVISION HISTORY:
5167 ! 15 September 1999: Yongjiu Dai; Initial code
5168 ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision
5169 ! June 2022: Sam Trahan; modified for CCPP
5170 !
5171 !EOP
5172 !
5173 ! !LOCAL VARIABLES:
5174 real(kind_lake) :: chik, chik2
5175 !------------------------------------------------------------------------------
5176
5177 chik2 = sqrt(1._kind_lake-16._kind_lake*zeta)
5178 chik = sqrt(chik2)
5179 stabilityfunc1 = 2._kind_lake*log((1._kind_lake+chik)*0.5_kind_lake) &
5180 !Changed to pie, Zack Subin, 7/9/08
5181 !Spelling corrected, changed to pi, Sam Trahan the Killjoy, 6/2/22
5182 + log((1._kind_lake+chik2)*0.5_kind_lake)-2._kind_lake*atan(chik)+pi*0.5_kind_lake
5183
5184 end function stabilityfunc1
5185
5186 !------------------------------------------------------------------------------
5187 !BOP
5188 !
5189 ! !IROUTINE: StabilityFunc2
5190 !
5191 ! !INTERFACE:
5192 real(kind_lake) function stabilityfunc2(zeta)
5193 !
5194 ! !DESCRIPTION:
5196 !
5197 ! !USES:
5198 !Removed by Zack Subin, 7/9/08
5199 ! use shr_const_mod, only: SHR_CONST_PI
5200 !
5201 ! !ARGUMENTS:
5202 implicit none
5203 real(kind_lake), intent(in) :: zeta
5204 !
5205 ! !CALLED FROM:
5206 ! subroutine FrictionVelocity in this module
5207 !
5208 ! !REVISION HISTORY:
5209 ! 15 September 1999: Yongjiu Dai; Initial code
5210 ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision
5211 ! June 2022: Sam Trahan modified for CCPP
5212 !
5213 !EOP
5214 !
5215 ! !LOCAL VARIABLES:
5216 real(kind_lake) :: chik2
5217 !------------------------------------------------------------------------------
5218
5219 chik2 = sqrt(1._kind_lake-16._kind_lake*zeta)
5220 stabilityfunc2 = 2._kind_lake*log((1._kind_lake+chik2)*0.5_kind_lake)
5221
5222 end function stabilityfunc2
5223
5224 !-----------------------------------------------------------------------
5225 !BOP
5226 !
5227 ! !IROUTINE: MoninObukIni
5228 !
5229 ! !INTERFACE:
5230 subroutine moninobukini (ur, thv, dthv, zldis, z0m, um, obu)
5231 !
5232 ! !DESCRIPTION:
5238 !
5239 ! !USES:
5240 !
5241 ! !ARGUMENTS:
5242 implicit none
5243 real(kind_lake), intent(in) :: ur
5244 real(kind_lake), intent(in) :: thv
5245 real(kind_lake), intent(in) :: dthv
5246 real(kind_lake), intent(in) :: zldis
5247 real(kind_lake), intent(in) :: z0m
5248 real(kind_lake), intent(out) :: um
5249 real(kind_lake), intent(out) :: obu
5250 !
5251 ! !CALLED FROM:
5252 ! subroutine BareGroundFluxes in module BareGroundFluxesMod.F90
5253 ! subroutine BiogeophysicsLake in module BiogeophysicsLakeMod.F90
5254 ! subroutine CanopyFluxes in module CanopyFluxesMod.F90
5255 !
5256 ! !REVISION HISTORY:
5257 ! 15 September 1999: Yongjiu Dai; Initial code
5258 ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision
5259 ! June 2022: Sam Trahan modified for CCPP
5260 !
5261 !EOP
5262 !
5263 ! !LOCAL VARIABLES:
5264 !
5265 real(kind_lake) :: wc ! convective velocity [m/s]
5266 real(kind_lake) :: rib ! bulk Richardson number
5267 real(kind_lake) :: zeta ! dimensionless height used in Monin-Obukhov theory
5268 real(kind_lake) :: ustar ! friction velocity [m/s]
5269 !-----------------------------------------------------------------------
5270
5271 ! Initial values of u* and convective velocity
5272
5273 ustar=0.06_kind_lake
5274 wc=0.5_kind_lake
5275 if (dthv >= 0._kind_lake) then
5276 um=max(ur,0.1_kind_lake)
5277 else
5278 um=sqrt(ur*ur+wc*wc)
5279 endif
5280
5281 rib=grav*zldis*dthv/(thv*um*um)
5282 if (pergro) then
5283 rib = 0._kind_lake
5284 endif
5285
5286 if (rib >= 0._kind_lake) then ! neutral or stable
5287 zeta = rib*log(zldis/z0m)/(1._kind_lake-5._kind_lake*min(rib,0.19_kind_lake))
5288 zeta = min(2._kind_lake,max(zeta,0.01_kind_lake ))
5289 else ! unstable
5290 zeta=rib*log(zldis/z0m)
5291 zeta = max(-100._kind_lake,min(zeta,-0.01_kind_lake ))
5292 endif
5293
5294 obu=zldis/zeta
5295
5296 end subroutine moninobukini
5297
5301 subroutine clm_lake_init(con_pi,karman,con_g,con_sbc,con_t0c,rhowater,con_csol,con_cliq, &
5302 con_hfus,con_hvap,con_rd,con_cp,rholakeice,clm_lake_debug, &
5303 clm_debug_print,con_eps_model,con_fvirt_model,errmsg,errflg)
5304 implicit none
5305 real(kind_phys), intent(in) :: con_pi,karman,con_g,con_sbc,con_t0c, &
5306 rhowater,con_csol,con_cliq, con_hfus,con_hvap,con_rd,con_cp, &
5307 rholakeice,con_eps_model,con_fvirt_model
5308 INTEGER, INTENT(OUT) :: errflg
5309 CHARACTER(*), INTENT(OUT) :: errmsg
5310 logical, intent(in) :: clm_lake_debug,clm_debug_print
5311 integer :: i, j
5312
5313 lakedebug = clm_lake_debug
5314 debug_print = clm_debug_print
5315 if(debug_print) then
5316 write(0,*) 'clm_lake_init'
5317 endif
5318
5319 errflg=0
5320 errmsg=''
5321
5322 pi = con_pi
5323 vkc = karman
5324 grav = con_g
5325 sb = con_sbc
5326 tfrz = con_t0c
5327 denh2o = rhowater
5328 denice = rholakeice
5329 cpice = con_csol
5330 cpliq = con_cliq
5331 hfus = con_hfus
5332 hvap = con_hvap
5333 hsub = con_hfus+con_hvap
5334 invhvap = 1._kind_lake/hvap
5335 invhsub = 1._kind_lake/hsub
5336 rair = con_rd
5337 cpair = con_cp
5338 con_eps = con_eps_model
5339 con_fvirt = con_fvirt_model
5340 one_minus_con_eps = 1.0_kind_lake - con_eps
5341
5342 ! dzlak(1) = 0.1_kind_lake
5343 ! dzlak(2) = 1._kind_lake
5344 ! dzlak(3) = 2._kind_lake
5345 ! dzlak(4) = 3._kind_lake
5346 ! dzlak(5) = 4._kind_lake
5347 ! dzlak(6) = 5._kind_lake
5348 ! dzlak(7) = 7._kind_lake
5349 ! dzlak(8) = 7._kind_lake
5350 ! dzlak(9) = 10.45_kind_lake
5351 ! dzlak(10)= 10.45_kind_lake
5352 !
5353 ! zlak(1) = 0.05_kind_lake
5354 ! zlak(2) = 0.6_kind_lake
5355 ! zlak(3) = 2.1_kind_lake
5356 ! zlak(4) = 4.6_kind_lake
5357 ! zlak(5) = 8.1_kind_lake
5358 ! zlak(6) = 12.6_kind_lake
5359 ! zlak(7) = 18.6_kind_lake
5360 ! zlak(8) = 25.6_kind_lake
5361 ! zlak(9) = 34.325_kind_lake
5362 ! zlak(10)= 44.775_kind_lake
5363 dzlak(1) = 0.1_kind_lake
5364 dzlak(2) = 0.1_kind_lake
5365 dzlak(3) = 0.1_kind_lake
5366 dzlak(4) = 0.1_kind_lake
5367 dzlak(5) = 0.1_kind_lake
5368 dzlak(6) = 0.1_kind_lake
5369 dzlak(7) = 0.1_kind_lake
5370 dzlak(8) = 0.1_kind_lake
5371 dzlak(9) = 0.1_kind_lake
5372 dzlak(10)= 0.1_kind_lake
5373
5374 zlak(1) = 0.05_kind_lake
5375 zlak(2) = 0.15_kind_lake
5376 zlak(3) = 0.25_kind_lake
5377 zlak(4) = 0.35_kind_lake
5378 zlak(5) = 0.45_kind_lake
5379 zlak(6) = 0.55_kind_lake
5380 zlak(7) = 0.65_kind_lake
5381 zlak(8) = 0.75_kind_lake
5382 zlak(9) = 0.85_kind_lake
5383 zlak(10)= 0.95_kind_lake
5384
5385 ! "0" refers to soil surface and "nlevsoil" refers to the bottom of model soil
5386
5387 do j = 1, nlevsoil
5388 zsoi(j) = scalez*(exp(0.5_kind_lake*(j-0.5_kind_lake))-1._kind_lake) !node depths
5389 enddo
5390
5391 dzsoi(1) = 0.5_kind_lake*(zsoi(1)+zsoi(2)) !thickness b/n two interfaces
5392 do j = 2,nlevsoil-1
5393 dzsoi(j)= 0.5_kind_lake*(zsoi(j+1)-zsoi(j-1))
5394 enddo
5395 dzsoi(nlevsoil) = zsoi(nlevsoil)-zsoi(nlevsoil-1)
5396
5397 zisoi(0) = 0._kind_lake
5398 do j = 1, nlevsoil-1
5399 zisoi(j) = 0.5_kind_lake*(zsoi(j)+zsoi(j+1)) !interface depths
5400 enddo
5401 zisoi(nlevsoil) = zsoi(nlevsoil) + 0.5_kind_lake*dzsoi(nlevsoil)
5402
5403 end subroutine clm_lake_init
5404
5405 SUBROUTINE lakeini(kdt, ISLTYP, gt0, snowd, & !i
5406 weasd, lakedepth_default, fhour, &
5407 oro_lakedepth, savedtke12d, snowdp2d, h2osno2d, & !o
5408 snl2d, t_grnd2d, t_lake3d, lake_icefrac3d, &
5409 t_soisno3d, h2osoi_ice3d, &
5410 h2osoi_liq3d, h2osoi_vol3d, z3d, dz3d, &
5411 zi3d, &
5412 fice, hice, min_lakeice, tsfc, &
5413 use_lake_model, use_lakedepth, &
5414 im, prsi, &
5415 xlat_d, xlon_d, clm_lake_initialized, &
5416 input_lakedepth, tg3, clm_lakedepth, &
5417 km, me, master, errmsg, errflg)
5418
5425
5426 !==============================================================================
5427 ! This subroutine was first edited by Hongping Gu for coupling
5428 ! 07/20/2010
5429 ! Long after, in June 2022, Sam Trahan updated it for CCPP
5430 !==============================================================================
5431
5432 implicit none
5433
5434 INTEGER, INTENT(OUT) :: errflg
5435 CHARACTER(*), INTENT(OUT) :: errmsg
5436
5437 INTEGER , INTENT (IN) :: im, me, master, km, kdt
5438 REAL(kind_phys), INTENT(IN) :: min_lakeice, fhour
5439 REAL(kind_phys), DIMENSION(:), INTENT(INOUT):: fice, hice
5440 REAL(kind_phys), DIMENSION(:), INTENT(IN):: tg3, xlat_d, xlon_d
5441 REAL(kind_phys), DIMENSION(:), INTENT(IN):: tsfc
5442 REAL(kind_phys), DIMENSION(:) ,INTENT(INOUT) :: clm_lake_initialized
5443 integer, dimension(:), intent(in) :: use_lake_model
5444 LOGICAL, INTENT (IN) :: use_lakedepth
5445
5446 INTEGER, DIMENSION(:), INTENT(IN) :: isltyp
5447 REAL(kind_phys), DIMENSION(:), INTENT(INOUT) :: snowd,weasd
5448 REAL(kind_phys), DIMENSION(:,:), INTENT(IN) :: gt0
5449 REAL(kind_phys), DIMENSION(:,:), INTENT(IN) :: prsi
5450 real(kind_phys), intent(in) :: lakedepth_default
5451
5452 real(kind_phys), dimension(:),intent(inout) :: clm_lakedepth
5453 real(kind_phys), dimension(:),intent(inout) :: input_lakedepth
5454 real(kind_phys), dimension(:),intent(in) :: oro_lakedepth
5455 real(kind_phys), dimension(:),intent(out) :: savedtke12d
5456 real(kind_phys), dimension(:),intent(out) :: snowdp2d, &
5457 h2osno2d, &
5458 snl2d, &
5459 t_grnd2d
5460
5461 real(kind_phys), dimension(:,:),INTENT(out) :: t_lake3d, &
5462 lake_icefrac3d
5463 real(kind_phys), dimension(:,-nlevsnow+1:),INTENT(out) :: t_soisno3d, &
5464 h2osoi_ice3d, &
5465 h2osoi_liq3d, &
5466 h2osoi_vol3d, &
5467 z3d, &
5468 dz3d
5469
5470 real(kind_phys), dimension(:,-nlevsnow+0:),INTENT(out) :: zi3d
5471
5472
5473 integer :: n,i,j,k,ib,lev,bottom ! indices
5474 real(kind_lake),dimension(1:im ) :: bd2d ! bulk density of dry soil material [kg/m^3]
5475 real(kind_lake),dimension(1:im ) :: tkm2d ! mineral conductivity
5476 real(kind_lake),dimension(1:im ) :: xksat2d ! maximum hydraulic conductivity of soil [mm/s]
5477 real(kind_lake),dimension(1:im ) :: depthratio2d ! ratio of lake depth to standard deep lake depth
5478
5479 logical,parameter :: arbinit = .false.
5480 real(kind_lake),parameter :: defval = -999.0
5481 integer :: isl
5482 integer :: numb_lak ! for debug
5483 character*256 :: message
5484 real(kind_lake) :: ht
5485 real(kind_lake) :: rhosn
5486 real(kind_lake) :: depth, lakedepth
5487
5488 logical :: climatology_limits
5489
5490 real(kind_lake) :: z_lake(nlevlake) ! layer depth for lake (m)
5491 real(kind_lake) :: dz_lake(nlevlake) ! layer thickness for lake (m)
5492
5493 integer, parameter :: xcheck=38
5494 integer, parameter :: ycheck=92
5495
5496 integer :: used_lakedepth_default, init_points, month, julday
5497 integer :: mon, iday, num2, num1, juld, day2, day1, wght1, wght2
5498 real(kind_lake) :: tclim, watsat
5499
5500 used_lakedepth_default=0
5501
5502 errmsg = ''
5503 errflg = 0
5504
5505 !!!!!!!!!!!!!!!!!!begin to initialize lake variables!!!!!!!!!!!!!!!!!!
5506
5507 init_points=0
5508 do_init: DO i=1,im
5509 if(use_lake_model(i)==0 .or. clm_lake_initialized(i)>0) then
5510 cycle
5511 endif
5512
5513 ! To handle cold-start with bad lakedepth2d
5514 if ( use_lakedepth ) then
5515 if (oro_lakedepth(i) == 10.0 .or. oro_lakedepth(i) <= 0.) then
5516 !- 10.0 is the fill value for lake depth, in this case set to default value
5517 clm_lakedepth(i) = lakedepth_default
5518 used_lakedepth_default = used_lakedepth_default+1
5519 else
5520 clm_lakedepth(i) = oro_lakedepth(i)
5521 endif
5522 else
5523 !- all lakes are initialized with the default lake depth
5524 clm_lakedepth(i) = lakedepth_default
5525 used_lakedepth_default = used_lakedepth_default+1
5526 endif
5527
5528 if(clm_lake_initialized(i)>0) then
5529 cycle
5530 endif
5531
5532 input_lakedepth=clm_lakedepth
5533
5534 snl2d(i) = defval
5535 do k = -nlevsnow+1,nlevsoil
5536 h2osoi_liq3d(i,k) = defval
5537 h2osoi_ice3d(i,k) = defval
5538 h2osoi_vol3d(i,k) = defval
5539 t_soisno3d(i,k) = defval
5540 z3d(i,k) = defval
5541 dz3d(i,k) = defval
5542 enddo
5543 do k = 1,nlevlake
5544 t_lake3d(i,k) = defval
5545 lake_icefrac3d(i,k) = defval
5546 enddo
5547
5548 if (use_lake_model(i) == 1) then
5549 ! for lake points only
5550 z3d(i,:) = 0.0
5551 dz3d(i,:) = 0.0
5552 zi3d(i,:) = 0.0
5553 h2osoi_liq3d(i,:) = 0.0
5554 h2osoi_ice3d(i,:) = 0.0
5555 lake_icefrac3d(i,:) = 0.0
5556 h2osoi_vol3d(i,:) = 0.0
5557 snl2d(i) = 0.0
5558
5559 if(fice(i)>min_lakeice) then
5560 lake_icefrac3d(i,1) = fice(i)
5561 snowdp2d(i) = snowd(i)*1e-3 ! SNOW in kg/m^2 and snowdp in m
5562 h2osno2d(i) = weasd(i) ! mm
5563 else
5564 fice(i) = 0.
5565 snowd(i) = 0.
5566 weasd(i) = 0.
5567 snowdp2d(i) = 0.
5568 h2osno2d(i) = 0.
5569 endif
5570
5571 ! Soil hydraulic and thermal properties
5572 isl = isltyp(i)
5573 if (isl == 0 ) isl = 14
5574 if (isl == 14 ) isl = isl + 1
5575
5576 call calculate_z_dz_lake(i,input_lakedepth,clm_lakedepth,z_lake,dz_lake)
5577
5578 z3d(i,1:nlevsoil) = zsoi(1:nlevsoil)
5579 zi3d(i,0:nlevsoil) = zisoi(0:nlevsoil)
5580 dz3d(i,1:nlevsoil) = dzsoi(1:nlevsoil)
5581 savedtke12d(i) = tkwat ! Initialize for first timestep.
5582
5583
5584 if (snowdp2d(i) < 0.01_kind_lake) then
5585 snl2d(i) = 0
5586 dz3d(i,-nlevsnow+1:0) = 0._kind_lake
5587 z3d(i,-nlevsnow+1:0) = 0._kind_lake
5588 zi3d(i,-nlevsnow+0:0) = 0._kind_lake
5589 else
5590 if ((snowdp2d(i) >= 0.01_kind_lake) .and. (snowdp2d(i) <= 0.03_kind_lake)) then
5591 snl2d(i) = -1
5592 dz3d(i,0) = snowdp2d(i)
5593 else if ((snowdp2d(i) > 0.03_kind_lake) .and. (snowdp2d(i) <= 0.04_kind_lake)) then
5594 snl2d(i) = -2
5595 dz3d(i,-1) = snowdp2d(i)*0.5_kind_lake
5596 dz3d(i, 0) = dz3d(i,-1)
5597 else if ((snowdp2d(i) > 0.04_kind_lake) .and. (snowdp2d(i) <= 0.07_kind_lake)) then
5598 snl2d(i) = -2
5599 dz3d(i,-1) = 0.02_kind_lake
5600 dz3d(i, 0) = snowdp2d(i) - dz3d(i,-1)
5601 else if ((snowdp2d(i) > 0.07_kind_lake) .and. (snowdp2d(i) <= 0.12_kind_lake)) then
5602 snl2d(i) = -3
5603 dz3d(i,-2) = 0.02_kind_lake
5604 dz3d(i,-1) = (snowdp2d(i) - 0.02_kind_lake)*0.5_kind_lake
5605 dz3d(i, 0) = dz3d(i,-1)
5606 else if ((snowdp2d(i) > 0.12_kind_lake) .and. (snowdp2d(i) <= 0.18_kind_lake)) then
5607 snl2d(i) = -3
5608 dz3d(i,-2) = 0.02_kind_lake
5609 dz3d(i,-1) = 0.05_kind_lake
5610 dz3d(i, 0) = snowdp2d(i) - dz3d(i,-2) - dz3d(i,-1)
5611 else if ((snowdp2d(i) > 0.18_kind_lake) .and. (snowdp2d(i) <= 0.29_kind_lake)) then
5612 snl2d(i) = -4
5613 dz3d(i,-3) = 0.02_kind_lake
5614 dz3d(i,-2) = 0.05_kind_lake
5615 dz3d(i,-1) = (snowdp2d(i) - dz3d(i,-3) - dz3d(i,-2))*0.5_kind_lake
5616 dz3d(i, 0) = dz3d(i,-1)
5617 else if ((snowdp2d(i) > 0.29_kind_lake) .and. (snowdp2d(i) <= 0.41_kind_lake)) then
5618 snl2d(i) = -4
5619 dz3d(i,-3) = 0.02_kind_lake
5620 dz3d(i,-2) = 0.05_kind_lake
5621 dz3d(i,-1) = 0.11_kind_lake
5622 dz3d(i, 0) = snowdp2d(i) - dz3d(i,-3) - dz3d(i,-2) - dz3d(i,-1)
5623 else if ((snowdp2d(i) > 0.41_kind_lake) .and. (snowdp2d(i) <= 0.64_kind_lake)) then
5624 snl2d(i) = -5
5625 dz3d(i,-4) = 0.02_kind_lake
5626 dz3d(i,-3) = 0.05_kind_lake
5627 dz3d(i,-2) = 0.11_kind_lake
5628 dz3d(i,-1) = (snowdp2d(i) - dz3d(i,-4) - dz3d(i,-3) - dz3d(i,-2))*0.5_kind_lake
5629 dz3d(i, 0) = dz3d(i,-1)
5630 else if (snowdp2d(i) > 0.64_kind_lake) then
5631 snl2d(i) = -5
5632 dz3d(i,-4) = 0.02_kind_lake
5633 dz3d(i,-3) = 0.05_kind_lake
5634 dz3d(i,-2) = 0.11_kind_lake
5635 dz3d(i,-1) = 0.23_kind_lake
5636 dz3d(i, 0)=snowdp2d(i)-dz3d(i,-4)-dz3d(i,-3)-dz3d(i,-2)-dz3d(i,-1)
5637 endif
5638 end if
5639
5640 do k = 0, nint(snl2d(i)+1), -1
5641 z3d(i,k) = zi3d(i,k) - 0.5_kind_lake*dz3d(i,k)
5642 zi3d(i,k-1) = zi3d(i,k) - dz3d(i,k)
5643 end do
5644
5645 ! 3:subroutine makearbinit
5646
5647 ! initial t_lake3d here
5648 if(tsfc(i)<160) then
5649 write(errmsg,'(A,F20.12,A)') 'Invalid tsfc value ',tsfc(i),' found. Was tsfc not initialized?'
5650 write(0,'(A)') trim(errmsg)
5651 errflg=1
5652 return
5653 endif
5654
5655 if(lake_icefrac3d(i,1) > 0.) then
5656 depth = 0.
5657 do k=2,nlevlake
5658 depth = depth + dz_lake(k)
5659 if(hice(i) >= depth) then
5660 lake_icefrac3d(i,k) = max(0.,lake_icefrac3d(i,1)+(0.-lake_icefrac3d(i,1))/z_lake(nlevlake)*depth)
5661 else
5662 lake_icefrac3d(i,k) = 0.
5663 endif
5664 end do
5665 endif
5666
5667 t_lake3d(i,1) = tsfc(i)
5668 t_grnd2d(i) = tsfc(i)
5669 if (lake_icefrac3d(i,1) <= 0.) then
5670 t_lake3d(i,1) = max(tfrz,tsfc(i))
5671 t_grnd2d(i) = max(tfrz,tsfc(i))
5672 endif
5673 do k = 2, nlevlake
5674 if(z_lake(k).le.depth_c) then
5675 t_lake3d(i,k) = tsfc(i)+(277.2_kind_lake-tsfc(i))/depth_c*z_lake(k)
5676 else
5677 t_lake3d(i,k) = 277.2_kind_lake
5678 end if
5679 if (lake_icefrac3d(i,k) <= 0.) then
5680 t_lake3d(i,k) = max(tfrz,t_lake3d(i,k))
5681 endif
5682 enddo
5683
5684 ! initial t_soisno3d
5685 ! in snow
5686 if(snowdp2d(i) > 0.) then
5687 do k = nint(snl2d(i))+1, 0
5688 t_soisno3d(i,k) =min(tfrz,tsfc(i))
5689 enddo
5690 endif
5691
5692 ! in soil
5693 t_soisno3d(i,1) = t_lake3d(i,nlevlake)
5694 t_soisno3d(i,nlevsoil) = tg3(i)
5695 do k = 2, nlevsoil-1
5696 t_soisno3d(i,k)=t_soisno3d(i,1)+(t_soisno3d(i,nlevsoil)-t_soisno3d(i,1))*dzsoi(k)
5697 enddo
5698
5699 if (snl2d(i) < 0) then
5700 do k = nint(snl2d(i)+1), 0
5701 ! Be careful because there may be new snow layers with bad temperatures like 0 even if
5702 ! coming from init. con. file.
5703 if(t_soisno3d(i,k) > 300 .or. t_soisno3d(i,k) < 200) t_soisno3d(i,k) = min(tfrz,tsfc(i))
5704 enddo
5705 end if
5706
5707 do k = 1,nlevsoil
5708 h2osoi_vol3d(i,k) = 1.0_kind_lake
5709 watsat = 0.489_kind_lake - 0.00126_kind_lake*sand(isl)
5710 h2osoi_vol3d(i,k) = min(h2osoi_vol3d(i,k),watsat)
5711
5712 ! soil layers
5713 if (t_soisno3d(i,k) <= tfrz) then
5714 h2osoi_ice3d(i,k) = dz3d(i,k)*denice*h2osoi_vol3d(i,k)
5715 h2osoi_liq3d(i,k) = 0._kind_lake
5716 else
5717 h2osoi_ice3d(i,k) = 0._kind_lake
5718 h2osoi_liq3d(i,k) = dz3d(i,k)*denh2o*h2osoi_vol3d(i,k)
5719 endif
5720 enddo
5721
5722 !tgs - in RAP and HRRR applications with cycled snow depth and snow
5723 !water equivalent, the actual snow density could be computed. This is
5724 !not used for now for consistency with the main Lake subroutine, where
5725 !constant snow density (250.) is used.
5726 if(h2osno2d(i).gt.0. .and. snowdp2d(i).gt.0.) then
5727 rhosn = h2osno2d(i)/snowdp2d(i)
5728 else
5729 rhosn = snow_bd ! bdsno=250.
5730 endif
5731
5732
5733 do k = -nlevsnow+1, 0
5734 if (k > snl2d(i)) then
5735 h2osoi_ice3d(i,k) = dz3d(i,k)*snow_bd
5736 h2osoi_liq3d(i,k) = 0._kind_lake
5737 end if
5738 end do
5739
5740 clm_lake_initialized(i) = 1
5741
5742 endif !if ( use_lakedepth ) then
5743 ENDDO do_init
5744
5745
5746 if(debug_print .and. init_points>0) then
5747 print *,'points initialized in clm_lake',init_points
5748 end if
5749
5750END SUBROUTINE lakeini
5751
5752END MODULE clm_lake
This module contains the CLM Lake model.
Definition clm_lake.f90:22