9     public add_increment_soil
    10     public add_increment_snow
    11     public calculate_landinc_mask
    12     public apply_land_da_adjustments_soil
    13     public apply_land_da_adjustments_snd
    14     public lsm_noah, lsm_noahmp
    16     integer, 
parameter            :: lsm_noah=1
    17     integer, 
parameter            :: lsm_noahmp=2
    21     integer, 
parameter       :: lsoil_incr=3
    23     real, 
parameter          :: tfreez=273.16
    55 subroutine add_increment_soil(rla,rlo,stc_state,smc_state,slc_state,stc_updated, slc_updated, &
    56                         soilsnow_tile,soilsnow_fg_tile,lensfc,lsoil,idim,jdim,lsm, myrank)
    66     integer, 
intent(in)      :: lensfc, lsoil, idim, jdim, myrank, lsm
    68     integer, 
intent(in)      :: soilsnow_tile(lensfc), soilsnow_fg_tile(lensfc)
    69     real, 
intent(inout)      :: rla(lensfc), rlo(lensfc)
    70     real, 
intent(inout)      :: stc_state(lensfc, lsoil)
    71     real, 
intent(inout)      :: slc_state(lensfc, lsoil)
    72     real, 
intent(inout)      :: smc_state(lensfc, lsoil)
    73     integer, 
intent(out)     :: stc_updated(lensfc), slc_updated(lensfc)
    75     integer                  :: iopt, nret, kgds_gaus(200)
    76     integer                  :: igaus, jgaus, ij
    77     integer                  :: mask_tile, mask_fg_tile
    78     integer                  :: itile, jtile
    80     integer                  :: igausp1, jgausp1
    81     logical                  :: upd_slc, upd_stc
    84     integer, 
allocatable     :: id1(:,:), id2(:,:), jdc(:,:)
    87     real                     :: stc_inc(lsoil)
    88     real                     :: slc_inc(lsoil)
    89     real, 
allocatable        :: xpts(:), ypts(:), lats(:), lons(:)
    90     real, 
allocatable        :: dum2d(:,:), lats_rad(:), lons_rad(:)
    91     real, 
allocatable        :: agrid(:,:,:), s2c(:,:,:)
    93     integer                  :: k, nother, nsnowupd, nnosoilnear
    94     integer                  :: nstcupd, nslcupd,  nfrozen, nfrozen_upd
    95     logical                  :: gaus_has_soil, soil_freeze, soil_ice
   108     kgds_gaus(7)  = -90000     
   109     kgds_gaus(8)  = nint(-360000./float(
idim_gaus))  
   110     kgds_gaus(9)  = nint((360.0 / float(
idim_gaus))*1000.0)
   117     if (lsm==lsm_noah) 
then    120     elseif (lsm==lsm_noahmp) 
then    126     print*,
'adjust soil using gsi increments on gaussian grid'   127     print*,
'updating soil temps', upd_stc
   128     print*,
'updating soil moisture', upd_slc
   129     print*,
'adjusting first ', lsoil_incr, 
' surface layers only'   149     print*,
'fatal error: problem in gdswzd. stop.'   150     call mpi_abort(mpi_comm_world, 12, ierr)
   153     deallocate (xpts, ypts)
   162     lats_rad(j) = dum2d(1,
jdim_gaus-j+1) * 3.1415926 / 180.0
   168     lons_rad = dum2d(:,1) * 3.1415926 / 180.0
   172     allocate(agrid(idim,jdim,2))
   173     agrid(:,:,1) = reshape(rlo, (/idim,jdim/) )
   174     agrid(:,:,2) = reshape(rla, (/idim,jdim/) )
   175     agrid        = agrid * 3.1415926 / 180.0
   177     allocate(id1(idim,jdim))
   178     allocate(id2(idim,jdim))
   179     allocate(jdc(idim,jdim))
   180     allocate(s2c(idim,jdim,4))
   189                   lons_rad, lats_rad, id1, id2, jdc, s2c, agrid )
   191     deallocate(lons_rad, lats_rad, agrid)
   207     ij_loop : 
do ij = 1, lensfc
   209         mask_tile    = soilsnow_tile(ij)
   210         mask_fg_tile = soilsnow_fg_tile(ij)
   216         if (mask_tile <= 0) 
then    224         jtile = (ij-1) / idim + 1
   226         if (itile==0) itile = idim
   232         if (mask_fg_tile == 2 .or. mask_tile == 2) 
then   233          nsnowupd = nsnowupd + 1
   241         if (mask_tile == 1) 
then   243            igaus   = id1(itile,jtile)
   244            jgaus   = jdc(itile,jtile)
   245            igausp1 = id2(itile,jtile)
   246            jgausp1 = jdc(itile,jtile)+1
   249            gaus_has_soil = .false.
   255            if (.not. gaus_has_soil) 
then   256              nnosoilnear = nnosoilnear + 1
   267                    stc_inc(k)  = stc_inc(k) + (s2c(itile,jtile,1) * 
stc_inc_gaus(k,igaus,jgaus))
   269                    slc_inc(k)  = slc_inc(k) + (s2c(itile,jtile,1) * 
slc_inc_gaus(k,igaus,jgaus))
   271              wsum  = wsum + s2c(itile,jtile,1)
   277                    stc_inc(k) = stc_inc(k) + (s2c(itile,jtile,2) * 
stc_inc_gaus(k,igausp1,jgaus))
   279                    slc_inc(k) = slc_inc(k) + (s2c(itile,jtile,2) * 
slc_inc_gaus(k,igausp1,jgaus))
   281              wsum  = wsum + s2c(itile,jtile,2)
   287                    stc_inc(k) = stc_inc(k) + (s2c(itile,jtile,3) * 
stc_inc_gaus(k,igausp1,jgausp1))
   289                    slc_inc(k) = slc_inc(k) + (s2c(itile,jtile,3) * 
slc_inc_gaus(k,igausp1,jgausp1))
   291              wsum  = wsum + s2c(itile,jtile,3)
   297                    stc_inc(k) = stc_inc(k) + (s2c(itile,jtile,4) * 
stc_inc_gaus(k,igaus,jgausp1))
   299                    slc_inc(k) = slc_inc(k) + (s2c(itile,jtile,4) * 
slc_inc_gaus(k,igaus,jgausp1))
   301              wsum  = wsum + s2c(itile,jtile,4)
   306              stc_inc(k) = stc_inc(k) / wsum
   307              slc_inc(k) = slc_inc(k) / wsum
   317              if ( stc_state(ij,k) < tfreez)  soil_freeze=.true.
   318              if ( smc_state(ij,k) - slc_state(ij,k) > 0.001 )  soil_ice=.true.
   321                 stc_state(ij,k) = stc_state(ij,k) + stc_inc(k)
   324                     nstcupd = nstcupd + 1
   328              if ( (stc_state(ij,k) < tfreez) .and. (.not. soil_freeze) .and. (k==1) ) & 
   329                    nfrozen_upd = nfrozen_upd + 1 
   332              if ( (.not. soil_freeze ) .and. (.not. soil_ice ) ) 
then    335                     nslcupd = nslcupd + 1
   339                    slc_state(ij,k) = max(slc_state(ij,k) + slc_inc(k), 0.0)
   340                    smc_state(ij,k) = max(smc_state(ij,k) + slc_inc(k), 0.0) 
   343                 if (k==1) nfrozen = nfrozen+1
   352     write(*,
'(a,i2)') 
'statistics of grids number processed for rank : ', myrank
   353     write(*,
'(a,i8)') 
' soil grid total', lensfc
   354     write(*,
'(a,i8)') 
' soil grid cells slc updated = ',nslcupd
   355     write(*,
'(a,i8)') 
' soil grid cells stc updated = ',nstcupd
   356     write(*,
'(a,i8)') 
' soil grid cells not updated, frozen = ',nfrozen
   357     write(*,
'(a,i8)') 
' soil grid cells update, became frozen = ',nfrozen_upd
   358     write(*,
'(a,i8)') 
' (not updated) soil grid cells, no soil nearby on gsi grid = ',nnosoilnear
   359     write(*,
'(a,i8)') 
' (not updated yet) snow grid cells = ', nsnowupd
   360     write(*,
'(a,i8)') 
' grid cells, without soil or snow = ', nother
   362     deallocate(id1, id2, jdc, s2c)
   364 end subroutine add_increment_soil
   378 subroutine add_increment_snow(snd_inc,mask,lensfc,snd)
   382     integer, 
intent(in)      :: lensfc
   383     real, 
intent(in)         :: snd_inc(lensfc)
   384     integer, 
intent(in)      :: mask(lensfc)
   385     real, 
intent(inout)      :: snd(lensfc)
   391         if (mask(i) > 0) 
then    392                 snd(i) = max( snd(i) + snd_inc(i), 0.)
   396 end subroutine add_increment_snow
   408 subroutine calculate_landinc_mask(smc,swe,vtype,lensfc,veg_type_landice,mask)
   412     integer, 
intent(in)           :: lensfc, veg_type_landice
   413     real, 
intent(in)              :: smc(lensfc), swe(lensfc)
   414     real, 
intent(in)              :: vtype(lensfc)
   415     integer, 
intent(out)          :: mask(lensfc)
   423         if (smc(i) .LT. 0.99) 
then   424           if (swe(i) .GT. 0.001) 
then    430         if ( nint(vtype(i)) ==  veg_type_landice  ) 
then    435 end subroutine calculate_landinc_mask
   465 subroutine apply_land_da_adjustments_soil(lsm, isot, ivegsrc,lensfc, &
   466                  lsoil, rsoiltype, mask, stc_bck, stc_adj, smc_adj, slc_adj, &
   467                  stc_updated, slc_updated, zsoil)
   470     use set_soilveg_snippet_mod, 
only: set_soilveg
   471     use sflx_snippet,    
only: frh2o
   475     integer, 
intent(in)           :: lsm, lensfc, lsoil, isot, ivegsrc
   476     real, 
intent(in)              :: rsoiltype(lensfc) 
   477     integer, 
intent(in)           :: mask(lensfc)
   478     real, 
intent(in)              :: stc_bck(lensfc, lsoil)
   479     integer, 
intent(in)           :: stc_updated(lensfc), slc_updated(lensfc)
   480     real, 
intent(inout)           :: smc_adj(lensfc,lsoil), slc_adj(lensfc,lsoil) 
   481     real, 
intent(inout)           :: stc_adj(lensfc, lsoil)
   482     real(kind=4), 
intent(in)      :: zsoil(lsoil)
   485     logical                       :: frzn_bck, frzn_anl
   486     logical                       :: soil_freeze, soil_ice
   488     integer                       :: i, l, n_freeze, n_thaw, ierr, n_revert
   489     integer                       :: myrank, soiltype, iret, n_stc, n_slc
   490     logical                       :: upd_slc, upd_stc
   494     real, 
parameter               :: tfreez=273.16
   495     real, 
dimension(30)           :: maxsmc, bb, satpsi
   496     real, 
dimension(4)            :: dz 
   498     call mpi_comm_rank(mpi_comm_world, myrank, ierr)
   500     if (lsm==lsm_noah) 
then    503     elseif (lsm==lsm_noahmp) 
then    511         call set_soilveg(isot, ivegsrc, maxsmc, bb, satpsi, iret)
   513             print *, 
'FATAL ERROR: problem in set_soilveg'   514             call mpi_abort(mpi_comm_world, 10, ierr)
   517         print *, 
'Adjusting noah model smc after stc DA update'   523           if (mask(i) > 0) 
then    525                frzn_bck = (stc_bck(i,l) .LT. tfreez )
   526                frzn_anl = (stc_adj(i,l) .LT. tfreez )
   528                if (frzn_bck .eqv. frzn_anl) 
then   530                elseif (frzn_bck .and. .not. frzn_anl) 
then   533                     n_freeze = n_freeze + 1
   537                soiltype = nint(rsoiltype(i))
   539                call frh2o(stc_adj(i,l), smc_adj(i,l),slc_adj(i,l), maxsmc(soiltype), &
   540                           bb(soiltype), satpsi(soiltype),slc_new)
   542                slc_adj(i,l) = max( min( slc_new, smc_adj(i,l)), 0.0 )
   546         print *, 
'adjusted: ', n_thaw,
' thawed,', n_freeze, 
' frozen'   552           print *, 
'Reverting frozen noah-mp model stc back to background'   558           if (stc_updated(i) == 1 ) 
then   564                    if ( min(stc_bck(i,l),stc_adj(i,l)) < tfreez)  soil_freeze=.true.
   565                    if ( smc_adj(i,l) - slc_adj(i,l) > 0.001 )  soil_ice=.true.
   566                    if ( soil_freeze .or. soil_ice ) 
then    568                       if (l==1) n_revert = n_revert+1
   569                       stc_adj(i,l)=stc_bck(i,l)
   580               dz(l) = -zsoil(l) + zsoil(l-1) 
   582           print *, 
'Applying soil moisture mins '    585           if (slc_updated(i) == 1 ) 
then    591                 slc_adj(i,l) = max( 0.001/dz(l), slc_adj(i,l) )
   592                 smc_adj(i,l) = max( 0.001/dz(l), smc_adj(i,l) )
   599         print *, 
'FATAL ERROR: unrecognised LSM,', lsm
   600         call mpi_abort(mpi_comm_world, 10, ierr)
   603     write(*,
'(a,i2)') 
'statistics of grids number processed for rank : ', myrank 
   604     write(*,
'(a,i8)') 
' soil grid total', lensfc
   605     write(*,
'(a,i8)') 
' soil grid cells with slc update', n_slc
   606     write(*,
'(a,i8)') 
' soil grid cells with stc update', n_stc
   607     write(*,
'(a,i8)') 
' soil grid cells reverted', n_revert
   609 end subroutine apply_land_da_adjustments_soil
   626 subroutine apply_land_da_adjustments_snd(lsm, lensfc, mask, swe_bck, snd_bck, snd_anl, swe_adj)
   629     use bulk_snow_module, 
only: calc_density
   633     integer, 
intent(in) :: lsm, lensfc
   634     integer, 
intent(in) :: mask(lensfc)
   635     real, 
intent(in)    :: swe_bck(lensfc), snd_bck(lensfc)
   636     real, 
intent(in)    :: snd_anl(lensfc)
   637     real, 
intent(inout)    :: swe_adj(lensfc)
   639     integer  :: ierr, myrank, i
   641     real     :: density(lensfc)
   643     call mpi_comm_rank(mpi_comm_world, myrank, ierr)
   645     if (lsm .NE. lsm_noah) 
then   646         print *, 
'FATAL ERROR: apply_land_da_adjustments not coded for models other than noah', lsm
   647         call mpi_abort(mpi_comm_world, 10, ierr)
   651    call calc_density(lensfc, mask, swe_bck, snd_bck, myrank, density)
   654         if ( mask(i)>0 ) 
then   655                 swe_adj(i) = snd_anl(i)*density(i)
   660 end subroutine apply_land_da_adjustments_snd
   662 end module land_increments
 integer, dimension(:,:), allocatable, public soilsnow_gaus
GSI soil / snow mask for land on the gaussian grid. 
 
integer, public idim_gaus
'i' dimension of GSI gaussian grid. 
 
subroutine, public remap_coef(is, ie, js, je, im, jm, lon, lat, id1, id2, jdc, s2c, agrid)
Generate the weights and index of the grids used in the bilinear interpolation. 
 
real, dimension(:,:,:), allocatable, public slc_inc_gaus
GSI soil moisture increments on the gaussian grid. 
 
real, dimension(:,:,:), allocatable, public stc_inc_gaus
GSI soil temperature increments on the gaussian grid. 
 
Module containing utility routines. 
 
This module contains routines that read and write data. 
 
integer, public jdim_gaus
'j' dimension of GSI gaussian grid.