Skip to content

Commit

Permalink
Working tiled surface layer solver
Browse files Browse the repository at this point in the history
  • Loading branch information
bartvstratum committed Jul 2, 2020
1 parent 8def726 commit c56c478
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 25 deletions.
96 changes: 90 additions & 6 deletions src/modlsm.f90
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,15 @@ module modlsm
! Precipitation interception et al.
real, allocatable :: throughfall(:,:)

! Random
real, allocatable :: du_tot(:,:), thv_1(:,:)

! Data structure for sub-grid tiles
type lsm_tile
! Static properties:
real, allocatable :: z0m(:,:), z0h(:,:)
! Base tile fraction (i.e. without liquid water)
real, allocatable :: base_frac(:,:)
! Dynamic tile fraction:
real, allocatable :: frac(:,:)
! Monin-obukhov / surface layer:
Expand Down Expand Up @@ -81,8 +86,8 @@ subroutine lsm
implicit none

! tmp...
thlflux(:,:) = 0.
qtflux(:,:) = 0.
thlflux(:,:) = 0.1
qtflux(:,:) = 0.1e-3
G0(:,:) = 0.
phiw_source(:,:,:) = 0.
throughfall(:,:) = 0.
Expand All @@ -95,8 +100,6 @@ subroutine lsm
call stability




!
! 2. Calculate soil tendencies
!
Expand All @@ -116,13 +119,71 @@ subroutine lsm
end subroutine lsm

!
! Calculate Obukhov length, ustar, .. for all tiles
! Calculate Obukhov length, ustar, and aerodynamic resistance, for all tiles
!
subroutine stability
use modglobal, only : i1, j1, cu, cv, rv, rd
use modfields, only : u0, v0, thl0, qt0
implicit none

real :: du, dv
integer :: i, j
real, parameter :: du_min = 0.1

! Calculate properties shared by all tiles:
! Absolute wind speed difference, and virtual potential temperature atmosphere
do j=2,j1
do i=2,i1
du = 0.5*(u0(i,j,1) + u0(i+1,j,1)) + cu
dv = 0.5*(v0(i,j,1) + v0(i,j+1,1)) + cv
du_tot(i,j) = sqrt(du**2 + dv**2)

thv_1(i,j) = thl0(i,j,1) * (1.+(rv/rd-1.)*qt0(i,j,1))
end do
end do

call calc_obuk_ustar_ra(tile_lv)
call calc_obuk_ustar_ra(tile_hv)
call calc_obuk_ustar_ra(tile_bs)
call calc_obuk_ustar_ra(tile_ws)

end subroutine stability

!
! Calculate Obukhov length and ustar, for single tile
!
subroutine calc_obuk_ustar_ra(tile)
use modglobal, only : i1, j1, rd, rv, grav, zf
implicit none

type(lsm_tile), intent(inout) :: tile
integer :: i, j
real :: thvs, db

do j=2,j1
do i=2,i1
! Buoyancy difference surface - atmosphere
thvs = tile%thlskin(i,j) * (1.+(rv/rd-1.)*tile%qtskin(i,j))
db = grav/thvs * (thvs - thv_1(i,j))

! Iteratively find Obukhov length
tile%obuk(i,j) = calc_obuk_dirichlet( &
tile%obuk(i,j), du_tot(i,j), db, zf(1), tile%z0m(i,j), tile%z0h(i,j))
end do
end do

do j=2,j1
do i=2,i1
! Calculate friction velocity and aerodynamic resistance
tile%ustar(i,j) = du_tot(i,j) * fm(zf(1), tile%z0m(i,j), tile%obuk(i,j))
tile%ra(i,j) = 1./tile%ustar(i,j) * fh(zf(1), tile%z0h(i,j), tile%obuk(i,j))
end do
end do

end subroutine calc_obuk_ustar_ra





!
Expand Down Expand Up @@ -463,6 +524,9 @@ subroutine allocate_fields

allocate(throughfall(i2, j2))

allocate(du_tot(i2, j2))
allocate(thv_1(i2, j2))

! NOTE: names differ from what is described in modsurfdata!
! Diffusivity temperature:
allocate(lambda (i2, j2, kmax_soil ))
Expand Down Expand Up @@ -502,7 +566,8 @@ subroutine allocate_tile(tile)
allocate(tile % z0m(i2, j2))
allocate(tile % z0h(i2, j2))

! Dynamic tile fraction:
! Base and dynamic tile fraction:
allocate(tile % base_frac(i2, j2))
allocate(tile % frac(i2, j2))

! Monin-obukhov / surface layer:
Expand Down Expand Up @@ -568,6 +633,7 @@ subroutine init_homogeneous
implicit none

integer :: ierr, k
real :: c_low, c_high, c_bare
real :: z0m_low, z0m_high, z0m_bare
real :: z0h_low, z0h_high, z0h_bare
real :: lambda_s_low, lambda_s_high, lambda_s_bare
Expand All @@ -580,6 +646,7 @@ subroutine init_homogeneous

! Read namelist
namelist /NAMLSM_HOMOGENEOUS/ &
c_low, c_high, &
z0m_low, z0m_high, z0m_bare, &
z0h_low, z0h_high, z0h_bare, &
lambda_s_low, lambda_s_high, lambda_s_bare, &
Expand All @@ -600,6 +667,9 @@ subroutine init_homogeneous
end if

! Broadcast to all MPI tasks
call MPI_BCAST(c_low, 1, my_real, 0, comm3d, mpierr)
call MPI_BCAST(c_high, 1, my_real, 0, comm3d, mpierr)

call MPI_BCAST(z0m_low, 1, my_real, 0, comm3d, mpierr)
call MPI_BCAST(z0m_high, 1, my_real, 0, comm3d, mpierr)
call MPI_BCAST(z0m_bare, 1, my_real, 0, comm3d, mpierr)
Expand Down Expand Up @@ -627,6 +697,12 @@ subroutine init_homogeneous
call MPI_BCAST(soil_index_p, kmax_soil, mpi_integer, 0, comm3d, mpierr)

! Set values
c_bare = 1.-c_low-c_high
tile_lv % base_frac(:,:) = c_low
tile_hv % base_frac(:,:) = c_high
tile_bs % base_frac(:,:) = c_bare
tile_ws % base_frac(:,:) = 0.

tile_lv % z0m(:,:) = z0m_low
tile_hv % z0m(:,:) = z0m_high
tile_bs % z0m(:,:) = z0m_bare
Expand Down Expand Up @@ -658,6 +734,13 @@ subroutine init_homogeneous
tsoilm(:,:,:) = tsoil(:,:,:)
phiwm (:,:,:) = phiw (:,:,:)

! Set properties wet skin tile
tile_ws % z0m(:,:) = c_low*z0m_low + c_high*z0m_high + c_bare*z0m_bare
tile_ws % z0h(:,:) = c_low*z0h_low + c_high*z0h_high + c_bare*z0h_bare

tile_ws % lambda_stable(:,:) = c_low*lambda_s_low + c_high*lambda_s_high + c_bare*lambda_s_bare
tile_ws % lambda_unstable(:,:) = c_low*lambda_us_low + c_high*lambda_us_high + c_bare*lambda_us_bare

! Cleanup!
deallocate(t_soil_p, theta_soil_p)

Expand Down Expand Up @@ -840,6 +923,7 @@ function calc_obuk_dirichlet(L_in, du, db_in, zsl, z0m, z0h) result(res)

if (m > 1) then
print*,'WARNING: convergence has not been reached in Obukhov length iteration'
print*,'Input: ', L_in, du, db_in, zsl, z0m, z0h
res = 1e-9
return
end if
Expand Down
4 changes: 4 additions & 0 deletions src/modstartup.f90
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,10 @@ subroutine readinitfiles
tskin = thls
qskin = qts
case(11)
thls = thlprof(1)
qts = qtprof(1)
tskin = thls
qskin = qts
call init_lsm_tiles
case(10)
call initsurf_user
Expand Down
87 changes: 68 additions & 19 deletions src/modtimestat.f90
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ module modtimestat
real :: qlint
logical:: store_zi = .false.

!Variables for heterogeneity
! Variables for heterogeneity
real, allocatable :: u0av_patch (:,:) ! patch averaged um at full level
real, allocatable :: v0av_patch (:,:) ! patch averaged vm at full level
real, allocatable :: w0av_patch (:,:) ! patch averaged wm at full level
Expand All @@ -72,11 +72,13 @@ module modtimestat
real,allocatable, dimension(:,:) :: cc_patch, qlint_patch, qlintmax_patch, qlintmax_patchl, tke_tot_patch
real,allocatable, dimension(:,:) :: wmax_patch, wmax_patchl, qlmax_patch, qlmax_patchl, ztopmax_patch, ztopmax_patchl
real,allocatable, dimension(:,:) :: ust_patch, qst_patch, tst_patch, wthls_patch, wqls_patch, wthvs_patch
!In combination with isurf = 1

! In combination with isurf = 1
real,allocatable, dimension(:,:) :: Qnet_patch, H_patch, LE_patch, G0_patch, tendskin_patch,rs_patch,ra_patch
real,allocatable, dimension(:,:) :: cliq_patch, wl_patch, rsveg_patch, rssoil_patch, tskin_patch, obl_patch
real,allocatable, dimension(:,:) :: zi_patch,ziold_patch,we_patch, zi_field


contains
!> Initializing Timestat. Read out the namelist, initializing the variables
subroutine inittimestat
Expand Down Expand Up @@ -185,7 +187,7 @@ subroutine inittimestat
' [m/s] '
close(ifoutput)
end if

if(lhetero) then
do i=1,xpatches
do j=1,ypatches
Expand All @@ -197,7 +199,7 @@ subroutine inittimestat
'# time cc z_cbase z_ctop_avg z_ctop_max zi we', &
' <<ql>> <<ql>>_max w_max tke ql_max'
close(ifoutput)

name = 'tmsurfpatchiiixjjj.'//cexpnr
write (name(12:14),'(i3.3)') i
write (name(16:18),'(i3.3)') j
Expand All @@ -206,7 +208,7 @@ subroutine inittimestat
'# time ust tst qst obukh', &
' thls z0 wthls wthvs wqls '
close(ifoutput)

if(isurf == 1) then
name = 'tmlsmpatchiiixjjj.'//cexpnr
write (name(11:13),'(i3.3)') i
Expand All @@ -231,7 +233,7 @@ subroutine inittimestat
if (isurf == 1) then
nvar = 32
else if (isurf == 11) then
nvar = 25
nvar = 34
else
nvar = 21
end if
Expand Down Expand Up @@ -273,11 +275,24 @@ subroutine inittimestat
call ncinfo(ncname(30,:),'Wl','Liquid water reservoir','m','time')
call ncinfo(ncname(31,:),'rssoil','Soil evaporation resistance','s/m','time')
call ncinfo(ncname(32,:),'rsveg','Vegitation resistance','s/m','time')

else if (isurf==11) then
call ncinfo(ncname(22,:),'Qnet','Net radiation','W/m^2','time')
call ncinfo(ncname(23,:),'H','Sensible heat flux','W/m^2','time')
call ncinfo(ncname(24,:),'LE','Latent heat flux','W/m^2','time')
call ncinfo(ncname(25,:),'G','Ground heat flux','W/m^2','time')

call ncinfo(ncname(26,:),'obuk_lv','Obukhov length low veg','m','time')
call ncinfo(ncname(27,:),'obuk_hv','Obukhov length high veg','m','time')
call ncinfo(ncname(28,:),'obuk_bs','Obukhov length bare soil','m','time')

call ncinfo(ncname(29,:),'ustar_lv','Friction velocity low veg','m s-1','time')
call ncinfo(ncname(30,:),'ustar_hv','Friction velocity high veg','m s-1','time')
call ncinfo(ncname(31,:),'ustar_bs','Friction velocity bare soil','m s-1','time')

call ncinfo(ncname(32,:),'ra_lv','Aerodynamic resistance low veg','s m-1','time')
call ncinfo(ncname(33,:),'ra_hv','Aerodynamic resistance high veg','s m-1','time')
call ncinfo(ncname(34,:),'ra_bs','Aerodynamic resistance bare soil','s m-1','time')
end if

call open_nc(fname, ncid,nrec)
Expand Down Expand Up @@ -355,9 +370,10 @@ subroutine timestat
lhetero, xpatches, ypatches, qts_patch, wt_patch, wq_patch, &
thls_patch,obl,z0mav_patch, wco2av, Anav, Respav,gcco2av
use modsurface, only : patchxnr,patchynr
use modlsm, only : tile_lv, tile_hv, tile_bs, tile_ws
use mpi
use modmpi, only : my_real,mpi_sum,mpi_max,mpi_min,comm3d,mpierr,myid
use modstat_nc, only : lnetcdf, writestat_nc,nc_fillvalue
use modstat_nc, only : lnetcdf, writestat_nc,nc_fillvalue
implicit none

real :: zbaseavl, ztopavl, ztopmaxl, ztop,zbaseminl
Expand All @@ -372,6 +388,12 @@ subroutine timestat
! lsm variables
real :: Qnetavl, Havl, LEavl, G0avl, tendskinavl, rsavl, raavl, tskinavl,Wlavl,cliqavl,rsvegavl,rssoilavl
real :: Qnetav, Hav, LEav, G0av, tendskinav, rsav, raav, tskinav,Wlav,cliqav,rsvegav,rssoilav

! LSM tiled variables
real :: obuk_lv_av, obuk_hv_av, obuk_bs_av
real :: ustar_lv_av, ustar_hv_av, ustar_bs_av
real :: ra_lv_av, ra_hv_av, ra_bs_av

integer:: i, j, k

! heterogeneity variables
Expand Down Expand Up @@ -768,20 +790,25 @@ subroutine timestat
endif

else if(isurf == 11) then
Qnetavl = sum(Qnet(2:i1,2:j1))
Havl = sum(H(2:i1,2:j1))
LEavl = sum(LE(2:i1,2:j1))
G0avl = sum(G0(2:i1,2:j1))

call MPI_ALLREDUCE(Qnetavl, Qnetav, 1, MY_REAL,MPI_SUM, comm3d,mpierr)
call MPI_ALLREDUCE(Havl, Hav, 1, MY_REAL,MPI_SUM, comm3d,mpierr)
call MPI_ALLREDUCE(LEavl, LEav, 1, MY_REAL,MPI_SUM, comm3d,mpierr)
call MPI_ALLREDUCE(G0avl, G0av, 1, MY_REAL,MPI_SUM, comm3d,mpierr)
Qnetav = mean_2d(Qnet)
Hav = mean_2d(H)
LEav = mean_2d(LE)
G0av = mean_2d(G0)

! Tiled variables
obuk_lv_av = mean_2d(tile_lv%obuk)
obuk_hv_av = mean_2d(tile_hv%obuk)
obuk_bs_av = mean_2d(tile_bs%obuk)

ustar_lv_av = mean_2d(tile_lv%ustar)
ustar_hv_av = mean_2d(tile_hv%ustar)
ustar_bs_av = mean_2d(tile_bs%ustar)

ra_lv_av = mean_2d(tile_lv%ra)
ra_hv_av = mean_2d(tile_hv%ra)
ra_bs_av = mean_2d(tile_bs%ra)

Qnetav = Qnetav / ijtot
Hav = Hav / ijtot
LEav = LEav / ijtot
G0av = G0av / ijtot
end if

! 9.8 write the results to output file
Expand Down Expand Up @@ -887,6 +914,15 @@ subroutine timestat
vars(23) = Hav
vars(24) = LEav
vars(25) = G0av
vars(26) = obuk_lv_av
vars(27) = obuk_hv_av
vars(28) = obuk_bs_av
vars(29) = ustar_lv_av
vars(30) = ustar_hv_av
vars(31) = ustar_bs_av
vars(32) = ra_lv_av
vars(33) = ra_hv_av
vars(34) = ra_bs_av
end if

call writestat_nc(ncid,nvar,ncname,vars,nrec,.true.)
Expand Down Expand Up @@ -960,6 +996,19 @@ subroutine timestat

end subroutine timestat

function mean_2d(var_2d) result(res)
use modglobal, only : i1, j1, ijtot
use modmpi, only : my_real, mpi_sum, comm3d, mpierr
implicit none
real, intent(in) :: var_2d(:,:)
real :: res, var_sum_l, var_sum

var_sum_l = sum(var_2d(2:i1,2:j1))
call mpi_allreduce(var_sum_l, var_sum, 1, my_real, mpi_sum, comm3d, mpierr)
res = var_sum / ijtot

end function mean_2d

!>Calculate the boundary layer height
!!
!! There are 3 available ways to calculate the boundary layer height:
Expand Down

0 comments on commit c56c478

Please sign in to comment.