NCEPLIBS-ip  4.3.0
ip_grid_descriptor_mod.F90
Go to the documentation of this file.
1 
5 
16  implicit none
17 
18  private
19 
20  public :: ip_grid_descriptor
23 
24  public :: operator(==)
25 
28  type, abstract :: ip_grid_descriptor
29  integer :: grid_num
30  contains
32  procedure :: is_same_grid
33  end type ip_grid_descriptor
34 
39  integer :: gds(200)
40  contains
42  procedure :: is_same_grid_grib1
43  end type grib1_descriptor
44 
48  integer :: gdt_num
49  integer :: gdt_len
50  integer, allocatable :: gdt_tmpl(:)
51  contains
53  procedure :: is_same_grid_grib2
54  end type grib2_descriptor
55 
56  interface operator (==)
57  module procedure is_same_grid
58  end interface operator (==)
59 
60  interface init_descriptor
61  module procedure init_grib1_descriptor
62  module procedure init_grib2_descriptor
63  end interface init_descriptor
64 
65 contains
66 
74  function init_grib1_descriptor(gds) result(desc)
75  type(grib1_descriptor) :: desc
76  integer, intent(in) :: gds(:)
77  desc%gds = gds
78  desc%grid_num = gds(1)
79 
80  !call desc%decode_template()
81 
82  end function init_grib1_descriptor
83 
93  function init_grib2_descriptor(gdt_num, gdt_len, gdt_tmpl) result(desc)
94  type(grib2_descriptor) :: desc
95  integer, intent(in) :: gdt_num, gdt_len, gdt_tmpl(:)
96  desc%grid_num = gdt_num
97 
98  desc%gdt_num = gdt_num
99  desc%gdt_len = gdt_len
100  allocate(desc%gdt_tmpl(gdt_len))
101  desc%gdt_tmpl = gdt_tmpl
102 
103  !call desc%decode_template()
104 
105  end function init_grib2_descriptor
106 
115  logical function is_same_grid(grid1, grid2)
116  class(ip_grid_descriptor), intent(in) :: grid1, grid2
117 
118  select type(grid1)
119  type is(grib1_descriptor)
120  select type(grid2)
121  type is(grib1_descriptor)
122  is_same_grid = grid1%is_same_grid_grib1(grid2)
123  class default
124  is_same_grid = .false.
125  end select
126  type is(grib2_descriptor)
127  select type(grid2)
128  type is(grib2_descriptor)
129  is_same_grid = grid1%is_same_grid_grib2(grid2)
130  class default
131  is_same_grid = .false.
132  end select
133  end select
134 
135  end function is_same_grid
136 
145  logical function is_same_grid_grib1(self, grid_desc) result(same_grid)
146  class(grib1_descriptor), intent(in) :: self, grid_desc
147 
148  if (all(self%gds == grid_desc%gds)) then
149  same_grid = .true.
150  else
151  same_grid = .false.
152  end if
153 
154  end function is_same_grid_grib1
155 
164  logical function is_same_grid_grib2(self, grid_desc) result(same_grid)
165  class(grib2_descriptor), intent(in) :: self, grid_desc
166 
167  same_grid = .false.
168  if (self%grid_num == grid_desc%grid_num) then
169  if (self%gdt_len == grid_desc%gdt_len) then
170  if (all(self%gdt_tmpl == grid_desc%gdt_tmpl)) then
171  same_grid = .true.
172  end if
173  end if
174  end if
175 
176  end function is_same_grid_grib2
177 
178 
179 
180  ! subroutine decode_template_grib1(self)
181  ! type(grib1_descriptor), intent(inout) :: self
182 
183  ! integer :: im, jm, iwrap, jg
184  ! integer :: iscan, kscan, nscan, nscan_field_pos
185  ! integer :: jwrap1, jwrap2
186 
187  ! real :: dlat, dlon
188  ! real :: rlat1, rlat2
189  ! real :: rlon1, rlon2
190 
191  ! ! set a default value for this to check if it has changed
192  ! ! for rotated grids nscan is set = 3, but in other places it's not, so use this special value
193  ! ! just for field_position routine
194  ! nscan_field_pos = -1
195 
196  ! im = self%gds(2)
197  ! jm = self%gds(3)
198  ! iwrap = 0
199  ! jwrap1 = 0
200  ! jwrap2 = 0
201  ! nscan = mod(self%gds(11) / 32, 2)
202  ! kscan = 0
203 
204  ! select case(self%gds(1))
205  ! case(0)
206  ! rlon1=self%gds(5)*1.e-3
207  ! rlon2=self%gds(8)*1.e-3
208  ! iscan=mod(self%gds(11)/128,2)
209  ! if(iscan.eq.0) then
210  ! dlon=(mod(rlon2-rlon1-1+3600,360.)+1)/(im-1)
211  ! else
212  ! dlon=-(mod(rlon1-rlon2-1+3600,360.)+1)/(im-1)
213  ! endif
214  ! iwrap=nint(360/abs(dlon))
215  ! if(im.lt.iwrap) iwrap=0
216  ! if(iwrap.gt.0.and.mod(iwrap,2).eq.0) then
217  ! rlat1=self%gds(4)*1.e-3
218  ! rlat2=self%gds(7)*1.e-3
219  ! dlat=abs(rlat2-rlat1)/(jm-1)
220  ! if(abs(rlat1).gt.90-0.25*dlat) then
221  ! jwrap1=2
222  ! elseif(abs(rlat1).gt.90-0.75*dlat) then
223  ! jwrap1=1
224  ! endif
225  ! if(abs(rlat2).gt.90-0.25*dlat) then
226  ! jwrap2=2*jm
227  ! elseif(abs(rlat2).gt.90-0.75*dlat) then
228  ! jwrap2=2*jm+1
229  ! endif
230  ! endif
231  ! case(1)
232  ! rlon1=self%gds(5)*1.e-3
233  ! rlon2=self%gds(8)*1.e-3
234  ! iscan=mod(self%gds(11)/128,2)
235  ! if(iscan.eq.0) then
236  ! dlon=(mod(rlon2-rlon1-1+3600,360.)+1)/(im-1)
237  ! else
238  ! dlon=-(mod(rlon1-rlon2-1+3600,360.)+1)/(im-1)
239  ! endif
240  ! iwrap=nint(360/abs(dlon))
241  ! if(im.lt.iwrap) iwrap=0
242  ! case(4)
243  ! rlon1=self%gds(5)*1.e-3
244  ! rlon2=self%gds(8)*1.e-3
245  ! iscan=mod(self%gds(11)/128,2)
246  ! if(iscan.eq.0) then
247  ! dlon=(mod(rlon2-rlon1-1+3600,360.)+1)/(im-1)
248  ! else
249  ! dlon=-(mod(rlon1-rlon2-1+3600,360.)+1)/(im-1)
250  ! endif
251  ! iwrap=nint(360/abs(dlon))
252  ! if(im.lt.iwrap) iwrap=0
253  ! if(iwrap.gt.0.and.mod(iwrap,2).eq.0) then
254  ! jg=self%gds(10)*2
255  ! if(jm.eq.jg) then
256  ! jwrap1=1
257  ! jwrap2=2*jm+1
258  ! endif
259  ! endif
260  ! case(203)
261  ! ! why is nscan set to 3 for this grid?
262  ! nscan_field_pos = 3
263  ! kscan=mod(self%gds(11) / 256, 2)
264  ! case default
265  ! print *, "grib1 grid type ", self%gds(1), " not recognized"
266  ! error stop
267  ! end select
268 
269  ! self%im = im
270  ! self%jm = jm
271  ! self%nm = im * jm
272  ! self%iwrap = iwrap
273  ! self%jwrap1 = jwrap1
274  ! self%jwrap2 = jwrap2
275  ! self%nscan = nscan
276 
277  ! if (nscan_field_pos == -1) then
278  ! ! just use regular value of nscan
279  ! self%nscan_field_pos = nscan
280  ! else
281  ! ! nscan = 3 for rotated grids and is set to 3 for use in field_position
282  ! self%nscan_field_pos = nscan_field_pos
283  ! end if
284 
285  ! self%kscan = kscan
286 
287  ! end subroutine decode_template_grib1
288 
289  ! subroutine decode_template_grib2(self)
290  ! type(grib2_descriptor), intent(inout) :: self
291 
292  ! integer :: im, jm, iwrap, jg
293  ! integer :: i_offset_odd, i_offset_even
294  ! integer :: iscan, kscan, nscan, nscan_field_pos
295  ! integer :: jwrap1, jwrap2, iscale
296 
297  ! real :: dlat, dlon
298  ! real :: rlat1, rlat2
299  ! real :: rlon1, rlon2
300 
301  ! nscan_field_pos = -1
302 
303  ! select case(self%gdt_num)
304  ! ! EQUIDISTANT CYLINDRICAL
305  ! case(0)
306  ! im=self%gdt_tmpl(8)
307  ! jm=self%gdt_tmpl(9)
308  ! nscan=mod(self%gdt_tmpl(19)/32,2)
309  ! kscan=0
310  ! iscale=self%gdt_tmpl(10)*self%gdt_tmpl(11)
311  ! if(iscale==0) iscale=10**6
312  ! rlon1=float(self%gdt_tmpl(13))/float(iscale)
313  ! rlon2=float(self%gdt_tmpl(16))/float(iscale)
314  ! iscan=mod(self%gdt_tmpl(19)/128,2)
315  ! if(iscan.eq.0) then
316  ! dlon=(mod(rlon2-rlon1-1+3600,360.)+1)/(im-1)
317  ! else
318  ! dlon=-(mod(rlon1-rlon2-1+3600,360.)+1)/(im-1)
319  ! endif
320  ! iwrap=nint(360/abs(dlon))
321  ! if(im.lt.iwrap) iwrap=0
322  ! jwrap1=0
323  ! jwrap2=0
324  ! if(iwrap.gt.0.and.mod(iwrap,2).eq.0) then
325  ! rlat1=float(self%gdt_tmpl(12))/float(iscale)
326  ! rlat2=float(self%gdt_tmpl(15))/float(iscale)
327  ! dlat=abs(rlat2-rlat1)/(jm-1)
328  ! if(abs(rlat1).gt.90-0.25*dlat) then
329  ! jwrap1=2
330  ! elseif(abs(rlat1).gt.90-0.75*dlat) then
331  ! jwrap1=1
332  ! endif
333  ! if(abs(rlat2).gt.90-0.25*dlat) then
334  ! jwrap2=2*jm
335  ! elseif(abs(rlat2).gt.90-0.75*dlat) then
336  ! jwrap2=2*jm+1
337  ! endif
338  ! endif
339  ! case(1)
340  ! i_offset_odd=mod(self%gdt_tmpl(19)/8,2)
341  ! i_offset_even=mod(self%gdt_tmpl(19)/4,2)
342  ! im=self%gdt_tmpl(8)
343  ! jm=self%gdt_tmpl(9)
344  ! iwrap=0
345  ! jwrap1=0
346  ! jwrap2=0
347  ! kscan=0
348  ! nscan=mod(self%gdt_tmpl(19)/32,2)
349  ! if(i_offset_odd/=i_offset_even)then
350  ! kscan=i_offset_odd
351  ! nscan_field_pos=3
352  ! endif
353  ! ! MERCATOR CYLINDRICAL
354  ! case(10)
355  ! im=self%gdt_tmpl(8)
356  ! jm=self%gdt_tmpl(9)
357  ! rlon1=float(self%gdt_tmpl(11))*1.0e-6
358  ! rlon2=float(self%gdt_tmpl(15))*1.0e-6
359  ! iscan=mod(self%gdt_tmpl(16)/128,2)
360  ! if(iscan.eq.0) then
361  ! dlon=(mod(rlon2-rlon1-1+3600,360.)+1)/(im-1)
362  ! else
363  ! dlon=-(mod(rlon1-rlon2-1+3600,360.)+1)/(im-1)
364  ! endif
365  ! iwrap=nint(360/abs(dlon))
366  ! if(im.lt.iwrap) iwrap=0
367  ! jwrap1=0
368  ! jwrap2=0
369  ! kscan=0
370  ! nscan=mod(self%gdt_tmpl(16)/32,2)
371  ! ! POLAR STEREOGRAPHIC AZIMUTHAL
372  ! case(20)
373  ! im=self%gdt_tmpl(8)
374  ! jm=self%gdt_tmpl(9)
375  ! nscan=mod(self%gdt_tmpl(18)/32,2)
376  ! iwrap=0
377  ! jwrap1=0
378  ! jwrap2=0
379  ! kscan=0
380  ! ! LAMBERT CONFORMAL CONICAL
381  ! case(30)
382  ! im=self%gdt_tmpl(8)
383  ! jm=self%gdt_tmpl(9)
384  ! nscan=mod(self%gdt_tmpl(18)/32,2)
385  ! iwrap=0
386  ! jwrap1=0
387  ! jwrap2=0
388  ! kscan=0
389  ! ! GAUSSIAN CYLINDRICAL
390  ! case(40)
391  ! im=self%gdt_tmpl(8)
392  ! jm=self%gdt_tmpl(9)
393  ! iscale=self%gdt_tmpl(10)*self%gdt_tmpl(11)
394  ! if(iscale==0) iscale=10**6
395  ! rlon1=float(self%gdt_tmpl(13))/float(iscale)
396  ! rlon2=float(self%gdt_tmpl(16))/float(iscale)
397  ! iscan=mod(self%gdt_tmpl(19)/128,2)
398  ! if(iscan.eq.0) then
399  ! dlon=(mod(rlon2-rlon1-1+3600,360.)+1)/(im-1)
400  ! else
401  ! dlon=-(mod(rlon1-rlon2-1+3600,360.)+1)/(im-1)
402  ! endif
403  ! iwrap=nint(360/abs(dlon))
404  ! if(im.lt.iwrap) iwrap=0
405  ! jwrap1=0
406  ! jwrap2=0
407  ! if(iwrap.gt.0.and.mod(iwrap,2).eq.0) then
408  ! jg=self%gdt_tmpl(18)*2
409  ! if(jm.eq.jg) then
410  ! jwrap1=1
411  ! jwrap2=2*jm+1
412  ! endif
413  ! endif
414  ! nscan=mod(self%gdt_tmpl(19)/32,2)
415  ! kscan=0
416  ! case default
417  ! print *, "gdt_num ", self%gdt_num, " not recognized"
418  ! error stop
419  ! end select
420 
421  ! self%im = im
422  ! self%jm = jm
423  ! self%nm = im*jm
424  ! self%iwrap = iwrap
425  ! self%jwrap1 = jwrap1
426  ! self%jwrap2 = jwrap2
427  ! self%nscan = nscan
428  ! if (nscan_field_pos == -1) then
429  ! self%nscan_field_pos = nscan
430  ! else
431  ! self%nscan_field_pos = nscan_field_pos
432  ! end if
433  ! self%kscan = kscan
434 
435  ! end subroutine decode_template_grib2
436 
437  ! subroutine earth_radius(self, radius, eccen_squared)
438  ! class(ip_grid_descriptor), intent(in) :: self
439  ! real, intent(out) :: radius, eccen_squared
440 
441  ! real :: flat, major_axis, minor_axis
442  ! logical :: elliptical
443 
444  ! select type(self)
445  ! type is(grib1_descriptor)
446  ! associate(gds => self%gds)
447  ! select case(gds(1))
448  ! case(0)
449  ! radius = 6.3712d6
450  ! eccen_squared = 0d0
451  ! case(1)
452  ! radius = 6.3712d6
453  ! eccen_squared = 0d0
454  ! case(3)
455  ! radius = 6.3712d6
456  ! eccen_squared = 0d0
457  ! case(4)
458  ! radius = 6.3712d6
459  ! eccen_squared = 0d0
460  ! case(5)
461  ! elliptical = mod(gds(6) / 64, 2) == 1
462  ! if (.not. elliptical) then
463  ! radius = 6.3712d6
464  ! eccen_squared = 0d0
465  ! else
466  ! radius = 6.378137E6 ! WGS-84
467  ! eccen_squared = 0.00669437999013d0
468  ! end if
469  ! case(203)
470  ! radius = 6.3712d6
471  ! eccen_squared = 0d0
472  ! case(205)
473  ! radius = 6.3712d6
474  ! eccen_squared = 0d0
475  ! case default
476  ! print *, "grib1 grid not recognized. gds(1) = ", gds(1)
477  ! error stop
478  ! end select
479  ! end associate
480  ! type is(grib2_descriptor)
481  ! associate(gdt_tmpl => self%gdt_tmpl)
482  ! select case (gdt_tmpl(1))
483  ! case (0)
484  ! radius = 6367470.0
485  ! eccen_squared = 0.0
486  ! case (1) ! user specified spherical
487  ! radius = float(gdt_tmpl(3))/float(10**gdt_tmpl(2))
488  ! eccen_squared = 0.0
489  ! case (2) ! iau 1965
490  ! radius = 6378160.0 ! semi major axis
491  ! flat = 1.0/297.0 ! flattening
492  ! eccen_squared = (2.0*flat) - (flat**2)
493  ! case (3) ! user specified elliptical (km)
494  ! major_axis = float(gdt_tmpl(5))/float(10**gdt_tmpl(4))
495  ! major_axis = major_axis * 1000.0
496  ! minor_axis = float(gdt_tmpl(7))/float(10**gdt_tmpl(6))
497  ! minor_axis = minor_axis * 1000.0
498  ! eccen_squared = 1.0 - (minor_axis**2 / major_axis**2)
499  ! radius = major_axis
500  ! case (4) ! iag-grs80 model
501  ! radius = 6378137.0 ! semi major axis
502  ! flat = 1.0/298.2572 ! flattening
503  ! eccen_squared = (2.0*flat) - (flat**2)
504  ! case (5) ! wgs84 datum
505  ! radius = 6378137.0 ! semi major axis
506  ! eccen_squared = 0.00669437999013
507  ! case (6)
508  ! radius = 6371229.0
509  ! eccen_squared = 0.0
510  ! case (7) ! user specified elliptical (m)
511  ! major_axis = float(gdt_tmpl(5))/float(10**gdt_tmpl(4))
512  ! minor_axis = float(gdt_tmpl(7))/float(10**gdt_tmpl(6))
513  ! eccen_squared = 1.0 - (minor_axis**2 / major_axis**2)
514  ! radius = major_axis
515  ! case (8)
516  ! radius = 6371200.0
517  ! eccen_squared = 0.0
518  ! case default
519  ! radius = -9999.
520  ! eccen_squared = -9999.
521  ! error stop
522  ! end select
523  ! end associate
524  ! class default
525  ! print *, "unknown descriptor type"
526  ! error stop
527  ! end select
528  ! end subroutine earth_radius
529 
530 end module ip_grid_descriptor_mod
Users derived type grid descriptor objects to abstract away the raw GRIB1 and GRIB2 grid definitions.
type(grib2_descriptor) function, public init_grib2_descriptor(gdt_num, gdt_len, gdt_tmpl)
Initialize grib-2 descriptor from integer grid definition template (GDT).
logical function is_same_grid(grid1, grid2)
Test whether two grid descriptors are the same.
logical function is_same_grid_grib1(self, grid_desc)
Test whether two grib1_descriptors are the same.
logical function is_same_grid_grib2(self, grid_desc)
Test whether two grib2_descriptors are the same.
type(grib1_descriptor) function, public init_grib1_descriptor(gds)
Initialize grib-1 descriptor from integer grid definition section (GDS).
Descriptor representing a grib1 grib descriptor section (GDS) with an integer array.
Grib-2 descriptor containing a grib2 GDT represented by an integer array.
Abstract descriptor object which represents a grib1 or grib2 descriptor.