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