global_cycle  1.13.0
cycle.f90
Go to the documentation of this file.
1 
4 
111  PROGRAM sfc_drv
112 
113  use mpi
114 
115  IMPLICIT NONE
116 !
117  CHARACTER(LEN=3) :: donst
118  INTEGER :: idim, jdim, lsoil, lugb, iy, im, id, ih, ialb
119  INTEGER :: isot, ivegsrc, lensfc, zsea1_mm, zsea2_mm, ierr
120  INTEGER :: nprocs, myrank, num_threads, num_parthds, max_tasks
121  REAL :: fh, deltsfc, zsea1, zsea2
122  LOGICAL :: use_ufo, do_nsst, do_lndinc, do_sfccycle, frac_grid
123 !
124  NAMELIST/namcyc/ idim,jdim,lsoil,lugb,iy,im,id,ih,fh,&
125  deltsfc,ialb,use_ufo,donst, &
126  do_sfccycle,isot,ivegsrc,zsea1_mm, &
127  zsea2_mm, max_tasks, do_lndinc, frac_grid
128 !
129  DATA idim,jdim,lsoil/96,96,4/
130  DATA iy,im,id,ih,fh/1997,8,2,0,0./
131  DATA lugb/51/, deltsfc/0.0/, ialb/1/, max_tasks/99999/
132  DATA isot/1/, ivegsrc/2/, zsea1_mm/0/, zsea2_mm/0/
133 !
134  CALL mpi_init(ierr)
135  CALL mpi_comm_size(mpi_comm_world, nprocs, ierr)
136  CALL mpi_comm_rank(mpi_comm_world, myrank, ierr)
137 
138  if (myrank==0) call w3tagb('GLOBAL_CYCLE',2018,0179,0055,'NP20')
139 
140  num_threads = num_parthds()
141 
142  print*
143  print*,"STARTING CYCLE PROGRAM ON RANK ", myrank
144  print*,"RUNNING WITH ", nprocs, "TASKS"
145  print*,"AND WITH ", num_threads, " THREADS."
146 
147  use_ufo = .false.
148  donst = "NO"
149  do_lndinc = .false.
150  do_sfccycle = .true.
151  frac_grid = .false.
152 
153  print*
154  print*,"READ NAMCYC NAMELIST."
155 
156  CALL baopenr(36, "fort.36", ierr)
157  READ(36, nml=namcyc)
158 !IF (MYRANK==0) WRITE(6,NAMCYC)
159 
160  IF (max_tasks < 99999 .AND. myrank > (max_tasks - 1)) THEN
161  print*,"USER SPECIFIED MAX NUMBER OF TASKS: ", max_tasks
162  print*,"WILL NOT RUN CYCLE PROGRAM ON RANK: ", myrank
163  GOTO 333
164  ENDIF
165 
166  lensfc = idim*jdim ! TOTAL NUMBER OF POINTS FOR THE CUBED-SPHERE TILE
167 
168  zsea1 = float(zsea1_mm) / 1000.0 ! CONVERT FROM MM TO METERS
169  zsea2 = float(zsea2_mm) / 1000.0
170 
171  IF (donst == "YES") THEN
172  do_nsst=.true.
173  ELSE
174  do_nsst=.false.
175  ENDIF
176 
177  print*
178  IF (myrank==0) print*,"LUGB,IDIM,JDIM,ISOT,IVEGSRC,LSOIL,DELTSFC,IY,IM,ID,IH,FH: ", &
179  lugb,idim,jdim,isot,ivegsrc,lsoil,deltsfc,iy,im,id,ih,fh
180 
181  CALL sfcdrv(lugb,idim,jdim,lensfc,lsoil,deltsfc, &
182  iy,im,id,ih,fh,ialb, &
183  use_ufo,do_nsst,do_sfccycle,do_lndinc, &
184  frac_grid,zsea1,zsea2,isot,ivegsrc,myrank)
185 
186  print*
187  print*,'CYCLE PROGRAM COMPLETED NORMALLY ON RANK: ', myrank
188 
189  333 CONTINUE
190 
191  CALL mpi_barrier(mpi_comm_world, ierr)
192 
193  if (myrank==0) call w3tage('GLOBAL_CYCLE')
194 
195  CALL mpi_finalize(ierr)
196 
197  stop
198 
199  END PROGRAM sfc_drv
200 
309  SUBROUTINE sfcdrv(LUGB, IDIM,JDIM,LENSFC,LSOIL,DELTSFC, &
310  IY,IM,ID,IH,FH,IALB, &
311  USE_UFO,DO_NSST,DO_SFCCYCLE,DO_LNDINC,&
312  FRAC_GRID,ZSEA1,ZSEA2,ISOT,IVEGSRC,MYRANK)
313 !
314  USE read_write_data
315  use machine
316  USE mpi
317  USE land_increments, ONLY: gaussian_to_fv3_interp, &
318  add_increment_soil, &
319  add_jedi_increment_snow, &
320  calculate_landinc_mask, &
321  apply_land_da_adjustments_soil, &
322  apply_land_da_adjustments_snd, &
323  lsm_noah, lsm_noahmp
324 
325  IMPLICIT NONE
326 
327  INTEGER, INTENT(IN) :: IDIM, JDIM, LENSFC, LSOIL, IALB
328  INTEGER, INTENT(IN) :: LUGB, IY, IM, ID, IH
329  INTEGER, INTENT(IN) :: ISOT, IVEGSRC, MYRANK
330 
331  LOGICAL, INTENT(IN) :: USE_UFO, DO_NSST,DO_SFCCYCLE
332  LOGICAL, INTENT(IN) :: DO_LNDINC, FRAC_GRID
333 
334  REAL, INTENT(IN) :: FH, DELTSFC, ZSEA1, ZSEA2
335 
336  INTEGER, PARAMETER :: NLUNIT=35
337  INTEGER, PARAMETER :: SZ_NML=1
338 
339  CHARACTER(LEN=5) :: TILE_NUM
340  CHARACTER(LEN=500) :: NST_FILE
341  CHARACTER(LEN=500) :: GSI_SOI_FILE,JEDI_SOI_FILE,JEDI_SNO_FILE
342  CHARACTER(LEN=4) :: INPUT_NML_FILE(SZ_NML)
343 
344  INTEGER :: I, IERR
345  INTEGER :: I_INDEX(LENSFC), J_INDEX(LENSFC)
346  INTEGER :: IDUM(IDIM,JDIM)
347  integer :: num_parthds, num_threads
348 
349  LOGICAL :: IS_NOAHMP
350  INTEGER :: LSM
351 
352  real(kind=kind_io8) :: min_ice(lensfc)
353 
354  REAL :: SLMASK(LENSFC), OROG(LENSFC)
355  REAL :: SIHFCS(LENSFC), SICFCS(LENSFC)
356  REAL :: SITFCS(LENSFC), TSFFCS(LENSFC)
357  REAL :: SWEFCS(LENSFC), ZORFCS(LENSFC)
358  REAL :: ALBFCS(LENSFC,4), TG3FCS(LENSFC)
359  REAL :: CNPFCS(LENSFC), SMCFCS(LENSFC,LSOIL)
360  REAL :: STCFCS(LENSFC,LSOIL), SLIFCS(LENSFC)
361  REAL :: AISFCS(LENSFC), F10M(LENSFC)
362  REAL :: VEGFCS(LENSFC), VETFCS(LENSFC)
363  REAL :: SOTFCS(LENSFC), ALFFCS(LENSFC,2)
364  REAL :: CVFCS(LENSFC), CVTFCS(LENSFC)
365  REAL :: CVBFCS(LENSFC), TPRCP(LENSFC)
366  REAL :: SRFLAG(LENSFC), SNDFCS(LENSFC)
367  REAL :: SLCFCS(LENSFC,LSOIL), VMXFCS(LENSFC)
368  REAL :: VMNFCS(LENSFC), T2M(LENSFC)
369  REAL :: Q2M(LENSFC), SLPFCS(LENSFC)
370  REAL :: ABSFCS(LENSFC), OROG_UF(LENSFC)
371  REAL :: USTAR(LENSFC), SOCFCS(LENSFC)
372  REAL :: FMM(LENSFC), FHH(LENSFC)
373  REAL :: RLA(LENSFC), RLO(LENSFC)
374  REAL(KIND=4) :: ZSOIL(LSOIL)
375  REAL :: SIG1T(LENSFC)
378  REAL, ALLOCATABLE :: STC_BCK(:,:), SMC_BCK(:,:), SLC_BCK(:,:)
379  REAL, ALLOCATABLE :: SLIFCS_FG(:), SICFCS_FG(:)
380  INTEGER, ALLOCATABLE :: LANDINC_MASK_FG(:), LANDINC_MASK(:)
381  REAL, ALLOCATABLE :: SND_BCK(:), SND_INC(:), SWE_BCK(:)
382  REAL(KIND=KIND_IO8), ALLOCATABLE :: SLMASKL(:), SLMASKW(:), LANDFRAC(:)
383 
384  TYPE(NSST_DATA) :: NSST
385  real, dimension(idim,jdim) :: tf_clm,tf_trd,sal_clm
386  real, dimension(lensfc) :: tf_clm_tile,tf_trd_tile,sal_clm_tile
387  INTEGER :: veg_type_landice
388  INTEGER, DIMENSION(LENSFC) :: STC_UPDATED, SLC_UPDATED
389  REAL, DIMENSION(LENSFC,LSOIL) :: STCINC, SLCINC
390 
391  LOGICAL :: FILE_EXISTS, DO_SOI_INC_GSI, DO_SOI_INC_JEDI, DO_SNO_INC_JEDI
392  CHARACTER(LEN=3) :: RANKCH
393  INTEGER :: lsoil_incr
394 
395 !--------------------------------------------------------------------------------
396 ! NST_FILE is the path/name of the gaussian GSI file which contains NSST
397 ! increments.
398 !--------------------------------------------------------------------------------
399 
400  NAMELIST/namsfcd/ nst_file, lsoil_incr, do_sno_inc_jedi, do_soi_inc_jedi, do_soi_inc_gsi
401 
402  DATA nst_file/'NULL'/
403 
404  do_sno_inc_jedi = .false.
405  do_soi_inc_gsi = .false.
406  do_soi_inc_jedi = .false.
407  lsoil_incr = 3 !default
408 
409 
410  sig1t = 0.0 ! Not a dead start!
411 
412  input_nml_file = "NULL"
413 
414  CALL baopenr(37, "fort.37", ierr)
415  READ (37, nml=namsfcd)
416 
417  print*
418  print*,'IN ROUTINE SFCDRV,IDIM=',idim,'JDIM=',jdim,'FH=',fh
419 
420 !--------------------------------------------------------------------------------
421 ! READ THE OROGRAPHY AND GRID POINT LAT/LONS FOR THE CUBED-SPHERE TILE.
422 !--------------------------------------------------------------------------------
423 
424  ALLOCATE(landfrac(lensfc))
425  IF(frac_grid) THEN
426  print*,'- RUNNING WITH FRACTIONAL GRID.'
427  CALL read_lat_lon_orog(rla,rlo,orog,orog_uf,tile_num,idim,jdim,lensfc,landfrac=landfrac)
428  ELSE
429  CALL read_lat_lon_orog(rla,rlo,orog,orog_uf,tile_num,idim,jdim,lensfc)
430  landfrac=-999.9
431  ENDIF
432 
433  DO i = 1, idim
434  idum(i,:) = i
435  ENDDO
436 
437  i_index = reshape(idum, (/lensfc/))
438 
439  DO i = 1, jdim
440  idum(:,i) = i
441  ENDDO
442 
443  j_index = reshape(idum, (/lensfc/) )
444 
445  IF (do_nsst) THEN
446  print*
447  print*,"WILL PROCESS NSST RECORDS."
448  ALLOCATE(nsst%C_0(lensfc))
449  ALLOCATE(nsst%C_D(lensfc))
450  ALLOCATE(nsst%D_CONV(lensfc))
451  ALLOCATE(nsst%DT_COOL(lensfc))
452  ALLOCATE(nsst%IFD(lensfc))
453  ALLOCATE(nsst%QRAIN(lensfc))
454  ALLOCATE(nsst%TREF(lensfc))
455  ALLOCATE(nsst%TFINC(lensfc))
456  ALLOCATE(nsst%W_0(lensfc))
457  ALLOCATE(nsst%W_D(lensfc))
458  ALLOCATE(nsst%XS(lensfc))
459  ALLOCATE(nsst%XT(lensfc))
460  ALLOCATE(nsst%XTTS(lensfc))
461  ALLOCATE(nsst%XU(lensfc))
462  ALLOCATE(nsst%XV(lensfc))
463  ALLOCATE(nsst%XZ(lensfc))
464  ALLOCATE(nsst%XZTS(lensfc))
465  ALLOCATE(nsst%Z_C(lensfc))
466  ALLOCATE(nsst%ZM(lensfc))
467  ALLOCATE(slifcs_fg(lensfc))
468  ALLOCATE(sicfcs_fg(lensfc))
469  ENDIF
470 
471 IF (do_lndinc) THEN
472  ! identify variables to be updated, and allocate arrays.
473  IF (do_soi_inc_gsi .and. do_soi_inc_jedi) THEN
474  print*
475  print*, 'FATAL ERROR: Can not do gsi and jedi soil updates at the same time, choose one!'
476  CALL mpi_abort(mpi_comm_world, 15, ierr)
477  ENDIF
478  IF (do_soi_inc_gsi .or. do_soi_inc_jedi) THEN
479  print*
480  print*," APPLYING SOIL INCREMENTS FROM GSI OR JEDI"
481  ALLOCATE(stc_bck(lensfc, lsoil), smc_bck(lensfc, lsoil), slc_bck(lensfc,lsoil))
482  ALLOCATE(landinc_mask_fg(lensfc))
483  ENDIF
484  ! FOR NOW, CODE SO CAN DO BOTH, BUT MIGHT NEED TO THINK ABOUT THIS SOME MORE.
485  IF (do_sno_inc_jedi) THEN
486  ! ideally, would check here that sfcsub snow DA update is not also requested
487  ! but latter is controlled by fnsol, which is read in within that routine.
488  ! should be done at script level.
489  print*
490  print*," APPLYING SNOW INCREMENTS FROM JEDI"
491  ALLOCATE(snd_bck(lensfc), snd_inc(lensfc), swe_bck(lensfc))
492  ENDIF
493  ! set-up land mask info
494  ALLOCATE(landinc_mask(lensfc))
495  if (ivegsrc == 2) then ! sib
496  veg_type_landice=13
497  else
498  veg_type_landice=15
499  endif
500 ENDIF
501 
502 !--------------------------------------------------------------------------------
503 ! READ THE INPUT SURFACE DATA ON THE CUBED-SPHERE TILE.
504 !--------------------------------------------------------------------------------
505 
506  CALL read_data(lsoil,lensfc,do_nsst,do_sno_inc_jedi,do_soi_inc_jedi,.false.,is_noahmp=is_noahmp, &
507  tsffcs=tsffcs,smcfcs=smcfcs, &
508  swefcs=swefcs,stcfcs=stcfcs,tg3fcs=tg3fcs,zorfcs=zorfcs, &
509  cvfcs=cvfcs, cvbfcs=cvbfcs,cvtfcs=cvtfcs,albfcs=albfcs, &
510  vegfcs=vegfcs,slifcs=slifcs,cnpfcs=cnpfcs,f10m=f10m , &
511  vetfcs=vetfcs,sotfcs=sotfcs,alffcs=alffcs,ustar=ustar , &
512  fmm=fmm ,fhh=fhh ,sihfcs=sihfcs,sicfcs=sicfcs, &
513  sitfcs=sitfcs,tprcp=tprcp ,srflag=srflag,sndfcs=sndfcs, &
514  vmnfcs=vmnfcs,vmxfcs=vmxfcs,slcfcs=slcfcs,slpfcs=slpfcs, &
515  absfcs=absfcs,t2m=t2m ,q2m=q2m ,slmask=slmask, &
516  zsoil=zsoil, nsst=nsst)
517 
518  IF (frac_grid .AND. .NOT. is_noahmp) THEN
519  print *, 'FATAL ERROR: NOAH lsm update does not work with fractional grids.'
520  call mpi_abort(mpi_comm_world, 18, ierr)
521  ENDIF
522 
523  IF (is_noahmp .AND. do_sno_inc_jedi) THEN
524  print *, 'FATAL ERROR: Snow increment update does not work with NOAH_MP.'
525  call mpi_abort(mpi_comm_world, 29, ierr)
526  ENDIF
527 
528  IF (is_noahmp) THEN
529  lsm=lsm_noahmp
530  ELSE
531  lsm=lsm_noah
532  ENDIF
533 
534  IF (use_ufo) THEN
535  print*
536  print*,'USE UNFILTERED OROGRAPHY.'
537  ELSE
538  orog_uf = 0.0
539  ENDIF
540 
541  DO i=1,lensfc
542  aisfcs(i) = 0.
543  IF(nint(slifcs(i)).EQ.2) aisfcs(i) = 1.
544  ENDDO
545 
546  IF (do_nsst) THEN
547  sicfcs_fg=sicfcs
548  IF (.NOT. do_sfccycle ) THEN
549  print*
550  print*,"FIRST GUESS MASK ADJUSTED BY IFD RECORD"
551  slifcs_fg = slifcs
552  WHERE(nint(nsst%IFD) == 3) slifcs_fg = 2.0
553  ELSE
554  print*
555  print*,"SAVE FIRST GUESS MASK"
556  slifcs_fg = slifcs
557  ENDIF
558  ENDIF
559 
560  ! CALCULATE MASK FOR LAND INCREMENTS
561  IF (do_lndinc) &
562  CALL calculate_landinc_mask(swefcs, vetfcs, sotfcs, &
563  lensfc,veg_type_landice, landinc_mask)
564 
565 !--------------------------------------------------------------------------------
566 ! UPDATE SURFACE FIELDS.
567 !
568 ! FIRST, SET WATER AND LAND MASKS - SLMASKW/SLMASKL. FOR UNCOUPLED
569 ! (NON-FRACTIONAL) MODE, THESE ARE IDENTICAL TO THE CURRENT
570 ! MASK - '0' WATER; '1' LAND.
571 !--------------------------------------------------------------------------------
572 
573  IF (do_sfccycle) THEN
574  ALLOCATE(slmaskl(lensfc), slmaskw(lensfc))
575 
576  set_mask : IF (frac_grid) THEN
577 
578  DO i=1,lensfc
579  IF(landfrac(i) > 0.0_kind_io8) THEN
580  slmaskl(i) = ceiling(landfrac(i)-1.0e-6_kind_io8)
581  slmaskw(i) = floor(landfrac(i)+1.0e-6_kind_io8)
582  ELSE
583  IF(nint(slmask(i)) == 1) THEN ! If landfrac is zero, this should not happen.
584  ! So, stop processing.
585  print*, 'FATAL ERROR: LAND FRAC AND SLMASK MISMATCH.'
586  CALL mpi_abort(mpi_comm_world, 27, ierr)
587  ELSE
588  slmaskl(i) = 0.0_kind_io8
589  slmaskw(i) = 0.0_kind_io8
590  ENDIF
591  ENDIF
592 
593  ENDDO
594 
595  ELSE
596 
597 ! For running uncoupled (non-fractional grid).
598 
599  DO i=1,lensfc
600  IF(nint(slmask(i)) == 1) THEN
601  slmaskl(i) = 1.0_kind_io8
602  slmaskw(i) = 1.0_kind_io8
603  ELSE
604  slmaskl(i) = 0.0_kind_io8
605  slmaskw(i) = 0.0_kind_io8
606  ENDIF
607  ENDDO
608 
609  ENDIF set_mask
610 
611  DO i=1,lensfc
612  if(nint(slmask(i)) == 0) then
613  min_ice(i) = 0.15_kind_io8
614  else
615  min_ice(i) = 0.0_kind_io8
616  endif
617  ENDDO
618 
619  socfcs=0 ! Soil color. Not used yet.
620 
621  num_threads = num_parthds()
622  print*
623  print*,"CALL SFCCYCLE TO UPDATE SURFACE FIELDS."
624  CALL sfccycle(lugb,lensfc,lsoil,sig1t,deltsfc, &
625  iy,im,id,ih,fh,rla,rlo, &
626  slmaskl,slmaskw, orog, orog_uf, use_ufo, do_nsst, &
627  sihfcs,sicfcs,sitfcs,sndfcs,slcfcs, &
628  vmnfcs,vmxfcs,slpfcs,absfcs, &
629  tsffcs,swefcs,zorfcs,albfcs,tg3fcs, &
630  cnpfcs,smcfcs,stcfcs,slifcs,aisfcs, &
631  vegfcs,vetfcs,sotfcs,socfcs,alffcs, &
632  cvfcs,cvbfcs,cvtfcs,myrank,num_threads, nlunit, &
633  sz_nml, input_nml_file, &
634  min_ice, &
635  ialb,isot,ivegsrc,tile_num,i_index,j_index)
636 
637  DEALLOCATE(slmaskl, slmaskw)
638  ENDIF
639 
640 !--------------------------------------------------------------------------------
641 ! IF RUNNING WITH NSST, READ IN GSI FILE WITH THE UPDATED INCREMENTS (ON THE
642 ! GAUSSIAN GRID), INTERPOLATE INCREMENTS TO THE CUBED-SPHERE TILE, AND PERFORM
643 ! REQUIRED ADJUSTMENTS AND QC.
644 !--------------------------------------------------------------------------------
645 
646  IF (do_nsst) THEN
647  IF (nst_file == "NULL") THEN
648  print*
649  print*,"NO GSI FILE. ADJUST IFD FOR FORMER ICE POINTS."
650  DO i = 1, lensfc
651  IF (sicfcs_fg(i) > 0.0 .AND. sicfcs(i) == 0) THEN
652  nsst%IFD(i) = 3.0
653  ENDIF
654  ENDDO
655  nsst%TFINC = 0.0
656  ELSE
657  print*
658  print*,"ADJUST TREF FROM GSI INCREMENT"
659 !
660 ! Get tf climatology at the time
661 !
662  call get_tf_clm(rla,rlo,jdim,idim,iy,im,id,ih,tf_clm,tf_trd)
663  tf_clm_tile(:) = reshape(tf_clm, (/lensfc/) )
664  tf_trd_tile(:) = reshape(tf_trd, (/lensfc/) )
665 !
666 ! Get salinity climatology at the time
667 !
668  call get_sal_clm(rla,rlo,jdim,idim,iy,im,id,ih,sal_clm)
669  sal_clm_tile(:) = reshape(sal_clm, (/lensfc/) )
670 !
671 ! read tf analysis increment generated by GSI
672 !
673  CALL read_gsi_data(nst_file, 'NST')
674 !
675 ! update foundation & surface temperature for NSST
676 !
677  CALL adjust_nsst(rla,rlo,slifcs,slifcs_fg,tsffcs,sitfcs,sicfcs,sicfcs_fg,&
678  stcfcs,nsst,lensfc,lsoil,idim,jdim,zsea1,zsea2, &
679  tf_clm_tile,tf_trd_tile,sal_clm_tile,landfrac,frac_grid)
680  ENDIF
681  ENDIF
682 
683 !--------------------------------------------------------------------------------
684 ! READ IN AND APPLY LAND INCREMENTS FROM THE GSI/JEDI
685 !--------------------------------------------------------------------------------
686 
687  IF (do_lndinc) THEN
688 
689  ! SNOW INCREMENTS
690  ! do snow first, as temperature updates will use snow analaysis
691  IF (do_sno_inc_jedi) THEN
692  ! updates are made to snow depth only over land (and not-land ice).
693  ! SWE is then updated from the snow depth analysis, using the model
694  ! forecast density
695 
696  ! make sure incr. files exist
697  WRITE(rankch, '(I3.3)') (myrank+1)
698  jedi_sno_file = "snow_xainc." // rankch
699 
700  INQUIRE(file=trim(jedi_sno_file), exist=file_exists)
701  IF (.not. file_exists) then
702  print *, 'FATAL ERROR: snow increment (fv3 grid) update requested, &
703  but file does not exist : ', trim(jedi_sno_file)
704  call mpi_abort(mpi_comm_world, 10, ierr)
705  ENDIF
706 
707  !--------------------------------------------------------------------------------
708  ! read increments in
709  !--------------------------------------------------------------------------------
710 
711  ! Only coded for DA on native model grid (would always be the case for cycling DA)
712  CALL read_data(lsoil,lensfc,.false.,.true.,.false.,.true.,sndfcs=snd_inc)
713 
714  !--------------------------------------------------------------------------------
715  ! add increments to state vars
716  !--------------------------------------------------------------------------------
717 
718  ! store background states
719  snd_bck = sndfcs
720  swe_bck = swefcs
721 
722  CALL add_jedi_increment_snow(snd_inc,landinc_mask,lensfc,sndfcs)
723 
724  !--------------------------------------------------------------------------------
725  ! make any necessary adjustments to dependent variables
726  !--------------------------------------------------------------------------------
727 
728  CALL apply_land_da_adjustments_snd(lsm, lensfc, landinc_mask, swe_bck, snd_bck, &
729  sndfcs, swefcs)
730 
731  ENDIF ! jedi snow increments
732 
733  !re-calculate soilsnow mask if snow has been updated.
734  landinc_mask_fg = landinc_mask
735 
736  IF (do_sfccycle .OR. do_sno_inc_jedi) THEN
737  CALL calculate_landinc_mask(swefcs, vetfcs, sotfcs, lensfc, &
738  veg_type_landice, landinc_mask)
739  ENDIF
740 
741  ! store background states
742  stc_bck = stcfcs
743  smc_bck = smcfcs
744  slc_bck = slcfcs
745 
746  ! SOIL INCREMENTS
747  IF (do_soi_inc_gsi) THEN
748 
749  !--------------------------------------------------------------------------------
750  ! read increments in
751  !--------------------------------------------------------------------------------
752  ! make sure incr. files exist
753  WRITE(rankch, '(I3.3)') (myrank+1)
754  gsi_soi_file = "sfcincr_gsi." // rankch
755 
756  INQUIRE(file=trim(gsi_soi_file), exist=file_exists)
757  IF (.not. file_exists) then
758  print *, 'FATAL ERROR: gsi soil increment (gaussian grid) update requested, &
759  but file does not exist : ', trim(gsi_soi_file)
760  call mpi_abort(mpi_comm_world, 10, ierr)
761  ENDIF
762 
763  CALL read_gsi_data(gsi_soi_file, 'LND', lsoil=lsoil)
764 
765  !--------------------------------------------------------------------------------
766  ! interpolate increments to cubed sphere tiles
767  !--------------------------------------------------------------------------------
768 
769  CALL gaussian_to_fv3_interp(lsoil_incr,rla,rlo,&
770  stcinc,slcinc,landinc_mask,lensfc,lsoil,idim,jdim,lsm,myrank)
771 
772  !--------------------------------------------------------------------------------
773  ! save interpolated increments
774  !--------------------------------------------------------------------------------
775  CALL write_data(lensfc,idim,jdim,lsoil,do_nsst,.true.,nsst, &
776  stcinc=stcinc,slcinc=slcinc)
777 
778  ENDIF ! end reading and interpolating gsi soil increments
779 
780  IF (do_soi_inc_jedi) THEN
781 
782  !--------------------------------------------------------------------------------
783  ! read increments in
784  !--------------------------------------------------------------------------------
785  ! make sure incr. files exist
786  WRITE(rankch, '(I3.3)') (myrank+1)
787  jedi_soi_file = "soil_xainc." // rankch
788 
789  INQUIRE(file=trim(jedi_soi_file), exist=file_exists)
790  IF (.not. file_exists) then
791  print *, 'FATAL ERROR: soil increment (fv3 grid) update requested, but file &
792  does not exist: ', trim(jedi_soi_file)
793  call mpi_abort(mpi_comm_world, 10, ierr)
794  ENDIF
795 
796  CALL read_data(lsoil,lensfc,.false.,.false.,.true., &
797  .true.,is_noahmp=is_noahmp, &
798  stcinc=stcinc,slcinc=slcinc)
799 
800  ENDIF ! end reading jedi soil increments
801 
802  IF (do_soi_inc_gsi .or. do_soi_inc_jedi) THEN
803 
804  !--------------------------------------------------------------------------------
805  ! add increments to state vars
806  !--------------------------------------------------------------------------------
807 
808  ! below updates [STC/SMC/STC]FCS to hold the analysis
809  CALL add_increment_soil(lsoil_incr,stcinc,slcinc,stcfcs,smcfcs,slcfcs,stc_updated, &
810  slc_updated,landinc_mask,landinc_mask_fg,lensfc,lsoil,lsm,myrank)
811 
812  !--------------------------------------------------------------------------------
813  ! make any necessary adjustments to dependent variables
814  !--------------------------------------------------------------------------------
815 
816  CALL apply_land_da_adjustments_soil(lsoil_incr, lsm, isot, ivegsrc,lensfc, lsoil, &
817  sotfcs, landinc_mask_fg, stc_bck, stcfcs, smcfcs, slcfcs, stc_updated, &
818  slc_updated,zsoil)
819 
820 
821  ENDIF ! end applying soil increments and making adjustments
822 
823 !--------------------------------------------------------------------------------
824 ! clean up
825 !--------------------------------------------------------------------------------
826 
827  IF(ALLOCATED(landinc_mask_fg)) DEALLOCATE(landinc_mask_fg)
828  IF(ALLOCATED(landinc_mask)) DEALLOCATE(landinc_mask)
829  IF(ALLOCATED(stc_bck)) DEALLOCATE(stc_bck)
830  IF(ALLOCATED(smc_bck)) DEALLOCATE(smc_bck)
831  IF(ALLOCATED(slc_bck)) DEALLOCATE(slc_bck)
832  IF(ALLOCATED(snd_bck)) DEALLOCATE(snd_bck)
833  IF(ALLOCATED(swe_bck)) DEALLOCATE(swe_bck)
834  IF(ALLOCATED(snd_inc)) DEALLOCATE(snd_inc)
835 
836  ENDIF
837 !--------------------------------------------------------------------------------
838 ! WRITE OUT UPDATED SURFACE DATA ON THE CUBED-SPHERE TILE.
839 !--------------------------------------------------------------------------------
840 
841  IF (lsm==lsm_noahmp) THEN
842 
843  CALL write_data(lensfc,idim,jdim,lsoil,do_nsst,.false.,nsst,vegfcs=vegfcs, &
844  slcfcs=slcfcs,smcfcs=smcfcs,stcfcs=stcfcs,&
845  sicfcs=sicfcs,sihfcs=sihfcs)
846 
847  ELSEIF (lsm==lsm_noah) THEN
848 
849  CALL write_data(lensfc,idim,jdim,lsoil, &
850  do_nsst,.false.,nsst,slifcs=slifcs,tsffcs=tsffcs,vegfcs=vegfcs, &
851  swefcs=swefcs,tg3fcs=tg3fcs,zorfcs=zorfcs, &
852  albfcs=albfcs,alffcs=alffcs,cnpfcs=cnpfcs, &
853  f10m=f10m,t2m=t2m,q2m=q2m,vetfcs=vetfcs, &
854  sotfcs=sotfcs,ustar=ustar,fmm=fmm,fhh=fhh, &
855  sicfcs=sicfcs,sihfcs=sihfcs,sitfcs=sitfcs,tprcp=tprcp, &
856  srflag=srflag,swdfcs=sndfcs,vmnfcs=vmnfcs, &
857  vmxfcs=vmxfcs,slpfcs=slpfcs,absfcs=absfcs, &
858  slcfcs=slcfcs,smcfcs=smcfcs,stcfcs=stcfcs)
859 
860  ENDIF
861 
862  IF (do_nsst) THEN
863  DEALLOCATE(nsst%C_0)
864  DEALLOCATE(nsst%C_D)
865  DEALLOCATE(nsst%D_CONV)
866  DEALLOCATE(nsst%DT_COOL)
867  DEALLOCATE(nsst%IFD)
868  DEALLOCATE(nsst%QRAIN)
869  DEALLOCATE(nsst%TREF)
870  DEALLOCATE(nsst%TFINC)
871  DEALLOCATE(nsst%W_0)
872  DEALLOCATE(nsst%W_D)
873  DEALLOCATE(nsst%XS)
874  DEALLOCATE(nsst%XT)
875  DEALLOCATE(nsst%XTTS)
876  DEALLOCATE(nsst%XU)
877  DEALLOCATE(nsst%XV)
878  DEALLOCATE(nsst%XZ)
879  DEALLOCATE(nsst%XZTS)
880  DEALLOCATE(nsst%Z_C)
881  DEALLOCATE(nsst%ZM)
882  DEALLOCATE(slifcs_fg)
883  DEALLOCATE(sicfcs_fg)
884  ENDIF
885 
886  RETURN
887 
888  END SUBROUTINE sfcdrv
889 
921  SUBROUTINE adjust_nsst(RLA,RLO,SLMSK_TILE,SLMSK_FG_TILE,SKINT_TILE,&
922  SICET_TILE,sice_tile,sice_fg_tile,SOILT_TILE,NSST, &
923  LENSFC,LSOIL,IDIM,JDIM,ZSEA1,ZSEA2, &
924  tf_clm_tile,tf_trd_tile,sal_clm_tile,LANDFRAC, &
925  FRAC_GRID)
927  USE utils
928  USE gdswzd_mod
929  USE read_write_data, ONLY : idim_gaus, jdim_gaus, &
931  nsst_data
932 
933  USE mpi
934 
935  IMPLICIT NONE
936 
937  INTEGER, INTENT(IN) :: LENSFC, LSOIL, IDIM, JDIM
938 
939  LOGICAL, INTENT(IN) :: FRAC_GRID
940 
941  REAL, INTENT(IN) :: SLMSK_TILE(LENSFC), SLMSK_FG_TILE(LENSFC), LANDFRAC(LENSFC)
942  real, intent(in) :: tf_clm_tile(lensfc),tf_trd_tile(lensfc),sal_clm_tile(lensfc)
943  REAL, INTENT(IN) :: ZSEA1, ZSEA2,sice_tile(lensfc),sice_fg_tile(lensfc)
944  REAL, INTENT(IN) :: RLA(LENSFC), RLO(LENSFC)
945  REAL, INTENT(INOUT) :: SKINT_TILE(LENSFC)
946  REAL, INTENT(INOUT) :: SICET_TILE(LENSFC),SOILT_TILE(LENSFC,LSOIL)
947 
948  TYPE(NSST_DATA) :: NSST
949 
950  REAL, PARAMETER :: TMAX=313.0,tzero=273.16
951 
952  INTEGER :: IOPT, NRET, KGDS_GAUS(200)
953  INTEGER :: IGAUS, JGAUS, IJ, II, JJ, III, JJJ, KRAD
954  INTEGER :: ISTART, IEND, JSTART, JEND
955 !INTEGER :: MASK_TILE, MASK_FG_TILE
956  INTEGER,allocatable :: MASK_TILE(:),MASK_FG_TILE(:)
957  INTEGER :: ITILE, JTILE
958  INTEGER :: MAX_SEARCH, J, IERR
959  INTEGER :: IGAUSP1, JGAUSP1
960  integer :: nintp,nsearched,nice,nland
961  integer :: nfill,nfill_tice,nfill_clm
962  integer :: nset_thaw,nset_thaw_s,nset_thaw_i,nset_thaw_c
963 
964  INTEGER, ALLOCATABLE :: ID1(:,:), ID2(:,:), JDC(:,:)
965 
966  LOGICAL :: IS_ICE
967 
968  real :: tfreez
969  REAL :: TREF_SAVE,WSUM,tf_ice,tf_thaw
970  REAL :: FILL, DTZM, GAUS_RES_KM, DTREF
971  REAL, ALLOCATABLE :: XPTS(:), YPTS(:), LATS(:), LONS(:)
972  REAL, ALLOCATABLE :: DUM2D(:,:), LATS_RAD(:), LONS_RAD(:)
973  REAL, ALLOCATABLE :: AGRID(:,:,:), S2C(:,:,:)
974 
975  kgds_gaus = 0
976  kgds_gaus(1) = 4 ! OCT 6 - TYPE OF GRID (GAUSSIAN)
977  kgds_gaus(2) = idim_gaus ! OCT 7-8 - # PTS ON LATITUDE CIRCLE
978  kgds_gaus(3) = jdim_gaus
979  kgds_gaus(4) = 90000 ! OCT 11-13 - LAT OF ORIGIN
980  kgds_gaus(5) = 0 ! OCT 14-16 - LON OF ORIGIN
981  kgds_gaus(6) = 128 ! OCT 17 - RESOLUTION FLAG
982  kgds_gaus(7) = -90000 ! OCT 18-20 - LAT OF EXTREME POINT
983  kgds_gaus(8) = nint(-360000./float(idim_gaus)) ! OCT 21-23 - LON OF EXTREME POINT
984  kgds_gaus(9) = nint((360.0 / float(idim_gaus))*1000.0)
985  ! OCT 24-25 - LONGITUDE DIRECTION INCR.
986  kgds_gaus(10) = jdim_gaus/2 ! OCT 26-27 - NUMBER OF CIRCLES POLE TO EQUATOR
987  kgds_gaus(12) = 255 ! OCT 29 - RESERVED
988  kgds_gaus(20) = 255 ! OCT 5 - NOT USED, SET TO 255
989 
990  print*
991  print*,'ADJUST NSST USING GSI INCREMENTS ON GAUSSIAN GRID'
992 
993 !----------------------------------------------------------------------
994 ! CALL GDSWZD TO COMPUTE THE LAT/LON OF EACH GSI GAUSSIAN GRID POINT.
995 !----------------------------------------------------------------------
996 
997  iopt = 0
998  fill = -9999.
999  ALLOCATE(xpts(idim_gaus*jdim_gaus))
1000  ALLOCATE(ypts(idim_gaus*jdim_gaus))
1001  ALLOCATE(lats(idim_gaus*jdim_gaus))
1002  ALLOCATE(lons(idim_gaus*jdim_gaus))
1003  xpts = fill
1004  ypts = fill
1005  lats = fill
1006  lons = fill
1007 
1008  CALL gdswzd(kgds_gaus,iopt,(idim_gaus*jdim_gaus),fill,xpts,ypts,lons,lats,nret)
1009 
1010  IF (nret /= (idim_gaus*jdim_gaus)) THEN
1011  print*,'FATAL ERROR: PROBLEM IN GDSWZD. STOP.'
1012  CALL mpi_abort(mpi_comm_world, 12, ierr)
1013  ENDIF
1014 
1015  DEALLOCATE (xpts, ypts)
1016 
1017  ALLOCATE(dum2d(idim_gaus,jdim_gaus))
1018  dum2d = reshape(lats, (/idim_gaus,jdim_gaus/) )
1019  DEALLOCATE(lats)
1020 
1021  ALLOCATE(lats_rad(jdim_gaus))
1022  DO j = 1, jdim_gaus
1023  lats_rad(j) = dum2d(1,jdim_gaus-j+1) * 3.1415926 / 180.0
1024  ENDDO
1025 
1026  dum2d = reshape(lons, (/idim_gaus,jdim_gaus/) )
1027  DEALLOCATE(lons)
1028  ALLOCATE(lons_rad(idim_gaus))
1029  lons_rad = dum2d(:,1) * 3.1415926 / 180.0
1030 
1031  DEALLOCATE(dum2d)
1032 
1033  ALLOCATE(agrid(idim,jdim,2))
1034  agrid(:,:,1) = reshape(rlo, (/idim,jdim/) )
1035  agrid(:,:,2) = reshape(rla, (/idim,jdim/) )
1036  agrid = agrid * 3.1415926 / 180.0
1037 
1038  ALLOCATE(id1(idim,jdim))
1039  ALLOCATE(id2(idim,jdim))
1040  ALLOCATE(jdc(idim,jdim))
1041  ALLOCATE(s2c(idim,jdim,4))
1042 
1043 !----------------------------------------------------------------------
1044 ! COMPUTE BILINEAR WEIGHTS FOR EACH MODEL POINT FROM THE NEAREST
1045 ! FOUR GSI/GAUSSIAN POINTS. DOES NOT ACCOUNT FOR MASK. THAT
1046 ! HAPPENS LATER.
1047 !----------------------------------------------------------------------
1048 
1049  CALL remap_coef( 1, idim, 1, jdim, idim_gaus, jdim_gaus, &
1050  lons_rad, lats_rad, id1, id2, jdc, s2c, agrid )
1051 
1052  DEALLOCATE(lons_rad, lats_rad, agrid)
1053 
1054 !----------------------------------------------------------------------
1055 ! THE MAXIMUM DISTANCE TO SEARCH IS 500 KM. HOW MANY GAUSSIAN
1056 ! GRID LENGTHS IS THAT?
1057 !----------------------------------------------------------------------
1058 
1059  gaus_res_km = 360.0 / idim_gaus * 111.0
1060  max_search = ceiling(500.0/gaus_res_km)
1061 
1062  print*
1063  print*,'MAXIMUM SEARCH IS ',max_search, ' GAUSSIAN POINTS.'
1064  print*
1065 
1066 !
1067 ! Initialize variables for counts statitics to be zeros
1068 !
1069  nintp = 0
1070  nset_thaw = 0
1071  nset_thaw_s = 0
1072  nset_thaw_i = 0
1073  nset_thaw_c = 0
1074  nsearched = 0
1075  nfill = 0
1076  nfill_tice = 0
1077  nfill_clm = 0
1078  nice = 0
1079  nland = 0
1080 !----------------------------------------------------------------------
1081 ! TREF INCREMENT WILL BE OUTPUT. INITIALIZE TO ZERO.
1082 !----------------------------------------------------------------------
1083 
1084  nsst%TFINC = 0.0
1085 
1086  allocate(mask_tile(lensfc))
1087  allocate(mask_fg_tile(lensfc))
1088 
1089  IF(.NOT. frac_grid) THEN
1090  mask_tile = nint(slmsk_tile)
1091  mask_fg_tile = nint(slmsk_fg_tile)
1092  ELSE
1093  mask_tile=0
1094  WHERE(sice_tile > 0.0) mask_tile=2
1095  WHERE(landfrac == 1.0) mask_tile=1
1096  mask_fg_tile=0
1097  WHERE(sice_fg_tile > 0.0) mask_fg_tile=2
1098  WHERE(landfrac == 1.0) mask_fg_tile=1
1099  ENDIF
1100 
1101  ij_loop : DO ij = 1, lensfc
1102 
1103 !
1104 ! when sea ice exists, get salinity dependent water temperature
1105 !
1106  tf_ice = tfreez(sal_clm_tile(ij)) + tzero
1107 !----------------------------------------------------------------------
1108 ! SKIP LAND POINTS. NSST NOT APPLIED AT LAND.
1109 !----------------------------------------------------------------------
1110 
1111  IF (mask_tile(ij) == 1) THEN
1112  nland = nland + 1
1113  cycle ij_loop
1114  ENDIF
1115 
1116 !
1117 ! these are ice points. set tref to tf_ice and update tmpsfc.
1118 !
1119  if (mask_tile(ij) == 2) then
1120  nsst%tref(ij)=tf_ice ! water part tmp set
1121  skint_tile(ij)=(1.0-sice_tile(ij))*nsst%tref(ij)+sice_tile(ij)*sicet_tile(ij)
1122  nice = nice + 1
1123  cycle ij_loop
1124  endif
1125 
1126 !
1127 ! Get i,j index on array of (idim,jdim) from known ij
1128 !
1129  jtile = (ij-1) / idim + 1
1130  itile = mod(ij,idim)
1131  IF (itile==0) itile = idim
1132 
1133 !----------------------------------------------------------------------
1134 ! IF THE MODEL POINT WAS ICE COVERED, BUT IS NOW OPEN WATER, SET
1135 ! TREF TO searched adjascent open water onea, if failed the search, set to
1136 ! weighted average of tf_ice and tf_clm. For NSST vars, set xz TO '30' AND ALL OTHER FIELDS TO ZERO.
1137 !----------------------------------------------------------------------
1138 
1139  IF (mask_fg_tile(ij) == 2 .AND. mask_tile(ij) == 0) THEN
1140 !
1141 ! set background for the thaw (just melted water) situation
1142 !
1143  call tf_thaw_set(nsst%tref,mask_fg_tile,itile,jtile,tf_ice,tf_clm_tile(ij),tf_thaw,idim,jdim, &
1144  nset_thaw_s,nset_thaw_i,nset_thaw_c)
1145  call nsst_water_reset(nsst,ij,tf_thaw)
1146  nset_thaw = nset_thaw + 1
1147  ENDIF
1148 
1149 !----------------------------------------------------------------------
1150 ! THESE ARE POINTS THAT ARE OPEN WATER AND WERE OPEN WATER PRIOR
1151 ! TO ANY ICE UPDATE BY SFCCYCLE. UPDATE TREF AND SKIN TEMP.
1152 ! AT OPEN WATER POINTS, THE SEA ICE TEMPERATURE (SICET_TILE) AND
1153 ! SOIL COLUMN TEMPERATURE (SOILT_TILE) ARE SET TO THE SKIN TEMP.
1154 ! IT IS SIMPLY A FILLER VALUE. THESE FIELDS ARE NOT USED AT
1155 ! OPEN WATER POINTS.
1156 !----------------------------------------------------------------------
1157 !----------------------------------------------------------------------
1158 ! SEE IF ANY OF THE NEAREST GSI POINTS MASK AREA OPEN WATER.
1159 ! IF SO, APPLY NSST INCREMENT USING BILINEAR INTERPOLATION.
1160 !----------------------------------------------------------------------
1161 
1162  igaus = id1(itile,jtile)
1163  jgaus = jdc(itile,jtile)
1164  igausp1 = id2(itile,jtile)
1165  jgausp1 = jdc(itile,jtile)+1
1166 
1167  IF (slmsk_gaus(igaus,jgaus) == 0 .OR. &
1168  slmsk_gaus(igausp1,jgaus) == 0 .OR. &
1169  slmsk_gaus(igausp1,jgausp1) == 0 .OR. &
1170  slmsk_gaus(igaus,jgausp1) == 0) THEN
1171 
1172  dtref = 0.0
1173  wsum = 0.0
1174 
1175  IF (slmsk_gaus(igaus,jgaus) == 0) THEN
1176  dtref = dtref + (s2c(itile,jtile,1) * dtref_gaus(igaus,jgaus))
1177  wsum = wsum + s2c(itile,jtile,1)
1178  ENDIF
1179 
1180  IF (slmsk_gaus(igausp1,jgaus) == 0) THEN
1181  dtref = dtref + (s2c(itile,jtile,2) * dtref_gaus(igausp1,jgaus))
1182  wsum = wsum + s2c(itile,jtile,2)
1183  ENDIF
1184 
1185  IF (slmsk_gaus(igausp1,jgausp1) == 0) THEN
1186  dtref = dtref + (s2c(itile,jtile,3) * dtref_gaus(igausp1,jgausp1))
1187  wsum = wsum + s2c(itile,jtile,3)
1188  ENDIF
1189 
1190  IF (slmsk_gaus(igaus,jgausp1) == 0) THEN
1191  dtref = dtref + (s2c(itile,jtile,4) * dtref_gaus(igaus,jgausp1))
1192  wsum = wsum + s2c(itile,jtile,4)
1193  ENDIF
1194 
1195  nintp = nintp + 1
1196  dtref = dtref / wsum
1197 
1198  tref_save = nsst%TREF(ij)
1199  nsst%TREF(ij) = nsst%TREF(ij) + dtref
1200  nsst%TREF(ij) = max(nsst%TREF(ij), tf_ice)
1201  nsst%TREF(ij) = min(nsst%TREF(ij), tmax)
1202  nsst%TFINC(ij) = nsst%TREF(ij) - tref_save
1203 
1204  CALL dtzm_point(nsst%XT(ij),nsst%XZ(ij),nsst%DT_COOL(ij), &
1205  nsst%Z_C(ij),zsea1,zsea2,dtzm)
1206 
1207  skint_tile(ij) = nsst%TREF(ij) + dtzm
1208  skint_tile(ij) = max(skint_tile(ij), tf_ice)
1209  skint_tile(ij) = min(skint_tile(ij), tmax)
1210 
1211  sicet_tile(ij) = skint_tile(ij)
1212 ! Under fractional grids, soilt is used at points with at
1213 ! least some land.
1214  IF(.NOT. frac_grid) soilt_tile(ij,:) = skint_tile(ij)
1215 
1216 !----------------------------------------------------------------------
1217 ! NO NEARBY GSI/GAUSSIAN OPEN WATER POINTS. PERFORM A SPIRAL SEARCH TO
1218 ! FIND NEAREST NON-LAND POINT ON GSI/GAUSSIAN GRID.
1219 !----------------------------------------------------------------------
1220 
1221  ELSE
1222 
1223  is_ice = .false.
1224 
1225  DO krad = 1, max_search
1226 
1227  istart = igaus - krad
1228  iend = igaus + krad
1229  jstart = jgaus - krad
1230  jend = jgaus + krad
1231 
1232  DO jj = jstart, jend
1233  DO ii = istart, iend
1234 
1235  IF((jj == jstart) .OR. (jj == jend) .OR. &
1236  (ii == istart) .OR. (ii == iend)) THEN
1237 
1238  IF ((jj >= 1) .AND. (jj <= jdim_gaus)) THEN
1239 
1240  jjj = jj
1241  IF (ii <= 0) THEN
1242  iii = idim_gaus + ii
1243  ELSE IF (ii >= (idim_gaus+1)) THEN
1244  iii = ii - idim_gaus
1245  ELSE
1246  iii = ii
1247  END IF
1248 
1249 !----------------------------------------------------------------------
1250 ! SEE IF NEARBY POINTS ARE SEA ICE. IF THEY ARE, AND THE SEARCH FOR
1251 ! A GAUSSIAN GRID OPEN WATER POINT FAILS, THEN TREF WILL BE SET TO
1252 ! FREEZING BELOW.
1253 !----------------------------------------------------------------------
1254 
1255  IF (krad <= 2 .AND. slmsk_gaus(iii,jjj) == 2) is_ice = .true.
1256 
1257  IF (slmsk_gaus(iii,jjj) == 0) THEN
1258 
1259 ! PRINT*,'MISMATCH AT TILE POINT ',ITILE,JTILE
1260 ! PRINT*,'UPDATE TREF USING GSI INCREMENT AT ',III,JJJ,DTREF_GAUS(III,JJJ)
1261  nsearched = nsearched + 1
1262 
1263  tref_save = nsst%TREF(ij)
1264  nsst%TREF(ij ) = nsst%TREF(ij) + dtref_gaus(iii,jjj)
1265  nsst%TREF(ij) = max(nsst%TREF(ij), tf_ice)
1266  nsst%TREF(ij) = min(nsst%TREF(ij), tmax)
1267  nsst%TFINC(ij) = nsst%TREF(ij) - tref_save
1268 
1269  CALL dtzm_point(nsst%XT(ij),nsst%XZ(ij),nsst%DT_COOL(ij), &
1270  nsst%Z_C(ij),zsea1,zsea2,dtzm)
1271 
1272  skint_tile(ij) = nsst%TREF(ij) + dtzm
1273  skint_tile(ij) = max(skint_tile(ij), tf_ice)
1274  skint_tile(ij) = min(skint_tile(ij), tmax)
1275 
1276  sicet_tile(ij) = skint_tile(ij)
1277  IF(.NOT. frac_grid) soilt_tile(ij,:) = skint_tile(ij)
1278  cycle ij_loop
1279 
1280  ENDIF ! GSI/Gaussian mask is open water
1281 
1282  ENDIF
1283 
1284  ENDIF
1285 
1286  ENDDO
1287  ENDDO
1288 
1289  ENDDO ! KRAD LOOP
1290 
1291 !----------------------------------------------------------------------
1292 ! THE SEARCH FAILED. IF THERE IS NEARBY ICE, SET TREF TO FREEZING.
1293 ! ELSE UPDATE TREF BASED ON THE ANNUAL SST CYCLE.
1294 !----------------------------------------------------------------------
1295 
1296 ! PRINT*,'WARNING !!!!!! SEARCH FAILED AT TILE POINT ',ITILE,JTILE
1297 
1298  nfill = nfill + 1
1299  IF (is_ice) THEN
1300  nsst%TREF(ij) = tf_ice
1301 ! PRINT*,"NEARBY ICE. SET TREF TO FREEZING"
1302  nfill_tice = nfill_tice + 1
1303  ELSE
1304  tref_save = nsst%TREF(ij)
1305  nsst%TREF(ij) = nsst%TREF(ij) + tf_trd_tile(ij)
1306  nsst%TREF(ij) = max(nsst%TREF(ij), tf_ice)
1307  nsst%TREF(ij) = min(nsst%TREF(ij), tmax)
1308  nsst%TFINC(ij) = nsst%TREF(ij) - tref_save
1309 ! PRINT*,'UPDATE TREF FROM SST CLIMO ',DTREF
1310  nfill_clm = nfill_clm + 1
1311  ENDIF
1312 
1313  CALL dtzm_point(nsst%XT(ij),nsst%XZ(ij),nsst%DT_COOL(ij), &
1314  nsst%Z_C(ij),zsea1,zsea2,dtzm)
1315 
1316  skint_tile(ij) = nsst%TREF(ij) + dtzm
1317  skint_tile(ij) = max(skint_tile(ij), tf_ice)
1318  skint_tile(ij) = min(skint_tile(ij), tmax)
1319 
1320  sicet_tile(ij) = skint_tile(ij)
1321  IF (.NOT. frac_grid) soilt_tile(ij,:) = skint_tile(ij)
1322 
1323  ENDIF ! NEARBY GAUSSIAN POINTS ARE OPEN WATER?
1324 
1325  ENDDO ij_loop
1326 
1327  write(*,'(a)') 'statistics of grids number processed for tile : '
1328  write(*,'(a,I8)') ' nintp = ',nintp
1329  write(*,'(a,4I8)') 'nset_thaw,nset_thaw_s,nset_thaw_i,nset_thaw_c =',nset_thaw,nset_thaw_s,nset_thaw_i,nset_thaw_c
1330  write(*,'(a,I8)') ' nsearched = ',nsearched
1331  write(*,'(a,3I6)') ' nfill,nfill_tice,nfill_clm = ',nfill,nfill_tice,nfill_clm
1332  write(*,'(a,I8)') ' nice = ',nice
1333  write(*,'(a,I8)') ' nland = ',nland
1334 
1335  DEALLOCATE(id1, id2, jdc, s2c, mask_tile, mask_fg_tile)
1336 
1337  END SUBROUTINE adjust_nsst
1338 
1349  SUBROUTINE climo_trend(LATITUDE, MON, DAY, DELTSFC, DTREF)
1350  IMPLICIT NONE
1351 
1352  INTEGER, INTENT(IN) :: MON, DAY
1353 
1354  REAL, INTENT(IN) :: LATITUDE, DELTSFC
1355  REAL, INTENT(OUT) :: DTREF
1356 
1357  INTEGER :: NUM_DAYS(12), MON2, MON1
1358 
1359  REAL, TARGET :: SST_80_90(12)
1360  REAL, TARGET :: SST_70_80(12)
1361  REAL, TARGET :: SST_60_70(12)
1362  REAL, TARGET :: SST_50_60(12)
1363  REAL, TARGET :: SST_40_50(12)
1364  REAL, TARGET :: SST_30_40(12)
1365  REAL, TARGET :: SST_20_30(12)
1366  REAL, TARGET :: SST_10_20(12)
1367  REAL, TARGET :: SST_00_10(12)
1368  REAL, TARGET :: SST_M10_00(12)
1369  REAL, TARGET :: SST_M20_M10(12)
1370  REAL, TARGET :: SST_M30_M20(12)
1371  REAL, TARGET :: SST_M40_M30(12)
1372  REAL, TARGET :: SST_M50_M40(12)
1373  REAL, TARGET :: SST_M60_M50(12)
1374  REAL, TARGET :: SST_M70_M60(12)
1375  REAL, TARGET :: SST_M80_M70(12)
1376  REAL, TARGET :: SST_M90_M80(12)
1377 
1378  REAL, POINTER :: SST(:)
1379 
1380  DATA num_days /31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/
1381 
1382  DATA sst_80_90 /271.466, 271.458, 271.448, 271.445, 271.519, 271.636, &
1383  272.023, 272.066, 272.001, 271.698, 271.510, 271.472/
1384 
1385  DATA sst_70_80 /272.149, 272.103, 272.095, 272.126, 272.360, 272.988, &
1386  274.061, 274.868, 274.415, 273.201, 272.468, 272.268/
1387 
1388  DATA sst_60_70 /274.240, 274.019, 273.988, 274.185, 275.104, 276.875, &
1389  279.005, 280.172, 279.396, 277.586, 275.818, 274.803/
1390 
1391  DATA sst_50_60 /277.277, 276.935, 277.021, 277.531, 279.100, 281.357, &
1392  283.735, 285.171, 284.399, 282.328, 279.918, 278.199/
1393 
1394  DATA sst_40_50 /281.321, 280.721, 280.850, 281.820, 283.958, 286.588, &
1395  289.195, 290.873, 290.014, 287.652, 284.898, 282.735/
1396 
1397  DATA sst_30_40 /289.189, 288.519, 288.687, 289.648, 291.547, 293.904, &
1398  296.110, 297.319, 296.816, 295.225, 292.908, 290.743/
1399 
1400  DATA sst_20_30 /294.807, 294.348, 294.710, 295.714, 297.224, 298.703, &
1401  299.682, 300.127, 300.099, 299.455, 297.953, 296.177/
1402 
1403  DATA sst_10_20 /298.878, 298.720, 299.033, 299.707, 300.431, 300.709, &
1404  300.814, 300.976, 301.174, 301.145, 300.587, 299.694/
1405 
1406  DATA sst_00_10 /300.415, 300.548, 300.939, 301.365, 301.505, 301.141, &
1407  300.779, 300.660, 300.818, 300.994, 300.941, 300.675/
1408 
1409  DATA sst_m10_00 /300.226, 300.558, 300.914, 301.047, 300.645, 299.870, &
1410  299.114, 298.751, 298.875, 299.294, 299.721, 299.989/
1411 
1412  DATA sst_m20_m10 /299.547, 299.985, 300.056, 299.676, 298.841, 297.788, &
1413  296.893, 296.491, 296.687, 297.355, 298.220, 298.964/
1414 
1415  DATA sst_m30_m20 /297.524, 298.073, 297.897, 297.088, 295.846, 294.520, &
1416  293.525, 293.087, 293.217, 293.951, 295.047, 296.363/
1417 
1418  DATA sst_m40_m30 /293.054, 293.765, 293.468, 292.447, 291.128, 289.781, &
1419  288.773, 288.239, 288.203, 288.794, 289.947, 291.553/
1420 
1421  DATA sst_m50_m40 /285.052, 285.599, 285.426, 284.681, 283.761, 282.826, &
1422  282.138, 281.730, 281.659, 281.965, 282.768, 283.961/
1423 
1424  DATA sst_m60_m50 /277.818, 278.174, 277.991, 277.455, 276.824, 276.229, &
1425  275.817, 275.585, 275.560, 275.687, 276.142, 276.968/
1426 
1427  DATA sst_m70_m60 /273.436, 273.793, 273.451, 272.813, 272.349, 272.048, &
1428  271.901, 271.838, 271.845, 271.889, 272.080, 272.607/
1429 
1430  DATA sst_m80_m70 /271.579, 271.578, 271.471, 271.407, 271.392, 271.391, &
1431  271.390, 271.391, 271.394, 271.401, 271.422, 271.486/
1432 
1433  DATA sst_m90_m80 /271.350, 271.350, 271.350, 271.350, 271.350, 271.350, &
1434  271.350, 271.350, 271.350, 271.350, 271.350, 271.350/
1435 
1436  NULLIFY(sst)
1437  IF (latitude > 80.0) THEN
1438  sst => sst_80_90
1439  ELSEIF (latitude > 70.0) THEN
1440  sst => sst_70_80
1441  ELSEIF (latitude > 60.0) THEN
1442  sst => sst_60_70
1443  ELSEIF (latitude > 50.0) THEN
1444  sst => sst_50_60
1445  ELSEIF (latitude > 40.0) THEN
1446  sst => sst_40_50
1447  ELSEIF (latitude > 30.0) THEN
1448  sst => sst_30_40
1449  ELSEIF (latitude > 20.0) THEN
1450  sst => sst_20_30
1451  ELSEIF (latitude > 10.0) THEN
1452  sst => sst_10_20
1453  ELSEIF (latitude > 0.0) THEN
1454  sst => sst_00_10
1455  ELSEIF (latitude > -10.0) THEN
1456  sst => sst_m10_00
1457  ELSEIF (latitude > -20.0) THEN
1458  sst => sst_m20_m10
1459  ELSEIF (latitude > -30.0) THEN
1460  sst => sst_m30_m20
1461  ELSEIF (latitude > -40.0) THEN
1462  sst => sst_m40_m30
1463  ELSEIF (latitude > -50.0) THEN
1464  sst => sst_m50_m40
1465  ELSEIF (latitude > -60.0) THEN
1466  sst => sst_m60_m50
1467  ELSEIF (latitude > -70.0) THEN
1468  sst => sst_m70_m60
1469  ELSEIF (latitude > -80.0) THEN
1470  sst => sst_m80_m70
1471  ELSE
1472  sst => sst_m90_m80
1473  END IF
1474 
1475  IF (day >= 15) THEN
1476  mon2 = mon+1
1477  IF(mon2 == 13) mon2 = 1
1478  mon1 = mon
1479  dtref = (sst(mon2) - sst(mon1)) / num_days(mon1)
1480  ELSE
1481  mon1 = mon - 1
1482  IF (mon1 == 0) mon1=12
1483  mon2 = mon
1484  dtref = (sst(mon2) - sst(mon1)) / num_days(mon1)
1485  ENDIF
1486 
1487  dtref = dtref * (deltsfc / 24.0)
1488 
1489  END SUBROUTINE climo_trend
1490 
1502  SUBROUTINE dtzm_point(XT,XZ,DT_COOL,ZC,Z1,Z2,DTZM)
1503  implicit none
1504 
1505  real, intent(in) :: xt,xz,dt_cool,zc,z1,z2
1506  real, intent(out) :: dtzm
1507 
1508  real, parameter :: zero = 0.0
1509  real, parameter :: one = 1.0
1510  real, parameter :: half = 0.5
1511  real :: dt_warm,dtw,dtc
1512 !
1513 ! get the mean warming in the range of z=z1 to z=z2
1514 !
1515  dtw = zero
1516  if ( xt > zero ) then
1517  dt_warm = (xt+xt)/xz ! Tw(0)
1518  if ( z1 < z2) then
1519  if ( z2 < xz ) then
1520  dtw = dt_warm*(one-(z1+z2)/(xz+xz))
1521  elseif ( z1 < xz .and. z2 >= xz ) then
1522  dtw = half*(one-z1/xz)*dt_warm*(xz-z1)/(z2-z1)
1523  endif
1524  elseif ( z1 == z2 ) then
1525  if ( z1 < xz ) then
1526  dtw = dt_warm*(one-z1/xz)
1527  endif
1528  endif
1529  endif
1530 !
1531 ! get the mean cooling in the range of z=z1 to z=z2
1532 !
1533  dtc = zero
1534  if ( zc > zero ) then
1535  if ( z1 < z2) then
1536  if ( z2 < zc ) then
1537  dtc = dt_cool*(one-(z1+z2)/(zc+zc))
1538  elseif ( z1 < zc .and. z2 >= zc ) then
1539  dtc = half*(one-z1/zc)*dt_cool*(zc-z1)/(z2-z1)
1540  endif
1541  elseif ( z1 == z2 ) then
1542  if ( z1 < zc ) then
1543  dtc = dt_cool*(one-z1/zc)
1544  endif
1545  endif
1546  endif
1547 
1548 !
1549 ! get the mean T departure from Tf in the range of z=z1 to z=z2
1550 !
1551  dtzm = dtw - dtc
1552 
1553  END SUBROUTINE dtzm_point
1554 
1574  subroutine tf_thaw_set(tf_ij,mask_ij,itile,jtile,tice,tclm,tf_thaw,nx,ny, &
1575  nset_thaw_s,nset_thaw_i,nset_thaw_c)
1577  real, dimension(nx*ny), intent(in) :: tf_ij
1578  integer, dimension(nx*ny), intent(in) :: mask_ij
1579  real, intent(in) :: tice,tclm
1580  integer, intent(in) :: itile,jtile,nx,ny
1581  real, intent(out) :: tf_thaw
1582  integer, intent(inout) :: nset_thaw_s,nset_thaw_i,nset_thaw_c
1583 ! Local
1584  real, parameter :: bmiss = -999.0
1585  real, dimension(nx,ny) :: tf
1586  integer, dimension(nx,ny) :: mask
1587  integer :: krad,max_search,istart,iend,jstart,jend
1588  integer :: ii,jj,iii,jjj
1589  logical :: is_ice
1590 
1591  max_search = 2
1592 
1593  mask(:,:) = reshape(mask_ij,(/nx,ny/) )
1594  tf(:,:) = reshape(tf_ij,(/nx,ny/) )
1595 
1596  tf_thaw = bmiss
1597 
1598  do krad = 1, max_search
1599 
1600  istart = itile - krad
1601  iend = itile + krad
1602  jstart = jtile - krad
1603  jend = jtile + krad
1604 
1605  do jj = jstart, jend
1606  do ii = istart, iend
1607 
1608 
1609  if ((jj == jstart) .or. (jj == jend) .or. &
1610  (ii == istart) .or. (ii == iend)) then
1611 
1612  if ((jj >= 1) .and. (jj <= ny)) then
1613  jjj = jj
1614  if (ii <= 0) then
1615  iii = nx + ii
1616  else if (ii >= (nx+1)) then
1617  iii = ii - nx
1618  else
1619  iii = ii
1620  endif
1621 
1622 !----------------------------------------------------------------------
1623 ! SEE IF NEARBY POINTS ARE SEA ICE. IF THEY ARE, AND THE SEARCH FOR
1624 ! A GAUSSIAN GRID OPEN WATER POINT FAILS, THEN TREF WILL BE SET TO
1625 ! FREEZING BELOW.
1626 !----------------------------------------------------------------------
1627  if (krad <= 2 .and. mask(iii,jjj) == 2) is_ice = .true.
1628 
1629  if (mask(iii,jjj) == 0) then
1630  tf_thaw = tf(iii,jjj)
1631  nset_thaw_s = nset_thaw_s + 1
1632  write(*,'(a,I4,2F9.3)') 'nset_thaw_s,tf(iii,jjj),tclm : ',nset_thaw_s,tf(iii,jjj),tclm
1633  go to 100
1634  endif ! tile mask is open water
1635 
1636  endif
1637  endif
1638  enddo
1639  enddo
1640  enddo ! krad loop
1641 
1642  100 continue
1643 
1644  if ( tf_thaw == bmiss ) then
1645  if (is_ice) then
1646  tf_thaw = tice
1647  nset_thaw_i = nset_thaw_i + 1
1648  write(*,'(a,I4,F9.3)') 'nset_thaw_i,tf_ice : ',nset_thaw_i,tice
1649  else
1650  tf_thaw = 0.8*tice+0.2*tclm
1651  nset_thaw_c = nset_thaw_c + 1
1652  write(*,'(a,I4,2F9.3)') 'nset_thaw_c,tf_ice,tclm : ',nset_thaw_c,tice,tclm
1653  endif
1654  endif
1655 
1656  end subroutine tf_thaw_set
1657 
1665  subroutine nsst_water_reset(nsst,ij,tf_thaw)
1667  implicit none
1668 
1669  integer, intent(in) :: ij
1670 
1671  real, intent(in) :: tf_thaw
1672 
1673  type(nsst_data), intent(inout) :: nsst
1674 
1675  nsst%c_0(ij) = 0.0
1676  nsst%c_d(ij) = 0.0
1677  nsst%d_conv(ij) = 0.0
1678  nsst%dt_cool(ij) = 0.0
1679  nsst%ifd(ij) = 0.0
1680  nsst%qrain(ij) = 0.0
1681  nsst%tref(ij) = tf_thaw
1682  nsst%w_0(ij) = 0.0
1683  nsst%w_d(ij) = 0.0
1684  nsst%xs(ij) = 0.0
1685  nsst%xt(ij) = 0.0
1686  nsst%xtts(ij) = 0.0
1687  nsst%xu(ij) = 0.0
1688  nsst%xv(ij) = 0.0
1689  nsst%xz(ij) = 30.0
1690  nsst%xzts(ij) = 0.0
1691  nsst%z_c(ij) = 0.0
1692  nsst%zm(ij) = 0.0
1693 
1694  end subroutine nsst_water_reset
1695 
1711 subroutine get_tf_clm(xlats_ij,xlons_ij,ny,nx,iy,im,id,ih,tf_clm,tf_trd)
1713 
1714  implicit none
1715 
1716  real, dimension(nx*ny), intent(in) :: xlats_ij
1717  real, dimension(nx*ny), intent(in) :: xlons_ij
1718  real, dimension(nx,ny), intent(out) :: tf_clm
1719  real, dimension(nx,ny), intent(out) :: tf_trd
1720  integer, intent(in) :: iy,im,id,ih,nx,ny
1721 ! local declare
1722  real, allocatable, dimension(:,:) :: tf_clm0 ! sst climatology at the valid time (nxc,nyc)
1723  real, allocatable, dimension(:,:) :: tf_trd0 ! 6-hourly sst climatology tendency valid at atime (nxc,nyc)
1724  real, allocatable, dimension(:) :: cxlats ! latitudes of sst climatology
1725  real, allocatable, dimension(:) :: cxlons ! longitudes of sst climatology
1726 
1727  real, dimension(nx*ny) :: tf_clm_ij ! sst climatology at target grids (nx*ny)
1728  real, dimension(nx*ny) :: tf_trd_ij ! 6-hourly sst climatology tendency
1729  real :: wei1,wei2
1730  integer :: nxc,nyc,mon1,mon2
1731  character (len=6), parameter :: fin_tf_clm='sstclm' ! sst climatology file name
1732 !
1733 ! get which two months used and their weights from atime
1734 !
1735  call get_tim_wei(iy,im,id,ih,mon1,mon2,wei1,wei2)
1736 !
1737 ! get the dimensions of the sst climatology & allocate the related arrays
1738 !
1739  call get_tf_clm_dim(fin_tf_clm,nyc,nxc)
1740  allocate( tf_clm0(nxc,nyc),tf_trd0(nxc,nyc),cxlats(nyc),cxlons(nxc) )
1741 !
1742 ! get tf_clm at the analysis time from monthly climatology & cxlats, cxlons
1743 !
1744  call get_tf_clm_ta(tf_clm0,tf_trd0,cxlats,cxlons,nyc,nxc,mon1,mon2,wei1,wei2)
1745 !
1746 ! get tf_clm (nx by ny lat/lon) valid at atime
1747 !
1748  if ( nx == nxc .and. ny == nyc ) then
1749  tf_clm(:,:) = tf_clm0(:,:)
1750  tf_trd(:,:) = tf_trd0(:,:)
1751 ! write(*,'(a,2f9.3)') 'same dimensions, tf_clm, min : ',minval(tf_clm),maxval(tf_clm)
1752  else
1753 ! write(*,'(a,4i8)') 'different dimensions,nx,ny,nxc,nyc : ',nx,ny,nxc,nyc
1754  call intp_tile(tf_clm0, cxlats, cxlons, nyc, nxc, &
1755  tf_clm_ij,xlats_ij,xlons_ij,ny, nx)
1756  call intp_tile(tf_trd0, cxlats, cxlons, nyc, nxc, &
1757  tf_trd_ij,xlats_ij,xlons_ij,ny, nx)
1758 ! write(*,'(a,2f9.3)') 'tf_clm0, min, max : ',minval(tf_clm0),maxval(tf_clm0)
1759 
1760  tf_clm(:,:) = reshape(tf_clm_ij, (/nx,ny/) )
1761  tf_trd(:,:) = reshape(tf_trd_ij, (/nx,ny/) )
1762  endif
1763 
1764 end subroutine get_tf_clm
1765 
1780 subroutine get_tf_clm_ta(tf_clm_ta,tf_clm_trend,xlats,xlons,nlat,nlon,mon1,mon2,wei1,wei2)
1782  implicit none
1783 
1784 ! input
1785  integer, intent(in) :: nlat,nlon,mon1,mon2
1786  real, intent(in) :: wei1,wei2
1787 ! output
1788  real, dimension(nlon,nlat), intent(out) :: tf_clm_ta,tf_clm_trend
1789  real, dimension(nlat), intent(out) :: xlats
1790  real, dimension(nlon), intent(out) :: xlons
1791 
1792 !input/output data file names
1793  character (len=6), parameter :: fin_tf_clm='sstclm'
1794 
1795 ! local declare
1796  real, dimension(nlon,nlat) :: tf_clm1,tf_clm2
1797 
1798 !
1799 ! read in rtg sst climatology without bitmap (surface mask) for mon1 and mon2
1800 !
1801  call read_tf_clim_grb(trim(fin_tf_clm),tf_clm1,xlats,xlons,nlat,nlon,mon1)
1802  call read_tf_clim_grb(trim(fin_tf_clm),tf_clm2,xlats,xlons,nlat,nlon,mon2)
1803 !
1804 ! tf_clim at the analysis time
1805 !
1806  tf_clm_ta(:,:) = wei1*tf_clm1(:,:)+wei2*tf_clm2(:,:)
1807 !
1808 ! tf_clim trend at the analysis time (month to month)
1809 !
1810  tf_clm_trend(:,:) = (tf_clm2(:,:)-tf_clm1(:,:))/120.0
1811 
1812  write(*,'(a,2f9.3)') 'tf_clm_ta, min, max : ',minval(tf_clm_ta),maxval(tf_clm_ta)
1813  write(*,'(a,2f9.3)') 'tf_clm_trend, min, max : ',minval(tf_clm_trend),maxval(tf_clm_trend)
1814  end subroutine get_tf_clm_ta
1815 
1828 subroutine get_sal_clm(xlats_ij,xlons_ij,ny,nx,iy,im,id,ih,sal_clm)
1830  implicit none
1831 
1832  real, dimension(nx*ny), intent(in) :: xlats_ij !
1833  real, dimension(nx*ny), intent(in) :: xlons_ij !
1834  real, dimension(nx,ny), intent(out) :: sal_clm !
1835  integer, intent(in) :: iy,im,id,ih,nx,ny
1836 ! local declare
1837  real, allocatable, dimension(:,:) :: sal_clm0 ! salinity climatology at the valid time
1838  real, allocatable, dimension(:) :: cxlats ! latitudes of sst climatology
1839  real, allocatable, dimension(:) :: cxlons ! longitudes of sst climatology
1840 
1841  real, dimension(nx*ny) :: sal_clm_ij ! salinity climatology at target grids (nx*ny)
1842  real :: wei1,wei2
1843  integer :: nxc,nyc,mon1,mon2
1844  character (len=6), parameter :: fin_sal_clm='salclm' ! salinity climatology file name
1845 !
1846 ! get which two months used and their weights from atime
1847 !
1848  call get_tim_wei(iy,im,id,ih,mon1,mon2,wei1,wei2)
1849 !
1850 ! get the dimensions of the sst climatology & allocate the related arrays
1851 !
1852  call get_dim_nc(fin_sal_clm,nyc,nxc)
1853  allocate( sal_clm0(nxc,nyc),cxlats(nyc),cxlons(nxc) )
1854 !
1855 ! get sal_clm at the analysis time from monthly climatology & cxlats, cxlons
1856 !
1857  call get_sal_clm_ta(sal_clm0,cxlats,cxlons,nyc,nxc,mon1,mon2,wei1,wei2)
1858 !
1859 ! get sal_clm (nx by ny lat/lon) valid at atime
1860 !
1861  if ( nx == nxc .and. ny == nyc ) then
1862  sal_clm(:,:) = sal_clm0(:,:)
1863 ! write(*,'(a,2f9.3)') 'same dimensions, sal_clm, min : ',minval(sal_clm),maxval(sal_clm)
1864  else
1865 ! write(*,'(a,4i8)') 'different dimensions,nx,ny,nxc,nyc : ',nx,ny,nxc,nyc
1866  call intp_tile(sal_clm0, cxlats, cxlons, nyc, nxc, &
1867  sal_clm_ij,xlats_ij,xlons_ij,ny, nx)
1868 ! write(*,'(a,2f9.3)') 'sal_clm0, min, max : ',minval(sal_clm0),maxval(sal_clm0)
1869 ! write(*,'(a,2f9.3)') 'done with intp_tile for sal_clm, min, max : ',minval(sal_clm_ij),maxval(sal_clm_ij)
1870 
1871  sal_clm(:,:) = reshape(sal_clm_ij, (/nx,ny/) )
1872  endif
1873 
1874 end subroutine get_sal_clm
1875 
1888 subroutine get_sal_clm_ta(sal_clm_ta,xlats,xlons,nlat,nlon,mon1,mon2,wei1,wei2)
1891  implicit none
1892 
1893 ! input
1894  integer, intent(in) :: nlat,nlon,mon1,mon2
1895  real, intent(in) :: wei1,wei2
1896 ! output
1897  real, dimension(nlon,nlat), intent(out) :: sal_clm_ta
1898  real, dimension(nlat), intent(out) :: xlats
1899  real, dimension(nlon), intent(out) :: xlons
1900 
1901 !input/output data file names
1902  character (len=6), parameter :: fin_sal_clm='salclm'
1903 
1904 ! local declare
1905  real, dimension(nlon,nlat) :: sal_clm1,sal_clm2
1906 
1907 !
1908 ! read in rtg sst climatology without bitmap (surface mask) for mon1 and mon2
1909 !
1910  call read_salclm_gfs_nc(trim(fin_sal_clm),sal_clm1,xlats,xlons,nlat,nlon,mon1)
1911  call read_salclm_gfs_nc(trim(fin_sal_clm),sal_clm2,xlats,xlons,nlat,nlon,mon2)
1912 !
1913 ! sal_clim at the analysis time
1914 !
1915  sal_clm_ta(:,:) = wei1*sal_clm1(:,:)+wei2*sal_clm2(:,:)
1916  write(*,'(a,2f9.3)') 'sal_clm_ta, min, max : ',minval(sal_clm_ta),maxval(sal_clm_ta)
1917  end subroutine get_sal_clm_ta
1918 
1933 subroutine intp_tile(tf_lalo,dlats_lalo,dlons_lalo,jdim_lalo,idim_lalo, &
1934  tf_tile,xlats_tile,xlons_tile,jdim_tile,idim_tile)
1936  use utils
1937 
1938  implicit none
1939 
1940 ! input/output
1941  real, dimension(idim_lalo,jdim_lalo), intent(in) :: tf_lalo
1942  real, dimension(jdim_lalo), intent(in) :: dlats_lalo
1943  real, dimension(idim_lalo), intent(in) :: dlons_lalo
1944  real, dimension(jdim_tile*idim_tile), intent(in) :: xlats_tile
1945  real, dimension(jdim_tile*idim_tile), intent(in) :: xlons_tile
1946  integer, intent(in) :: jdim_lalo,idim_lalo,jdim_tile,idim_tile
1947  real, dimension(jdim_tile*idim_tile), intent(out) :: tf_tile
1948 
1949 ! local
1950  real, parameter :: deg2rad=3.1415926/180.0
1951  real, dimension(jdim_lalo) :: xlats_lalo
1952  real, dimension(idim_lalo) :: xlons_lalo
1953  real :: wsum
1954  integer :: itile,jtile
1955  integer :: ij
1956  integer :: ilalo,jlalo,ilalop1,jlalop1
1957 
1958  integer, allocatable, dimension(:,:) :: id1,id2,jdc
1959  real, allocatable, dimension(:,:,:) :: agrid,s2c
1960 
1961  print*
1962  print*,'interpolate from lat/lon grids to any one grid with known lat/lon'
1963 
1964  xlats_lalo = dlats_lalo*deg2rad
1965  xlons_lalo = dlons_lalo*deg2rad
1966 
1967  allocate(agrid(idim_tile,jdim_tile,2))
1968  agrid(:,:,1) = reshape(xlons_tile, (/idim_tile,jdim_tile/) )
1969  agrid(:,:,2) = reshape(xlats_tile, (/idim_tile,jdim_tile/) )
1970  agrid = agrid*deg2rad
1971 
1972  allocate(id1(idim_tile,jdim_tile))
1973  allocate(id2(idim_tile,jdim_tile))
1974  allocate(jdc(idim_tile,jdim_tile))
1975  allocate(s2c(idim_tile,jdim_tile,4))
1976 
1977 !----------------------------------------------------------------------
1978 ! compute bilinear weights for each model point from the nearest
1979 ! four lalo points. does not account for mask. that
1980 ! happens later.
1981 !----------------------------------------------------------------------
1982 
1983  call remap_coef( 1, idim_tile, 1, jdim_tile, idim_lalo, jdim_lalo, &
1984  xlons_lalo, xlats_lalo, id1, id2, jdc, s2c, agrid )
1985 
1986  do ij = 1, jdim_tile*idim_tile
1987 
1988  jtile = (ij-1)/idim_tile + 1
1989  itile = mod(ij,idim_tile)
1990  if (itile==0) itile = idim_tile
1991 
1992  ilalo = id1(itile,jtile)
1993  ilalop1 = id2(itile,jtile)
1994  jlalo = jdc(itile,jtile)
1995  jlalop1 = jdc(itile,jtile) + 1
1996 
1997  wsum = s2c(itile,jtile,1) + s2c(itile,jtile,2) + &
1998  s2c(itile,jtile,3) + s2c(itile,jtile,4)
1999 
2000  tf_tile(ij) = ( s2c(itile,jtile,1)*tf_lalo(ilalo,jlalo) + &
2001  s2c(itile,jtile,2)*tf_lalo(ilalop1,jlalo) + &
2002  s2c(itile,jtile,3)*tf_lalo(ilalop1,jlalop1) + &
2003  s2c(itile,jtile,4)*tf_lalo(ilalo,jlalop1) )/wsum
2004  enddo
2005 
2006  deallocate(id1, id2, jdc, s2c)
2007 
2008 end subroutine intp_tile
2009 
2022 subroutine get_tim_wei(iy,im,id,ih,mon1,mon2,wei1,wei2)
2023  implicit none
2024 
2025 ! input
2026  integer, intent(in) :: iy,im,id,ih
2027 ! output
2028  integer, intent(out) :: mon1,mon2
2029  real, intent(out) :: wei1,wei2
2030 
2031 ! local declare
2032  real :: rjday
2033  integer :: mon,monend,monm,monp,jdow,jdoy,jday
2034  integer :: jda(8)
2035 !
2036 !dayhf : julian day of the middle of each month
2037 !
2038  real, dimension(13) :: dayhf
2039  data dayhf/15.5,45.0,74.5,105.0,135.5,166.0,196.5,227.5,258.0,288.5,319.0,349.5,380.5/
2040 
2041 ! 15, 44, 73.5, 104, 134.5, 165, 195.5, 226.5, 257, 287.5, 318.5, 349 ! from
2042 ! woa05
2043 
2044  jda=0
2045  jda(1)=iy
2046  jda(2)=im
2047  jda(3)=id
2048  jda(5)=ih
2049  jdow = 0
2050  jdoy = 0
2051  jday = 0
2052  call w3doxdat(jda,jdow,jdoy,jday)
2053  rjday=jdoy+jda(5)/24.
2054  if(rjday.lt.dayhf(1)) rjday=rjday+365.
2055 
2056  monend = 12
2057  do mon = 1, monend
2058  monm = mon
2059  monp = mon + 1
2060  if( rjday >= dayhf(monm) .and. rjday < dayhf(monp) ) then
2061  mon1 = monm
2062  mon2 = monp
2063  go to 10
2064  endif
2065  enddo
2066 
2067  print *,'FATAL ERROR in get_tim_wei, wrong rjday',rjday
2068  call abort
2069  10 continue
2070 
2071  wei1 = (dayhf(mon2)-rjday)/(dayhf(mon2)-dayhf(mon1))
2072  wei2 = (rjday-dayhf(mon1))/(dayhf(mon2)-dayhf(mon1))
2073 
2074  if( mon2 == 13 ) mon2=1
2075 
2076  write(*,'(a,2i4,3f9.3)') 'mon1,mon2,rjday,wei1,wei2=',mon1,mon2,rjday,wei1,wei2
2077 
2078  end subroutine get_tim_wei
2079 
2089  real function tfreez(salinity)
2091  implicit none
2092 
2093  REAL salinity,sal
2094  REAL a1, a2, a3
2095  parameter(a1 = -0.0575)
2096  parameter(a2 = 1.710523e-3)
2097  parameter(a3 = -2.154996e-4)
2098 
2099  IF (salinity .LT. 0.) THEN
2100  sal = 0.
2101  ELSE
2102  sal = salinity
2103  ENDIF
2104  tfreez = sal*(a1+a2*sqrt(sal)+a3*sal)
2105 
2106  return
2107  end
integer function num_parthds()
Return the number of omp threads.
Definition: num_parthds.f90:10
subroutine, public read_data(LSOIL, LENSFC, DO_NSST, DO_SNO_INC_JEDI, DO_SOI_INC_JEDI, INC_FILE, IS_NOAHMP, TSFFCS, SMCFCS, SWEFCS, STCFCS, TG3FCS, ZORFCS, CVFCS, CVBFCS, CVTFCS, ALBFCS, VEGFCS, SLIFCS, CNPFCS, F10M, VETFCS, SOTFCS, ALFFCS, USTAR, FMM, FHH, SIHFCS, SICFCS, SITFCS, TPRCP, SRFLAG, SNDFCS, VMNFCS, VMXFCS, SLCFCS, STCINC, SLCINC, SLPFCS, ABSFCS, T2M, Q2M, SLMASK, ZSOIL, NSST)
Read the first guess surface records and nsst records (if selected) for a single cubed-sphere tile...
subroutine, public get_tf_clm_dim(file_sst, mlat_sst, mlon_sst)
Get the i/j dimensions of RTG SST climatology file.
subroutine, public read_tf_clim_grb(file_sst, sst, rlats_sst, rlons_sst, mlat_sst, mlon_sst, mon)
Read a GRIB1 sst climatological analysis file.
integer, public idim_gaus
&#39;i&#39; dimension of GSI gaussian grid.
subroutine get_tf_clm(xlats_ij, xlons_ij, ny, nx, iy, im, id, ih, tf_clm, tf_trd)
Get the sst climatology at the valid time and on the target grid.
Definition: cycle.f90:1712
subroutine, public read_salclm_gfs_nc(filename, sal, xlats, xlons, nlat, nlon, itime)
Read the woa05 salinity monthly climatology file.
subroutine get_tf_clm_ta(tf_clm_ta, tf_clm_trend, xlats, xlons, nlat, nlon, mon1, mon2, wei1, wei2)
Get the reference temperature/sst climatology and its trend at analysis time.
Definition: cycle.f90:1781
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.
Definition: utils.F90:40
integer, dimension(:,:), allocatable, public slmsk_gaus
GSI land mask on the gaussian grid.
subroutine dtzm_point(XT, XZ, DT_COOL, ZC, Z1, Z2, DTZM)
Compute the vertical mean of the NSST t-profile.
Definition: cycle.f90:1503
subroutine get_sal_clm_ta(sal_clm_ta, xlats, xlons, nlat, nlon, mon1, mon2, wei1, wei2)
Get climatological salinity at the analysis time.
Definition: cycle.f90:1889
Holds machine dependent constants for global_cycle.
Definition: machine.f90:7
subroutine sfcdrv(LUGB, IDIM, JDIM, LENSFC, LSOIL, DELTSFC, IY, IM, ID, IH, FH, IALB, USE_UFO, DO_NSST, DO_SFCCYCLE, DO_LNDINC, FRAC_GRID, ZSEA1, ZSEA2, ISOT, IVEGSRC, MYRANK)
Driver routine for updating the surface fields.
Definition: cycle.f90:313
subroutine tf_thaw_set(tf_ij, mask_ij, itile, jtile, tice, tclm, tf_thaw, nx, ny, nset_thaw_s, nset_thaw_i, nset_thaw_c)
Set the background reference temperature (tf) for points where the ice has just melted.
Definition: cycle.f90:1576
subroutine, public get_dim_nc(filename, nlat, nlon)
Get the i/j dimensions of the data from a NetCDF file.
subroutine, public read_gsi_data(GSI_FILE, FILE_TYPE, LSOIL)
Read increment file from the GSI containing either the foundation temperature increments and mask...
subroutine intp_tile(tf_lalo, dlats_lalo, dlons_lalo, jdim_lalo, idim_lalo, tf_tile, xlats_tile, xlons_tile, jdim_tile, idim_tile)
Interpolate lon/lat grid data to the fv3 native grid (tf_lalo => tf_tile).
Definition: cycle.f90:1935
subroutine climo_trend(LATITUDE, MON, DAY, DELTSFC, DTREF)
If the tile point is an isolated water point that has no corresponding gsi water point, then tref is updated using the rtg sst climo trend.
Definition: cycle.f90:1350
real, dimension(:,:), allocatable, public dtref_gaus
GSI foundation temperature increment on the gaussian grid.
subroutine, public write_data(lensfc, idim, jdim, lsoil, do_nsst, inc_file, nsst, slifcs, tsffcs, vegfcs, swefcs, tg3fcs, zorfcs, albfcs, alffcs, cnpfcs, f10m, t2m, q2m, vetfcs, sotfcs, ustar, fmm, fhh, sicfcs, sihfcs, sitfcs, tprcp, srflag, swdfcs, vmnfcs, vmxfcs, slpfcs, absfcs, slcfcs, smcfcs, stcfcs, stcinc, slcinc)
Update surface records - and nsst records if selected - on a single cubed-sphere tile to a pre-existi...
Module containing utility routines.
Definition: utils.F90:7
This module contains routines that read and write data.
program sfc_drv
Stand alone surface/NSST cycle driver for the cubed-sphere grid.
Definition: cycle.f90:111
subroutine adjust_nsst(RLA, RLO, SLMSK_TILE, SLMSK_FG_TILE, SKINT_TILE, SICET_TILE, sice_tile, sice_fg_tile, SOILT_TILE, NSST, LENSFC, LSOIL, IDIM, JDIM, ZSEA1, ZSEA2, tf_clm_tile, tf_trd_tile, sal_clm_tile, LANDFRAC, FRAC_GRID)
Read in gsi file with the updated reference temperature increments (on the gaussian grid)...
Definition: cycle.f90:926
real function tfreez(salinity)
Compute the freezing point of water as a function of salinity.
Definition: cycle.f90:2090
integer, public jdim_gaus
&#39;j&#39; dimension of GSI gaussian grid.
subroutine get_tim_wei(iy, im, id, ih, mon1, mon2, wei1, wei2)
For a given date, determine the bounding months and the linear time interpolation weights...
Definition: cycle.f90:2023
subroutine get_sal_clm(xlats_ij, xlons_ij, ny, nx, iy, im, id, ih, sal_clm)
Get salinity climatology at the valid time on the target grid.
Definition: cycle.f90:1829
subroutine nsst_water_reset(nsst, ij, tf_thaw)
If the first guess was sea ice, but the analysis is open water, reset all nsst variables.
Definition: cycle.f90:1666
subroutine, public read_lat_lon_orog(RLA, RLO, OROG, OROG_UF, TILE_NUM, IDIM, JDIM, IJDIM, LANDFRAC)
Read latitude and longitude for the cubed-sphere tile from the &#39;grid&#39; file.