NCEPLIBS-ip 5.2.0
Loading...
Searching...
No Matches
ip_gaussian_grid_mod.F90
Go to the documentation of this file.
1
5
16 use ip_grid_mod
19 use sp_mod
20 implicit none
21
22 private
23 public :: ip_gaussian_grid
24
25 type, extends(ip_grid) :: ip_gaussian_grid
26 integer :: jh
27 real :: dlon
28 real :: rlat1
29 real :: rlon1
30 real :: rlon2
31 real :: hi
32 integer :: jg
33 integer :: jscan
34 contains
37 procedure :: init_grib1
40 procedure :: init_grib2
44 procedure :: gdswzd => gdswzd_gaussian
45 end type ip_gaussian_grid
46
47 INTEGER :: j1
48 INTEGER :: jh
49 REAL, ALLOCATABLE :: blat(:)
50 REAL :: dlon
51 REAL :: rerth
52 REAL, ALLOCATABLE :: ylat_row(:)
53
54contains
55
63 subroutine init_grib1(self, g1_desc)
64 class(ip_gaussian_grid), intent(inout) :: self
65 type(grib1_descriptor), intent(in) :: g1_desc
66
67 integer :: iscan, jg
68
69 associate(kgds => g1_desc%gds)
70 self%rerth = 6.3712e6
71 self%eccen_squared = 0.0
72
73 self%IM=kgds(2)
74 self%JM=kgds(3)
75 self%RLAT1=kgds(4)*1.e-3
76 self%RLON1=kgds(5)*1.e-3
77 self%RLON2=kgds(8)*1.e-3
78 self%JG=kgds(10)*2
79 iscan=mod(kgds(11)/128,2)
80 self%JSCAN=mod(kgds(11)/64,2)
81 self%HI=(-1.)**iscan
82 self%JH=(-1)**self%JSCAN
83 self%DLON=self%HI*(mod(self%HI*(self%RLON2-self%RLON1)-1+3600,360.)+1)/(self%IM-1)
84
85 self%iwrap = 0
86 self%jwrap1 = 0
87 self%jwrap2 = 0
88 self%nscan = mod(kgds(11) / 32, 2)
89 self%nscan_field_pos = self%nscan
90 self%kscan = 0
91
92 self%iwrap=nint(360 / abs(self%dlon))
93 if(self%im < self%iwrap) self%iwrap = 0
94
95 if(self%iwrap > 0 .and. mod(self%iwrap, 2) == 0) then
96 jg=kgds(10)*2
97 if(self%jm == self%jg) then
98 self%jwrap1 = 1
99 self%jwrap2 = 2 * self%jm + 1
100 endif
101 endif
102
103 end associate
104 end subroutine init_grib1
105
112 subroutine init_grib2(self, g2_desc)
113 class(ip_gaussian_grid), intent(inout) :: self
114 type(grib2_descriptor), intent(in) :: g2_desc
115
116 integer :: iscale, iscan, jg
117
118 associate(igdtmpl => g2_desc%gdt_tmpl, igdtlen => g2_desc%gdt_len)
119 call earth_radius(igdtmpl, igdtlen, self%rerth, self%eccen_squared)
120
121 self%IM=igdtmpl(8)
122 self%JM=igdtmpl(9)
123 iscale=igdtmpl(10)*igdtmpl(11)
124 IF(iscale==0) iscale=10**6
125 self%RLAT1=float(igdtmpl(12))/float(iscale)
126 self%RLON1=float(igdtmpl(13))/float(iscale)
127 self%RLON2=float(igdtmpl(16))/float(iscale)
128 self%JG=igdtmpl(18)*2
129 iscan=mod(igdtmpl(19)/128,2)
130 self%JSCAN=mod(igdtmpl(19)/64,2)
131 self%HI=(-1.)**iscan
132 self%JH=(-1)**self%JSCAN
133 self%DLON=self%HI*(mod(self%HI*(self%RLON2-self%RLON1)-1+3600,360.)+1)/(self%IM-1)
134
135
136 self%iwrap = nint(360 / abs(self%dlon))
137 if(self%im < self%iwrap) self%iwrap = 0
138 self%jwrap1 = 0
139 self%jwrap2 = 0
140 if(self%iwrap > 0 .and. mod(self%iwrap, 2) == 0) then
141 jg = igdtmpl(18) * 2
142 if(self%jm == jg) then
143 self%jwrap1=1
144 self%jwrap2 = 2 * self%jm + 1
145 endif
146 endif
147 self%nscan = mod(igdtmpl(19) / 32, 2)
148 self%nscan_field_pos = self%nscan
149 self%kscan = 0
150 end associate
151
152 end subroutine init_grib2
153
198 SUBROUTINE gdswzd_gaussian(self,IOPT,NPTS,FILL, &
199 XPTS,YPTS,RLON,RLAT,NRET, &
200 CROT,SROT,XLON,XLAT,YLON,YLAT,AREA)
201 IMPLICIT NONE
202 !
203 class(ip_gaussian_grid), intent(in) :: self
204 INTEGER, INTENT(IN ) :: IOPT, NPTS
205 INTEGER, INTENT( OUT) :: NRET
206 !
207 REAL, INTENT(IN ) :: FILL
208 REAL, INTENT(INOUT) :: RLON(NPTS),RLAT(NPTS)
209 REAL, INTENT(INOUT) :: XPTS(NPTS),YPTS(NPTS)
210 REAL, OPTIONAL, INTENT( OUT) :: CROT(NPTS),SROT(NPTS)
211 REAL, OPTIONAL, INTENT( OUT) :: XLON(NPTS),XLAT(NPTS)
212 REAL, OPTIONAL, INTENT( OUT) :: YLON(NPTS),YLAT(NPTS),AREA(NPTS)
213 !
214 INTEGER :: JSCAN, IM, JM
215 INTEGER :: J, JA, JG
216 INTEGER :: N
217 !
218 LOGICAL :: LROT, LMAP, LAREA
219 !
220 REAL, ALLOCATABLE :: ALAT(:), ALAT_JSCAN(:)
221 REAL, ALLOCATABLE :: ALAT_TEMP(:),BLAT_TEMP(:)
222 REAL :: HI, RLATA, RLATB, RLAT1, RLON1, RLON2
223 REAL :: XMAX, XMIN, YMAX, YMIN, YPTSA, YPTSB
224 REAL :: WB
225
226 IF(PRESENT(crot)) crot=fill
227 IF(PRESENT(srot)) srot=fill
228 IF(PRESENT(xlon)) xlon=fill
229 IF(PRESENT(xlat)) xlat=fill
230 IF(PRESENT(ylon)) ylon=fill
231 IF(PRESENT(ylat)) ylat=fill
232 IF(PRESENT(area)) area=fill
233
234 IF(PRESENT(crot).AND.PRESENT(srot))THEN
235 lrot=.true.
236 ELSE
237 lrot=.false.
238 ENDIF
239 IF(PRESENT(xlon).AND.PRESENT(xlat).AND.PRESENT(ylon).AND.PRESENT(ylat))THEN
240 lmap=.true.
241 ELSE
242 lmap=.false.
243 ENDIF
244 IF(PRESENT(area))THEN
245 larea=.true.
246 ELSE
247 larea=.false.
248 ENDIF
249
250 im=self%im
251 jm=self%jm
252
253 rlat1=self%rlat1
254 rlon1=self%rlon1
255 rlon2=self%rlon2
256
257 jg=self%jg
258 jscan=self%jscan
259 hi=self%hi
260
261 jh=self%jh
262 dlon=self%dlon
263 rerth = self%rerth
264
265 ALLOCATE(alat_temp(jg))
266 ALLOCATE(blat_temp(jg))
267 CALL splat(4,jg,alat_temp,blat_temp)
268 ALLOCATE(alat(0:jg+1))
269 ALLOCATE(blat(0:jg+1))
270 !$OMP PARALLEL DO PRIVATE(JA) SCHEDULE(STATIC)
271 DO ja=1,jg
272 alat(ja)=real(dpr*asin(alat_temp(ja)))
273 blat(ja)=blat_temp(ja)
274 ENDDO
275 !$OMP END PARALLEL DO
276 DEALLOCATE(alat_temp,blat_temp)
277 alat(0)=180.-alat(1)
278 alat(jg+1)=-alat(0)
279 blat(0)=-blat(1)
280 blat(jg+1)=blat(0)
281 j1=1
282 DO WHILE(j1.LT.jg.AND.rlat1.LT.(alat(j1)+alat(j1+1))/2)
283 j1=j1+1
284 ENDDO
285 IF(lmap)THEN
286 ALLOCATE(alat_jscan(jg))
287 DO ja=1,jg
288 alat_jscan(j1+jh*(ja-1))=alat(ja)
289 ENDDO
290 ALLOCATE(ylat_row(0:jg+1))
291 DO ja=2,(jg-1)
292 ylat_row(ja)=2.0/(alat_jscan(ja+1)-alat_jscan(ja-1))
293 ENDDO
294 ylat_row(1)=1.0/(alat_jscan(2)-alat_jscan(1))
295 ylat_row(0)=ylat_row(1)
296 ylat_row(jg)=1.0/(alat_jscan(jg)-alat_jscan(jg-1))
297 ylat_row(jg+1)=ylat_row(jg)
298 DEALLOCATE(alat_jscan)
299 ENDIF
300 xmin=0
301 xmax=im+1
302 IF(im.EQ.nint(360/abs(dlon))) xmax=im+2
303 ymin=0.5
304 ymax=jm+0.5
305 nret=0
306
307 ! TRANSLATE GRID COORDINATES TO EARTH COORDINATES
308 IF(iopt.EQ.0.OR.iopt.EQ.1) THEN
309 !$OMP PARALLEL DO PRIVATE(N,J,WB,RLATA,RLATB) REDUCTION(+:NRET) SCHEDULE(STATIC)
310 DO n=1,npts
311 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
312 ypts(n).GE.ymin.AND.ypts(n).LE.ymax) THEN
313 rlon(n)=mod(rlon1+dlon*(xpts(n)-1)+3600,360.)
314 j=int(ypts(n))
315 wb=ypts(n)-j
316 rlata=alat(j1+jh*(j-1))
317 rlatb=alat(j1+jh*j)
318 rlat(n)=rlata+wb*(rlatb-rlata)
319 nret=nret+1
320 IF(lrot) CALL gaussian_vect_rot(crot(n),srot(n))
321 IF(lmap) CALL gaussian_map_jacob(ypts(n),&
322 xlon(n),xlat(n),ylon(n),ylat(n))
323 IF(larea) CALL gaussian_grid_area(ypts(n),area(n))
324 ELSE
325 rlon(n)=fill
326 rlat(n)=fill
327 ENDIF
328 ENDDO
329 !$OMP END PARALLEL DO
330
331 ! TRANSLATE EARTH COORDINATES TO GRID COORDINATES
332 ELSEIF(iopt.EQ.-1) THEN
333 !$OMP PARALLEL DO PRIVATE(N,JA,YPTSA, YPTSB, WB) REDUCTION(+:NRET) SCHEDULE(STATIC)
334 DO n=1,npts
335 xpts(n)=fill
336 ypts(n)=fill
337 IF(abs(rlon(n)).LE.360.AND.abs(rlat(n)).LE.90) THEN
338 xpts(n)=1+hi*mod(hi*(rlon(n)-rlon1)+3600,360.)/dlon
339 ja=min(int((jg+1)/180.*(90-rlat(n))),jg)
340 IF(rlat(n).GT.alat(ja)) ja=max(ja-2,0)
341 IF(rlat(n).LT.alat(ja+1)) ja=min(ja+2,jg)
342 IF(rlat(n).GT.alat(ja)) ja=ja-1
343 IF(rlat(n).LT.alat(ja+1)) ja=ja+1
344 yptsa=1+jh*(ja-j1)
345 yptsb=1+jh*(ja+1-j1)
346 wb=(alat(ja)-rlat(n))/(alat(ja)-alat(ja+1))
347 ypts(n)=yptsa+wb*(yptsb-yptsa)
348 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
349 ypts(n).GE.ymin.AND.ypts(n).LE.ymax) THEN
350 nret=nret+1
351 IF(lrot) CALL gaussian_vect_rot(crot(n),srot(n))
352 IF(lmap) CALL gaussian_map_jacob(ypts(n), &
353 xlon(n),xlat(n),ylon(n),ylat(n))
354 IF(larea) CALL gaussian_grid_area(ypts(n),area(n))
355 ELSE
356 xpts(n)=fill
357 ypts(n)=fill
358 ENDIF
359 ENDIF
360 ENDDO
361 !$OMP END PARALLEL DO
362 ENDIF
363 DEALLOCATE(alat, blat)
364 IF (ALLOCATED(ylat_row)) DEALLOCATE(ylat_row)
365
366 END SUBROUTINE gdswzd_gaussian
367
380 SUBROUTINE gaussian_vect_rot(CROT,SROT)
381 IMPLICIT NONE
382
383 REAL, INTENT( OUT) :: CROT, SROT
384
385 crot=1.0
386 srot=0.0
387
388 END SUBROUTINE gaussian_vect_rot
389
400 SUBROUTINE gaussian_map_jacob(YPTS, XLON, XLAT, YLON, YLAT)
401 IMPLICIT NONE
402
403 REAL, INTENT(IN ) :: YPTS
404 REAL, INTENT( OUT) :: XLON, XLAT, YLON, YLAT
405
406 xlon=1/dlon
407 xlat=0.
408 ylon=0.
409 ylat=ylat_row(nint(ypts))
410
411 END SUBROUTINE gaussian_map_jacob
412
420 SUBROUTINE gaussian_grid_area(YPTS,AREA)
421 IMPLICIT NONE
422
423 REAL, INTENT(IN ) :: YPTS
424 REAL, INTENT( OUT) :: AREA
425
426 INTEGER :: J
427
428 REAL :: WB, WLAT, WLATA, WLATB
429
430 j = int(ypts)
431 wb=ypts-j
432 wlata=blat(j1+jh*(j-1))
433 wlatb=blat(j1+jh*j)
434 wlat=wlata+wb*(wlatb-wlata)
435 area=real(rerth**2*wlat*dlon/dpr)
436
437 END SUBROUTINE gaussian_grid_area
438end module ip_gaussian_grid_mod
439
void gdswzd(int igdtnum, int *igdtmpl, int igdtlen, int iopt, int npts, float fill, float *xpts, float *ypts, float *rlon, float *rlat, int *nret, float *crot, float *srot, float *xlon, float *xlat, float *ylon, float *ylat, float *area)
gdswzd() interface for C for _4 build of library.
Determine earth radius and shape.
Module containing common constants.
Gaussian grid coordinate transformations.
subroutine gdswzd_gaussian(self, iopt, npts, fill, xpts, ypts, rlon, rlat, nret, crot, srot, xlon, xlat, ylon, ylat, area)
Calculates Earth coordinates (iopt = 1) or grid coorindates (iopt = -1) for Gaussian grids.
real, dimension(:), allocatable ylat_row
dy/dlat for each row in 1/degrees.
subroutine gaussian_grid_area(ypts, area)
Computes the grid box area for a gaussian cylindrical grid.
integer jh
Scan mode flag in 'j' direction.
subroutine gaussian_map_jacob(ypts, xlon, xlat, ylon, ylat)
Computes the map jacobians for a gaussian cylindrical grid.
real rerth
Radius of the earth.
real dlon
"i"-direction increment.
subroutine init_grib1(self, g1_desc)
Initializes a gaussian grid given a grib1_descriptor object.
subroutine gaussian_vect_rot(crot, srot)
Computes the vector rotation sines and cosines for a gaussian cylindrical grid.
subroutine init_grib2(self, g2_desc)
Initializes a gaussian grid given a grib2_descriptor object.
real, dimension(:), allocatable blat
Gaussian latitude for each parallel.
integer j1
'j' index of first grid point within the global array of latitudes.
Users derived type grid descriptor objects to abstract away the raw GRIB1 and GRIB2 grid definitions.
Abstract ip_grid type.
subroutine splat(idrt, jmax, slat, wlat)
Computes cosines of colatitude and Gaussian weights for one of the following specific global sets of ...
Definition splat.F:46
Descriptor representing a grib1 grib descriptor section (GDS) with an integer array.
Abstract grid that holds fields and methods common to all grids.