FV3 Bundle
surface_variables_mod.f90
Go to the documentation of this file.
1 ! (C) Copyright 2018 UCAR
2 !
3 ! This software is licensed under the terms of the Apache Licence Version 2.0
4 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5 
6 !> Variable transforms/interpolation for surface variables in fv3-jedi
7 !> Daniel Holdaway, NASA/JCSDA
8 
10 
13 use crtm_module, only: crtm_irlandcoeff_classification
15 
16 implicit none
17 private
18 
19 public crtm_surface
22 
26 end interface
27 
28 contains
29 
30 !----------------------------------------------------------------------------
31 ! Surface quantities in the form needed by the crtm -------------------------
32 !----------------------------------------------------------------------------
33 
34 subroutine crtm_surface( geom, nobs, ngrid, lats_ob, lons_ob, &
35  fld_slmsk, fld_sheleg, fld_tsea, fld_vtype, fld_stype, fld_vfrac, fld_stc, &
36  fld_smc, fld_snwdph, fld_u_srf, fld_v_srf, fld_f10m, &
37  land_type, vegetation_type, soil_type, water_coverage, land_coverage, ice_coverage, &
38  snow_coverage, lai, water_temperature, land_temperature, ice_temperature, &
39  snow_temperature, soil_moisture_content, vegetation_fraction, soil_temperature, snow_depth, &
40  wind_speed, wind_direction )
41 
42  implicit none
43 
44  !Arguments
45  type(fv3jedi_geom) , intent(in) :: geom !Geometry for the model
46  integer , intent(in) :: nobs
47  integer , intent(in) :: ngrid
48  real(kind=kind_real), intent(in) :: lats_ob(nobs)
49  real(kind=kind_real), intent(in) :: lons_ob(nobs)
50  integer , intent(in) :: fld_slmsk (geom%isc:geom%iec,geom%jsc:geom%jec)
51  real(kind=kind_real), intent(in) :: fld_sheleg(geom%isc:geom%iec,geom%jsc:geom%jec)
52  real(kind=kind_real), intent(in) :: fld_tsea (geom%isc:geom%iec,geom%jsc:geom%jec)
53  integer , intent(in) :: fld_vtype (geom%isc:geom%iec,geom%jsc:geom%jec)
54  integer , intent(in) :: fld_stype (geom%isc:geom%iec,geom%jsc:geom%jec)
55  real(kind=kind_real), intent(in) :: fld_vfrac (geom%isc:geom%iec,geom%jsc:geom%jec)
56  real(kind=kind_real), intent(in) :: fld_stc (geom%isc:geom%iec,geom%jsc:geom%jec,4)
57  real(kind=kind_real), intent(in) :: fld_smc (geom%isc:geom%iec,geom%jsc:geom%jec,4)
58  real(kind=kind_real), intent(in) :: fld_snwdph(geom%isc:geom%iec,geom%jsc:geom%jec)
59  real(kind=kind_real), intent(in) :: fld_u_srf (geom%isc:geom%iec,geom%jsc:geom%jec)
60  real(kind=kind_real), intent(in) :: fld_v_srf (geom%isc:geom%iec,geom%jsc:geom%jec)
61  real(kind=kind_real), intent(in) :: fld_f10m (geom%isc:geom%iec,geom%jsc:geom%jec)
62  integer , intent(out) :: vegetation_type(nobs)
63  integer , intent(out) :: land_type(nobs)
64  integer , intent(out) :: soil_type(nobs)
65  real(kind=kind_real), intent(out) :: water_coverage(nobs)
66  real(kind=kind_real), intent(out) :: land_coverage(nobs)
67  real(kind=kind_real), intent(out) :: ice_coverage(nobs)
68  real(kind=kind_real), intent(out) :: snow_coverage(nobs)
69  real(kind=kind_real), intent(out) :: lai(nobs)
70  real(kind=kind_real), intent(out) :: water_temperature(nobs)
71  real(kind=kind_real), intent(out) :: land_temperature(nobs)
72  real(kind=kind_real), intent(out) :: ice_temperature(nobs)
73  real(kind=kind_real), intent(out) :: snow_temperature(nobs)
74  real(kind=kind_real), intent(out) :: soil_moisture_content(nobs)
75  real(kind=kind_real), intent(out) :: vegetation_fraction(nobs)
76  real(kind=kind_real), intent(out) :: soil_temperature(nobs)
77  real(kind=kind_real), intent(out) :: snow_depth(nobs)
78  real(kind=kind_real), intent(out) :: wind_speed(nobs)
79  real(kind=kind_real), intent(out) :: wind_direction(nobs)
80 
81  !Locals
82  real(kind=kind_real), parameter :: minsnow = 1.0_kind_real / 10.0_kind_real
83  real(kind=kind_real), parameter :: windlimit = 0.0001_kind_real
84  real(kind=kind_real), parameter :: quadcof (4, 2 ) = &
85  reshape((/0.0_kind_real, 1.0_kind_real, 1.0_kind_real, 2.0_kind_real, &
86  1.0_kind_real, -1.0_kind_real, 1.0_kind_real, -1.0_kind_real/), (/4, 2/))
87 
88  integer :: n, itype, istype
89  integer :: istyp00,istyp01,istyp10,istyp11
90  integer :: isflg, idomsfc
91  integer :: lai_type, iquadrant
92  logical :: lwind
93  real(kind=kind_real) :: dtsfc, dtsfcp
94  real(kind=kind_real) :: sfcpct(0:3), ts(0:3), wgtavg(0:3), dtskin(0:3)
95  real(kind=kind_real) :: w00,w01,w10,w11
96  real(kind=kind_real) :: sno00,sno01,sno10,sno11
97  real(kind=kind_real) :: sst00,sst01,sst10,sst11
98  real(kind=kind_real) :: tsavg,wgtmin
99  real(kind=kind_real) :: vty, sty, vfr, stp, sm, sn
100  real(kind=kind_real) :: uu5, vv5, f10, sfc_speed, windratio, windangle, windscale
101  real(kind=kind_real) :: wind10, wind10_direction
102 
103  !From GSI
104  integer, parameter :: gfs_soil_n_types = 9
105  integer, parameter :: gfs_vegetation_n_types = 13
106  integer, parameter :: invalid_land = 0
107  integer, parameter :: compacted_soil = 1
108  integer, parameter :: tilled_soil = 2
109  integer, parameter :: irrigated_low_vegetation = 5
110  integer, parameter :: meadow_grass = 6
111  integer, parameter :: scrub = 7
112  integer, parameter :: broadleaf_forest = 8
113  integer, parameter :: pine_forest = 9
114  integer, parameter :: tundra = 10
115  integer, parameter :: grass_soil = 11
116  integer, parameter :: broadleaf_pine_forest = 12
117  integer, parameter :: grass_scrub = 13
118  integer, parameter :: urban_concrete = 15
119  integer, parameter :: broadleaf_brush = 17
120  integer, parameter :: wet_soil = 18
121  integer, parameter :: scrub_soil = 19
122  integer, parameter :: nvege_type = 20
123  integer, parameter :: igbp_n_types = 20
124  integer, parameter :: soil_n_types = 16
125  integer, allocatable,dimension(:) :: map_to_crtm_ir
126  integer, allocatable,dimension(:) :: map_to_crtm_mwave
127  integer, parameter, dimension(1:IGBP_N_TYPES) :: igbp_to_gfs=(/4, &
128  1, 5, 2, 3, 8, 9, 6, 6, 7, 8, 12, 7, 12, 13, 11, 0, 10, 10, 11/)
129  integer, parameter, dimension(1:IGBP_N_TYPES) :: igbp_to_npoess=(/pine_forest, &
130  broadleaf_forest, pine_forest, broadleaf_forest, broadleaf_pine_forest, &
131  scrub, scrub_soil, broadleaf_brush, broadleaf_brush, scrub, broadleaf_brush, &
132  tilled_soil, urban_concrete, tilled_soil, invalid_land, compacted_soil, &
133  invalid_land, tundra, tundra, tundra/)
134  integer, parameter, dimension(1:IGBP_N_TYPES) :: igbp_to_igbp=(/1, &
135  2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, &
136  20/)
137  integer, parameter, dimension(1:SOIL_N_TYPES) :: map_soil_to_crtm=(/1, &
138  1, 4, 2, 2, 8, 7, 2, 6, 5, 2, 3, 8, 1, 6, 9/)
139 
140  !For interpolation
141  integer :: nn
142  real(kind=kind_real), allocatable, dimension(:,:) :: interp_w
143  integer , allocatable, dimension(:,:) :: interp_i
144  integer , allocatable, dimension(:,:) :: slmsk
145  real(kind=kind_real), allocatable, dimension(:,:) :: sheleg
146  real(kind=kind_real), allocatable, dimension(:,:) :: tsea
147  integer , allocatable, dimension(:,:) :: vtype
148  integer , allocatable, dimension(:,:) :: stype
149  real(kind=kind_real), allocatable, dimension(:,:) :: vfrac
150  real(kind=kind_real), allocatable, dimension(:,:) :: snwdph
151  real(kind=kind_real), allocatable, dimension(:,:) :: stc
152  real(kind=kind_real), allocatable, dimension(:,:) :: smc
153  real(kind=kind_real), allocatable, dimension(:,:) :: u_srf
154  real(kind=kind_real), allocatable, dimension(:,:) :: v_srf
155  real(kind=kind_real), allocatable, dimension(:,:) :: f10m
156  integer , allocatable, dimension(:,:) :: slmskp
157  real(kind=kind_real), allocatable, dimension(:,:) :: shelegp
158  real(kind=kind_real), allocatable, dimension(:,:) :: tseap
159  integer , allocatable, dimension(:,:) :: vtypep
160  integer , allocatable, dimension(:,:) :: stypep
161  real(kind=kind_real), allocatable, dimension(:,:) :: vfracp
162  real(kind=kind_real), allocatable, dimension(:,:) :: snwdphp
163  real(kind=kind_real), allocatable, dimension(:,:) :: stcp
164  real(kind=kind_real), allocatable, dimension(:,:) :: smcp
165  real(kind=kind_real), allocatable, dimension(:,:) :: u_srfp
166  real(kind=kind_real), allocatable, dimension(:,:) :: v_srfp
167  real(kind=kind_real), allocatable, dimension(:,:) :: f10mp
168 
169 !Number of weights
170 nn = 4
171 
172 allocate(interp_w(nobs,nn))
173 allocate(interp_i(nobs,nn))
174 allocate(slmsk(nobs,nn))
175 allocate(sheleg(nobs,nn))
176 allocate(tsea(nobs,nn))
177 allocate(vtype(nobs,nn))
178 allocate(stype(nobs,nn))
179 allocate(vfrac(nobs,nn))
180 allocate(stc(nobs,nn))
181 allocate(smc(nobs,nn))
182 allocate(snwdph(nobs,nn))
183 allocate(u_srf(nobs,nn))
184 allocate(v_srf(nobs,nn))
185 allocate(f10m(nobs,nn))
186 
187 allocate(slmskp(nobs,nn))
188 allocate(shelegp(nobs,nn))
189 allocate(tseap(nobs,nn))
190 allocate(vtypep(nobs,nn))
191 allocate(stypep(nobs,nn))
192 allocate(vfracp(nobs,nn))
193 allocate(stcp(nobs,nn))
194 allocate(smcp(nobs,nn))
195 allocate(snwdphp(nobs,nn))
196 allocate(u_srfp(nobs,nn))
197 allocate(v_srfp(nobs,nn))
198 allocate(f10mp(nobs,nn))
199 
200  !Second time level option, zero for now
201  slmskp = 0
202  shelegp = 0.0_kind_real
203  tseap = 0.0_kind_real
204  vtypep = 0.0_kind_real
205  stypep = 0
206  vfracp = 0
207  snwdphp = 0.0_kind_real
208  stcp = 0.0_kind_real
209  smcp = 0.0_kind_real
210  snwdphp = 0.0_kind_real
211  u_srfp = 0.0_kind_real
212  v_srfp = 0.0_kind_real
213  f10mp = 0.0_kind_real
214 
215  !Get interpolation weight and index in global grid
216  call crtm_surface_kdtree_setup( geom, nobs, ngrid, lats_ob, lons_ob, nn, interp_w, interp_i )
217 
218  !Get field at nn neighbours
219  call crtm_surface_kdtree_getfieldneighbours( geom, nobs, ngrid, nn, interp_i, fld_slmsk , slmsk )
220  call crtm_surface_kdtree_getfieldneighbours( geom, nobs, ngrid, nn, interp_i, fld_sheleg , sheleg )
221  call crtm_surface_kdtree_getfieldneighbours( geom, nobs, ngrid, nn, interp_i, fld_tsea , tsea )
222  call crtm_surface_kdtree_getfieldneighbours( geom, nobs, ngrid, nn, interp_i, fld_vtype , vtype )
223  call crtm_surface_kdtree_getfieldneighbours( geom, nobs, ngrid, nn, interp_i, fld_stype , stype )
224  call crtm_surface_kdtree_getfieldneighbours( geom, nobs, ngrid, nn, interp_i, fld_vfrac , vfrac )
225  call crtm_surface_kdtree_getfieldneighbours( geom, nobs, ngrid, nn, interp_i, fld_stc(:,:,1), stc )
226  call crtm_surface_kdtree_getfieldneighbours( geom, nobs, ngrid, nn, interp_i, fld_smc(:,:,1), smc )
227  call crtm_surface_kdtree_getfieldneighbours( geom, nobs, ngrid, nn, interp_i, fld_snwdph , snwdph )
228  call crtm_surface_kdtree_getfieldneighbours( geom, nobs, ngrid, nn, interp_i, fld_u_srf , u_srf )
229  call crtm_surface_kdtree_getfieldneighbours( geom, nobs, ngrid, nn, interp_i, fld_v_srf , v_srf )
230  call crtm_surface_kdtree_getfieldneighbours( geom, nobs, ngrid, nn, interp_i, fld_f10m , f10m )
231 
232  dtsfc = 1.0_kind_real
233  dtsfcp = 0.0_kind_real
234 
235  dtskin = 0.0_kind_real !TODO need real skin temperature increment?
236 
237  lwind = .true.
238 
239 ! Vegation, land and soil types
240 ! -----------------------------
241  allocate(map_to_crtm_ir(nvege_type))
242  allocate(map_to_crtm_mwave(nvege_type))
243 
244  map_to_crtm_mwave=igbp_to_gfs
245  map_to_crtm_ir = igbp_to_igbp
246 
247  !TODO, get this from CRTM properly
248  !select case ( TRIM(CRTM_IRlandCoeff_Classification()) )
249  ! case('NPOESS'); map_to_crtm_ir=igbp_to_npoess
250  ! case('IGBP') ; map_to_crtm_ir=igbp_to_igbp
251  !end select
252 
253  !Loop over all obs
254 
255  do n = 1,nobs
256 
257 ! Stage 1, like deter_sfc in GSI
258 ! ------------------------------
259 
260  w00 = interp_w(n,1)
261  w10 = interp_w(n,2)
262  w01 = interp_w(n,3)
263  w11 = interp_w(n,4)
264 
265  istyp00 = slmsk(n,1)
266  istyp10 = slmsk(n,2)
267  istyp01 = slmsk(n,3)
268  istyp11 = slmsk(n,4)
269 
270  sno00 = snwdph(n,1)*dtsfc + snwdphp(n,1)*dtsfcp
271  sno01 = snwdph(n,2)*dtsfc + snwdphp(n,2)*dtsfcp
272  sno10 = snwdph(n,3)*dtsfc + snwdphp(n,3)*dtsfcp
273  sno11 = snwdph(n,4)*dtsfc + snwdphp(n,4)*dtsfcp
274 
275  sst00 = tsea(n,1)*dtsfc + tsea(n,1)*dtsfcp
276  sst01 = tsea(n,2)*dtsfc + tsea(n,2)*dtsfcp
277  sst10 = tsea(n,3)*dtsfc + tsea(n,3)*dtsfcp
278  sst11 = tsea(n,4)*dtsfc + tsea(n,4)*dtsfcp
279 
280  tsavg = sst00*w00 + sst10*w10 + sst01*w01 + sst11*w11
281 
282  if (istyp00 >=1 .and. sno00 > minsnow) istyp00 = 3
283  if (istyp01 >=1 .and. sno01 > minsnow) istyp01 = 3
284  if (istyp10 >=1 .and. sno10 > minsnow) istyp10 = 3
285  if (istyp11 >=1 .and. sno11 > minsnow) istyp11 = 3
286 
287  sfcpct = 0.0_kind_real
288  sfcpct(istyp00) = sfcpct(istyp00) + w00
289  sfcpct(istyp01) = sfcpct(istyp01) + w01
290  sfcpct(istyp10) = sfcpct(istyp10) + w10
291  sfcpct(istyp11) = sfcpct(istyp11) + w11
292 
293  isflg = 0
294  if(sfcpct(0) > 0.99_kind_real)then
295  isflg = 0
296  else if(sfcpct(1) > 0.99_kind_real)then
297  isflg = 1
298  else if(sfcpct(2) > 0.99_kind_real)then
299  isflg = 2
300  else if(sfcpct(3) > 0.99_kind_real)then
301  isflg = 3
302  else
303  isflg = 4
304  end if
305 
306  ts(0:3)=0.0_kind_real
307  wgtavg(0:3)=0.0_kind_real
308  vfr=0.0_kind_real
309  stp=0.0_kind_real
310  sty=0.0_kind_real
311  vty=0.0_kind_real
312  sm=0.0_kind_real
313  sn=0.0_kind_real
314 
315  idomsfc=slmsk(n,1)
316  wgtmin = w00
317 
318  if(istyp00 == 1)then
319  vty = vtype(n,1)
320  sty = stype(n,1)
321  wgtavg(1) = wgtavg(1) + w00
322  ts(1)=ts(1)+w00*sst00
323  vfr =vfr +w00*( vfrac(n,1) * dtsfc + &
324  vfracp(n,1) * dtsfcp )
325  stp =stp +w00*( stc(n,1) * dtsfc + &
326  stcp(n,1) * dtsfcp )
327  sm =sm +w00*( smc(n,1) * dtsfc + &
328  smcp(n,1) * dtsfcp )
329  else if(istyp00 == 2)then
330  wgtavg(2) = wgtavg(2) + w00
331  ts(2)=ts(2)+w00*sst00
332  else if(istyp00 == 3)then
333  wgtavg(3) = wgtavg(3) + w00
334  ts(3)=ts(3)+w00*sst00
335  sn = sn + w00*sno00
336  else
337  wgtavg(0) = wgtavg(0) + w00
338  ts(0)=ts(0)+w00*sst00
339  end if
340 
341  if(istyp01 == 1)then
342  if(wgtmin < w01 .or. (vty == 0.0_kind_real .and. sty == 0.0_kind_real))then
343  vty = vtype(n,3)
344  sty = stype(n,3)
345  end if
346  wgtavg(1) = wgtavg(1) + w01
347  ts(1)=ts(1)+w01*sst01
348  vfr =vfr +w01*( vfrac(n,3) * dtsfc + &
349  vfracp(n,3) * dtsfcp )
350  stp =stp +w01*( stc(n,3) * dtsfc + &
351  stcp(n,3) * dtsfcp )
352  sm =sm +w01*( smc(n,3) * dtsfc + &
353  smcp(n,3) * dtsfcp )
354  else if(istyp01 == 2)then
355  wgtavg(2) = wgtavg(2) + w01
356  ts(2)=ts(2)+w01*sst01
357  else if(istyp01 == 3)then
358  wgtavg(3) = wgtavg(3) + w01
359  ts(3)=ts(3)+w01*sst01
360  sn = sn + w01*sno01
361  else
362  wgtavg(0) = wgtavg(0) + w01
363  ts(0)=ts(0)+w01*sst01
364  end if
365  if(wgtmin < w01)then
366  idomsfc=slmsk(n,3)
367  wgtmin = w01
368  end if
369 
370  if(istyp10 == 1)then
371  if(wgtmin < w10 .or. (vty == 0.0_kind_real .and. sty == 0.0_kind_real))then
372  vty = vtype(n,2)
373  sty = stype(n,2)
374  end if
375  wgtavg(1) = wgtavg(1) + w10
376  ts(1)=ts(1)+w10*sst10
377  vfr =vfr +w10*(vfrac(n,2) * dtsfc + &
378  vfracp(n,2) * dtsfcp )
379  stp =stp +w10*( stc(n,2) * dtsfc + &
380  stcp(n,2) * dtsfcp )
381  sm =sm +w10*( smc(n,2) * dtsfc + &
382  smcp(n,2) * dtsfcp )
383  else if(istyp10 == 2)then
384  wgtavg(2) = wgtavg(2) + w10
385  ts(2)=ts(2)+w10*sst10
386  else if(istyp10 == 3)then
387  wgtavg(3) = wgtavg(3) + w10
388  ts(3)=ts(3)+w10*sst10
389  sn = sn + w10*sno10
390  else
391  wgtavg(0) = wgtavg(0) + w10
392  ts(0)=ts(0)+w10*sst10
393  end if
394  if(wgtmin < w10)then
395  idomsfc=slmsk(n,2)
396  wgtmin = w10
397  end if
398 
399  if(istyp11 == 1)then
400  if(wgtmin < w11 .or. (vty == 0.0_kind_real .and. sty == 0.0_kind_real))then
401  vty = vtype(n,4)
402  sty = stype(n,4)
403  endif
404  wgtavg(1) = wgtavg(1) + w11
405  ts(1)=ts(1)+w11*sst11
406  vfr =vfr +w11*(vfrac(n,4) * dtsfc + &
407  vfracp(n,4) * dtsfcp )
408  stp =stp +w11*( stc(n,4) * dtsfc + &
409  stcp(n,4) * dtsfcp )
410  sm =sm +w11*( smc(n,4) * dtsfc + &
411  smcp(n,4) * dtsfcp )
412  else if(istyp11 == 2)then
413  wgtavg(2) = wgtavg(2) + w11
414  ts(2)=ts(2)+w11*sst11
415  else if(istyp11 == 3)then
416  wgtavg(3) = wgtavg(3) + w11
417  ts(3)=ts(3)+w11*sst11
418  sn = sn + w11*sno11
419  else
420  wgtavg(0) = wgtavg(0) + w11
421  ts(0)=ts(0)+w11*sst11
422  end if
423 
424  if(wgtmin < w11)then
425  idomsfc=slmsk(n,4)
426  wgtmin = w11
427  end if
428 
429  if(wgtavg(0) > 0.0_kind_real)then
430  ts(0) = ts(0)/wgtavg(0)
431  else
432  ts(0) = tsavg
433  end if
434 
435  if(wgtavg(1) > 0.0_kind_real)then
436  ts(1) = ts(1)/wgtavg(1)
437  sm = sm/wgtavg(1)
438  vfr = vfr/wgtavg(1)
439  stp = stp/wgtavg(1)
440  else
441  ts(1) = tsavg
442  sm=1.0_kind_real
443  end if
444 
445  if(wgtavg(2) > 0.0_kind_real)then
446  ts(2) = ts(2)/wgtavg(2)
447  else
448  ts(2) = tsavg
449  end if
450 
451  if(wgtavg(3) > 0.0_kind_real)then
452  ts(3) = ts(3)/wgtavg(3)
453  sn = sn/wgtavg(3)
454  else
455  ts(3) = tsavg
456  end if
457 
458  f10 = ( f10m(n,1)*w00 + f10m(n,2)*w10 + f10m(n,3)*w01 + f10m(n,4)*w11 ) * dtsfc + &
459  ( f10mp(n,1)*w00 + f10mp(n,2)*w10 + f10mp(n,3)*w01 + f10mp(n,4)*w11 ) * dtsfcp
460 
461 ! Stage 2 - like crtm_interface from GSI
462 ! --------------------------------------
463 
464  itype = vty
465  istype = sty
466 
467  itype = min(max(1,itype),nvege_type)
468  istype = min(max(1,istype),soil_n_types)
469  land_type(n) = max(1,map_to_crtm_ir(itype))
470  vegetation_type(n) = max(1,map_to_crtm_mwave(itype))
471  soil_type(n) = map_soil_to_crtm(istype)
472  lai_type = map_to_crtm_mwave(itype)
473 
474  water_coverage(n) = min(max(0.0_kind_real,sfcpct(0)),1.0_kind_real)
475  land_coverage(n) = min(max(0.0_kind_real,sfcpct(1)),1.0_kind_real)
476  ice_coverage(n) = min(max(0.0_kind_real,sfcpct(2)),1.0_kind_real)
477  snow_coverage(n) = min(max(0.0_kind_real,sfcpct(3)),1.0_kind_real)
478 
479  lai(n) = 0.0_kind_real
480 
481  if (land_coverage(n) > 0.0_kind_real) then
482 
483  if(lai_type>0)then
484  call get_lai(lai_type,lai(n)) !TODO: does nothing yet
485  endif
486 
487  ! for Glacial land ice soil type and vegetation type
488  if(soil_type(n) == 9 .OR. vegetation_type(n) == 13) then
489  ice_coverage(n) = min(ice_coverage(n) + land_coverage(n), 1.0_kind_real)
490  land_coverage(n) = 0.0_kind_real
491  endif
492 
493  endif
494 
495  if (lwind) then
496 
497  !Interpolate lowest level winds to observation location
498  uu5 = ( u_srf(n,1)*w00 + u_srf(n,2)*w10 + u_srf(n,3)*w01 + u_srf(n,4)*w11 ) * dtsfc + &
499  ( u_srfp(n,1)*w00 + u_srfp(n,2)*w10 + u_srfp(n,3)*w01 + u_srfp(n,4)*w11 ) * dtsfcp
500  vv5 = ( v_srf(n,1)*w00 + v_srf(n,2)*w10 + v_srf(n,3)*w01 + v_srf(n,4)*w11 ) * dtsfc + &
501  ( v_srfp(n,1)*w00 + v_srfp(n,2)*w10 + v_srfp(n,3)*w01 + v_srfp(n,4)*w11 ) * dtsfcp
502 
503  sfc_speed = f10*sqrt(uu5*uu5+vv5*vv5)
504  wind10 = sfc_speed
505  if (uu5*f10 >= 0.0_kind_real .and. vv5*f10 >= 0.0_kind_real) iquadrant = 1
506  if (uu5*f10 >= 0.0_kind_real .and. vv5*f10 < 0.0_kind_real) iquadrant = 2
507  if (uu5*f10 < 0.0_kind_real .and. vv5*f10 >= 0.0_kind_real) iquadrant = 4
508  if (uu5*f10 < 0.0_kind_real .and. vv5*f10 < 0.0_kind_real) iquadrant = 3
509  if (abs(vv5*f10) >= windlimit) then
510  windratio = (uu5*f10) / (vv5*f10)
511  else
512  windratio = 0.0_kind_real
513  if (abs(uu5*f10) > windlimit) then
514  windratio = windscale * uu5*f10
515  endif
516  endif
517  windangle = atan(abs(windratio)) ! wind azimuth is in radians
518  wind10_direction = quadcof(iquadrant, 1) * pi + windangle * quadcof(iquadrant, 2)
519  wind_speed(n) = sfc_speed
520  wind_direction(n) = rad2deg*wind10_direction
521 
522  else
523 
524  wind_speed(n) = 0.0_kind_real
525  wind_direction(n) = 0.0_kind_real
526 
527  endif
528 
529  water_temperature(n) = max(ts(0) + dtskin(0), 270._kind_real)
530 
531  !TODO, is nst_gsi ever > 1?
532  !if(nst_gsi > 1 .and. water_coverage(1) > 0.0_kind_real) then
533  !water_temperature(n) = max(data_s(itref)+data_s(idtw)-data_s(idtc) + dtskin(0), 271._kind_real)
534  !endif
535 
536  land_temperature(n) = ts(1) + dtskin(1)
537  ice_temperature(n) = min(ts(2) + dtskin(2), 280._kind_real)
538  snow_temperature(n) = min(ts(3) + dtskin(3), 280._kind_real)
539  soil_moisture_content(n) = sm
540  vegetation_fraction(n) = vfr
541  soil_temperature(n) = stp
542  snow_depth(n) = sn
543 
544  enddo
545 
546  deallocate(map_to_crtm_ir)
547  deallocate(map_to_crtm_mwave)
548 
549 end subroutine crtm_surface
550 
551 !----------------------------------------------------------------------------
552 !----------------------------------------------------------------------------
553 
554 subroutine crtm_surface_kdtree_setup( geom, nobs, ngrid, lats_ob, lons_ob, nn, interp_w, interp_i )
556 use mpp_mod, only: mpp_npes, mpp_pe
557 use mpi
558 use type_kdtree, only: kdtree_type
559 use type_mpl, only: mpl_type
560 
561 implicit none
562 
563 !Arguments
564 type(fv3jedi_geom) , intent(in) :: geom !Model geometry
565 integer , intent(in) :: nobs !Number of obs on this processor
566 integer , intent(in) :: ngrid !Number of grid points on this processor
567 real(kind=kind_real), intent(in) :: lats_ob(nobs) !Observation locations, lats
568 real(kind=kind_real), intent(in) :: lons_ob(nobs) !Observation locations, lons
569 integer , intent(in) :: nn !Number of neighbours to get back
570 real(kind=kind_real), intent(out) :: interp_w(nobs,nn) !Interpolation weights
571 integer , intent(out) :: interp_i(nobs,nn) !Interpolation indices (global unstructured grid)
572 
573 !Locals
574 integer :: npes, peid, ierr
575 integer :: i, j, k, l, n, jj, lowerb, upperb, ngrid_glo
576 real(kind=kind_real), allocatable :: grid_lat_loc(:), grid_lon_loc(:), grid_lat_glo(:), grid_lon_glo(:)
577 integer, allocatable :: ngridv(:), displs(:), rcvcnt(:)
578 logical, allocatable :: mask(:)
579 integer, allocatable :: nn_index(:,:)
580 real(kind=kind_real), allocatable :: nn_dist(:,:)
581 type(kdtree_type) :: kdtree
582 real(kind=kind_real) :: dist, tmplat(1), tmplon(1)
583 
584 type(mpl_type) :: mpl
585 
586 ! Gather the model grid to all processors
587 ! ---------------------------------------
588 
589 npes = mpp_npes()
590 peid = mpp_pe()
591 
592 !Unstructured local grid
593 allocate(grid_lat_loc(ngrid))
594 allocate(grid_lon_loc(ngrid))
595 jj = 0
596 do j = geom%jsc,geom%jec
597  do i = geom%isc,geom%iec
598  jj = jj + 1
599  grid_lat_loc(jj) = geom%grid_lat(i,j)
600  grid_lon_loc(jj) = geom%grid_lon(i,j)
601  enddo
602 enddo
603 
604 allocate(ngridv(0:npes-1))
605 allocate(displs(0:npes-1))
606 allocate(rcvcnt(0:npes-1))
607 
608 ngridv = 0
609 ngridv(peid) = ngrid
610 
611 do n = 0,npes-1
612  displs(n) = n
613  rcvcnt(n) = 1
614 enddo
615 
616 call mpi_allgatherv(ngrid, 1, mpi_int, ngridv, rcvcnt, displs, mpi_int, mpi_comm_world, ierr)
617 ngrid_glo = sum(ngridv)
618 
619 do n = 0,npes-1
620  rcvcnt(n) = ngridv(n)
621 enddo
622 displs(0) = 0
623 do n = 1,npes-1
624  displs(n) = displs(n-1) + rcvcnt(n-1)
625 enddo
626 
627 lowerb = displs(peid)+1
628 upperb = displs(peid)+rcvcnt(peid)
629 
630 allocate(grid_lat_glo(ngrid_glo))
631 allocate(grid_lon_glo(ngrid_glo))
632 
633 grid_lat_glo(lowerb:upperb) = grid_lat_loc
634 grid_lon_glo(lowerb:upperb) = grid_lon_loc
635 
636 call mpi_allgatherv(grid_lat_loc, rcvcnt(peid), mpi_real8, grid_lat_glo, rcvcnt, displs, mpi_real8, mpi_comm_world, ierr)
637 call mpi_allgatherv(grid_lon_loc, rcvcnt(peid), mpi_real8, grid_lon_glo, rcvcnt, displs, mpi_real8, mpi_comm_world, ierr)
638 
639 !Create cover tree for gloval grid
640 allocate(mask(ngrid_glo))
641 mask = .true.
642 
643 !Initialize mpl
644 call mpl%init()
645 
646 !Create kdtree
647 call kdtree%create(mpl,ngrid_glo,deg2rad*grid_lon_glo,deg2rad*grid_lat_glo,mask)
648 
649 
650 allocate(nn_index(nobs,nn))
651 allocate(nn_dist(nobs,nn))
652 
653 do k = 1,nobs
654 
655  tmplon(1) = deg2rad*lons_ob(k)
656  tmplat(1) = deg2rad*lats_ob(k)
657 
658  call kdtree%find_nearest_neighbors(tmplon(1),tmplat(1),nn,nn_index(k,:),nn_dist(k,:))
659 
660  dist=sum(nn_dist(k,:))
661 
662  do l = 1, nn
663  interp_w(k,l) = (dist-nn_dist(k,l))
664  interp_i(k,l) = nn_index(k,l)
665  end do
666 
667  interp_w(k,:) = interp_w(k,:) / sum(interp_w(k,:))
668 
669 enddo
670 
671 !Deallocate
672 call kdtree%dealloc
673 deallocate(mask)
674 deallocate(nn_index,nn_dist)
675 deallocate(grid_lon_glo,grid_lat_glo)
676 deallocate(grid_lat_loc,grid_lon_loc)
677 deallocate(ngridv,displs,rcvcnt)
678 
679 end subroutine crtm_surface_kdtree_setup
680 
681 !----------------------------------------------------------------------------
682 !----------------------------------------------------------------------------
683 
684 subroutine crtm_surface_kdtree_getfieldneighbours_int( geom, nobs, ngrid, nn, interp_i, field_in, field_out )
686 use mpp_mod, only: mpp_npes, mpp_pe
687 use mpi
688 
689 implicit none
690 
691 !Arguments
692 type(fv3jedi_geom) , intent(in) :: geom !Model geometry
693 integer , intent(in) :: nobs !Number of obs on this processor
694 integer , intent(in) :: ngrid !Number of grid points on this processor
695 integer , intent(in) :: nn !Number of neighbours
696 integer , intent(in) :: interp_i(nobs,nn) !Interpolation index
697 
698 integer , intent(in) :: field_in(geom%isc:geom%iec,geom%jsc:geom%jec) !Fields in
699 integer , intent(out) :: field_out(nobs,nn) !Field nearest neighbours
700 
701 !Locals
702 integer :: npes, peid, ierr
703 integer :: i, j, k, l, n, jj, lowerb, upperb, ngrid_glo
704 integer, allocatable :: field_loc(:), field_glo(:)
705 integer, allocatable :: ngridv(:), displs(:), rcvcnt(:)
706 
707 
708 ! Gather the model grid to all processors
709 ! ---------------------------------------
710 
711 npes = mpp_npes()
712 peid = mpp_pe()
713 
714 !Unstructured local grid
715 allocate(field_loc(ngrid))
716 jj = 0
717 do j = geom%jsc,geom%jec
718  do i = geom%isc,geom%iec
719  jj = jj + 1
720  field_loc(jj) = field_in(i,j)
721  enddo
722 enddo
723 
724 allocate(ngridv(0:npes-1))
725 allocate(displs(0:npes-1))
726 allocate(rcvcnt(0:npes-1))
727 
728 ngridv = 0
729 ngridv(peid) = ngrid
730 
731 do n = 0,npes-1
732  displs(n) = n
733  rcvcnt(n) = 1
734 enddo
735 
736 call mpi_allgatherv(ngrid, 1, mpi_int, ngridv, rcvcnt, displs, mpi_int, mpi_comm_world, ierr)
737 ngrid_glo = sum(ngridv)
738 
739 do n = 0,npes-1
740  rcvcnt(n) = ngridv(n)
741 enddo
742 displs(0) = 0
743 do n = 1,npes-1
744  displs(n) = displs(n-1) + rcvcnt(n-1)
745 enddo
746 
747 lowerb = displs(peid)+1
748 upperb = displs(peid)+rcvcnt(peid)
749 
750 allocate(field_glo(ngrid_glo))
751 
752 field_glo(lowerb:upperb) = field_loc
753 
754 call mpi_allgatherv(field_loc, rcvcnt(peid), mpi_int, field_glo, rcvcnt, displs, mpi_int, mpi_comm_world, ierr)
755 
756 
757 do k = 1,nobs
758  field_out(k,1) = field_glo(interp_i(k,1))
759  field_out(k,2) = field_glo(interp_i(k,2))
760  field_out(k,3) = field_glo(interp_i(k,3))
761  field_out(k,4) = field_glo(interp_i(k,4))
762 enddo
763 
764 
765 deallocate(field_glo)
766 deallocate(ngridv,displs,rcvcnt)
767 deallocate(field_loc)
768 
770 
771 subroutine crtm_surface_kdtree_getfieldneighbours_real( geom, nobs, ngrid, nn, interp_i, field_in, field_out )
773 use mpp_mod, only: mpp_npes, mpp_pe
774 use mpi
775 
776 !Arguments
777 type(fv3jedi_geom) , intent(in) :: geom !Model geometry
778 integer , intent(in) :: nobs !Number of obs on this processor
779 integer , intent(in) :: ngrid !Number of grid points on this processor
780 integer , intent(in) :: nn !Number of neighbours
781 integer , intent(in) :: interp_i(nobs,nn) !Interpolation index
782 
783 real(kind=kind_real), intent(in) :: field_in(geom%isc:geom%iec,geom%jsc:geom%jec) !Fields in
784 real(kind=kind_real), intent(out) :: field_out(nobs,nn) !Field nearest neighbours
785 
786 !Locals
787 integer :: npes, peid, ierr
788 integer :: i, j, k, l, n, jj, lowerb, upperb, ngrid_glo
789 real(kind=kind_real), allocatable :: field_loc(:), field_glo(:)
790 integer, allocatable :: ngridv(:), displs(:), rcvcnt(:)
791 
792 ! Gather the model grid to all processors
793 ! ---------------------------------------
794 
795 npes = mpp_npes()
796 peid = mpp_pe()
797 
798 !Unstructured local grid
799 allocate(field_loc(ngrid))
800 jj = 0
801 do j = geom%jsc,geom%jec
802  do i = geom%isc,geom%iec
803  jj = jj + 1
804  field_loc(jj) = field_in(i,j)
805  enddo
806 enddo
807 
808 allocate(ngridv(0:npes-1))
809 allocate(displs(0:npes-1))
810 allocate(rcvcnt(0:npes-1))
811 
812 ngridv = 0
813 ngridv(peid) = ngrid
814 
815 do n = 0,npes-1
816  displs(n) = n
817  rcvcnt(n) = 1
818 enddo
819 
820 call mpi_allgatherv(ngrid, 1, mpi_int, ngridv, rcvcnt, displs, mpi_int, mpi_comm_world, ierr)
821 ngrid_glo = sum(ngridv)
822 
823 do n = 0,npes-1
824  rcvcnt(n) = ngridv(n)
825 enddo
826 displs(0) = 0
827 do n = 1,npes-1
828  displs(n) = displs(n-1) + rcvcnt(n-1)
829 enddo
830 
831 lowerb = displs(peid)+1
832 upperb = displs(peid)+rcvcnt(peid)
833 
834 allocate(field_glo(ngrid_glo))
835 
836 field_glo(lowerb:upperb) = field_loc
837 
838 call mpi_allgatherv(field_loc, rcvcnt(peid), mpi_real8, field_glo, rcvcnt, displs, mpi_real8, mpi_comm_world, ierr)
839 
840 do k = 1,nobs
841  field_out(k,1) = field_glo(interp_i(k,1))
842  field_out(k,2) = field_glo(interp_i(k,2))
843  field_out(k,3) = field_glo(interp_i(k,3))
844  field_out(k,4) = field_glo(interp_i(k,4))
845 enddo
846 
847 deallocate(field_glo)
848 deallocate(ngridv,displs,rcvcnt)
849 deallocate(field_loc)
850 
852 
853 !----------------------------------------------------------------------------
854 !----------------------------------------------------------------------------
855 
856 subroutine get_lai(lai_type,lai)
858  implicit none
859 
860  integer , intent(in ) :: lai_type
861  real(kind=kind_real), intent(out) :: lai
862 
863  !Needs to be figured out
864 
865  end subroutine get_lai
866 
867 !----------------------------------------------------------------------------
868 !----------------------------------------------------------------------------
869 
870 end module surface_vt_mod
real(kind=kind_real), parameter, public deg2rad
subroutine crtm_surface_kdtree_getfieldneighbours_int(geom, nobs, ngrid, nn, interp_i, field_in, field_out)
real(kind=kind_real), parameter, public rad2deg
subroutine crtm_surface_kdtree_getfieldneighbours_real(geom, nobs, ngrid, nn, interp_i, field_in, field_out)
Fortran derived type to hold geometry data for the FV3JEDI model.
Definition: mpp.F90:39
subroutine get_lai(lai_type, lai)
Fortran module handling geometry for the FV3 model.
#define max(a, b)
Definition: mosaic_util.h:33
subroutine, public crtm_surface_kdtree_setup(geom, nobs, ngrid, lats_ob, lons_ob, nn, interp_w, interp_i)
subroutine, public crtm_surface(geom, nobs, ngrid, lats_ob, lons_ob, fld_slmsk, fld_sheleg, fld_tsea, fld_vtype, fld_stype, fld_vfrac, fld_stc, fld_smc, fld_snwdph, fld_u_srf, fld_v_srf, fld_f10m, land_type, vegetation_type, soil_type, water_coverage, land_coverage, ice_coverage, snow_coverage, lai, water_temperature, land_temperature, ice_temperature, snow_temperature, soil_moisture_content, vegetation_fraction, soil_temperature, snow_depth, wind_speed, wind_direction)
Variable transforms/interpolation for surface variables in fv3-jedi Daniel Holdaway, NASA/JCSDA.
integer, parameter, public kind_real
#define min(a, b)
Definition: mosaic_util.h:32
real(fp), parameter, public pi