NCEPLIBS-ip 5.2.0
Loading...
Searching...
No Matches
ip_equid_cylind_grid_mod.F90
Go to the documentation of this file.
1
7
19 use ip_grid_mod
21 implicit none
22
23 private
24 public :: ip_equid_cylind_grid
25
26 type, extends(ip_grid) :: ip_equid_cylind_grid
27 real :: hi
28 real :: rlat1
29 real :: rlon1
30 real :: rlat2
31 real :: rlon2
32 real :: dlat
33 real :: dlon
34 contains
36 procedure :: init_grib1
38 procedure :: init_grib2
42
43 REAL :: dlat
44 REAL :: dlon
45 REAL :: rerth
46
47contains
48
56 subroutine init_grib1(self, g1_desc)
57 class(ip_equid_cylind_grid), intent(inout) :: self
58 type(grib1_descriptor), intent(in) :: g1_desc
59
60 integer :: iscan
61
62 associate(kgds => g1_desc%gds)
63 self%IM=kgds(2)
64 self%JM=kgds(3)
65 self%RLAT1=kgds(4)*1.e-3
66 self%RLON1=kgds(5)*1.e-3
67 self%RLAT2=kgds(7)*1.e-3
68 self%RLON2=kgds(8)*1.e-3
69 iscan=mod(kgds(11)/128,2)
70 self%HI=(-1.)**iscan
71 self%DLON=self%HI*(mod(self%HI*(self%RLON2-self%RLON1)-1+3600,360.)+1)/(self%IM-1)
72 self%DLAT=(self%RLAT2-self%RLAT1)/(self%JM-1)
73
74 ! defaults
75 self%iwrap = 0
76 self%jwrap1 = 0
77 self%jwrap2 = 0
78 self%nscan = mod(kgds(11) / 32, 2)
79 self%nscan_field_pos = self%nscan
80 self%kscan = 0
81
82 self%iwrap = nint(360/abs(self%dlon))
83
84 if(self%im < self%iwrap) self%iwrap=0
85 self%jwrap1 = 0
86 self%jwrap2 = 0
87 if(self%iwrap > 0 .and. mod(self%iwrap,2) == 0) then
88 if(abs(self%rlat1) > 90-0.25*self%dlat) then
89 self%jwrap1 = 2
90 elseif(abs(self%rlat1) > 90-0.75*self%dlat) then
91 self%jwrap1 = 1
92 endif
93 if(abs(self%rlat2) > 90-0.25*self%dlat) then
94 self%jwrap2 = 2 * self%jm
95 elseif(abs(self%rlat2) > 90-0.75*self%dlat) then
96 self%jwrap2 = 2 * self%jm+1
97 endif
98 endif
99
100 self%rerth = 6.3712e6
101 self%eccen_squared = 0.0
102 end associate
103
104 end subroutine init_grib1
105
112 subroutine init_grib2(self, g2_desc)
113 class(ip_equid_cylind_grid), intent(inout) :: self
114 type(grib2_descriptor), intent(in) :: g2_desc
115
116 integer :: iscale, iscan
117
118 associate(igdtmpl => g2_desc%gdt_tmpl, igdtlen => g2_desc%gdt_len)
119 self%IM=igdtmpl(8)
120 self%JM=igdtmpl(9)
121 iscale=igdtmpl(10)*igdtmpl(11)
122 IF(iscale==0) iscale=10**6
123 self%RLAT1=float(igdtmpl(12))/float(iscale)
124 self%RLON1=float(igdtmpl(13))/float(iscale)
125 self%RLAT2=float(igdtmpl(15))/float(iscale)
126 self%RLON2=float(igdtmpl(16))/float(iscale)
127 iscan=mod(igdtmpl(19)/128,2)
128 self%HI=(-1.)**iscan
129 self%DLON=self%HI*(mod(self%HI*(self%RLON2-self%RLON1)-1+3600,360.)+1)/(self%IM-1)
130 self%DLAT=(self%RLAT2-self%RLAT1)/(self%JM-1)
131
132 self%nscan = mod(igdtmpl(19)/32,2)
133 self%nscan_field_pos = self%nscan
134 self%kscan = 0
135 self%iwrap = nint(360/abs(self%DLON))
136
137 if(self%im.lt.self%iwrap) self%iwrap=0
138 self%jwrap1=0
139 self%jwrap2=0
140
141 if(self%im < self%iwrap) self%iwrap=0
142 self%jwrap1 = 0
143 self%jwrap2 = 0
144 if(self%iwrap > 0 .and. mod(self%iwrap,2) == 0) then
145 if(abs(self%rlat1) > 90-0.25*self%dlat) then
146 self%jwrap1 = 2
147 elseif(abs(self%rlat1) > 90-0.75*self%dlat) then
148 self%jwrap1 = 1
149 endif
150 if(abs(self%rlat2) > 90-0.25*self%dlat) then
151 self%jwrap2 = 2 * self%jm
152 elseif(abs(self%rlat2) > 90-0.75*self%dlat) then
153 self%jwrap2 = 2 * self%jm+1
154 endif
155 endif
156
157 call earth_radius(igdtmpl, igdtlen, self%rerth, self%eccen_squared)
158
159 end associate
160 end subroutine init_grib2
161
206 SUBROUTINE gdswzd_equid_cylind(self,IOPT,NPTS,FILL, &
207 XPTS,YPTS,RLON,RLAT,NRET, &
208 CROT,SROT,XLON,XLAT,YLON,YLAT,AREA)
209 IMPLICIT NONE
210 !
211 class(ip_equid_cylind_grid), intent(in) :: self
212 INTEGER, INTENT(IN ) :: IOPT, NPTS
213 INTEGER, INTENT( OUT) :: NRET
214 !
215 REAL, INTENT(IN ) :: FILL
216 REAL, INTENT(INOUT) :: RLON(NPTS),RLAT(NPTS)
217 REAL, INTENT(INOUT) :: XPTS(NPTS),YPTS(NPTS)
218 REAL, OPTIONAL, INTENT( OUT) :: CROT(NPTS),SROT(NPTS)
219 REAL, OPTIONAL, INTENT( OUT) :: XLON(NPTS),XLAT(NPTS)
220 REAL, OPTIONAL, INTENT( OUT) :: YLON(NPTS),YLAT(NPTS),AREA(NPTS)
221 !
222 INTEGER :: IM, JM, N
223 !
224 LOGICAL :: LROT, LMAP, LAREA
225 !
226 REAL :: HI, RLAT1, RLON1, RLAT2, RLON2
227 REAL :: XMAX, XMIN, YMAX, YMIN
228 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
229 IF(PRESENT(crot)) crot=fill
230 IF(PRESENT(srot)) srot=fill
231 IF(PRESENT(xlon)) xlon=fill
232 IF(PRESENT(xlat)) xlat=fill
233 IF(PRESENT(ylon)) ylon=fill
234 IF(PRESENT(ylat)) ylat=fill
235 IF(PRESENT(area)) area=fill
236
237 im=self%im
238 jm=self%jm
239
240 rlat1=self%rlat1
241 rlon1=self%rlon1
242 rlat2=self%rlat2
243 rlon2=self%rlon2
244
245 hi=self%hi
246
247 rerth = self%rerth
248 dlat = self%dlat
249 dlon = self%dlon
250
251 xmin=0
252 xmax=im+1
253 IF(im.EQ.nint(360/abs(dlon))) xmax=im+2
254 ymin=0
255 ymax=jm+1
256 nret=0
257 IF(PRESENT(crot).AND.PRESENT(srot))THEN
258 lrot=.true.
259 ELSE
260 lrot=.false.
261 ENDIF
262 IF(PRESENT(xlon).AND.PRESENT(xlat).AND.PRESENT(ylon).AND.PRESENT(ylat))THEN
263 lmap=.true.
264 ELSE
265 lmap=.false.
266 ENDIF
267 IF(PRESENT(area))THEN
268 larea=.true.
269 ELSE
270 larea=.false.
271 ENDIF
272 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
273 ! TRANSLATE GRID COORDINATES TO EARTH COORDINATES
274 IF(iopt.EQ.0.OR.iopt.EQ.1) THEN
275 !$OMP PARALLEL DO PRIVATE(N) REDUCTION(+:NRET) SCHEDULE(STATIC)
276 DO n=1,npts
277 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
278 ypts(n).GE.ymin.AND.ypts(n).LE.ymax) THEN
279 rlon(n)=mod(rlon1+dlon*(xpts(n)-1)+3600,360.)
280 rlat(n)=min(max(rlat1+dlat*(ypts(n)-1),-90.),90.)
281 nret=nret+1
282 IF(lrot) CALL equid_cylind_vect_rot(crot(n),srot(n))
283 IF(lmap) CALL equid_cylind_map_jacob(xlon(n),xlat(n),ylon(n),ylat(n))
284 IF(larea) CALL equid_cylind_grid_area(rlat(n),area(n))
285 ELSE
286 rlon(n)=fill
287 rlat(n)=fill
288 ENDIF
289 ENDDO
290 !$OMP END PARALLEL DO
291 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
292 ! TRANSLATE EARTH COORDINATES TO GRID COORDINATES
293 ELSEIF(iopt.EQ.-1) THEN
294 !$OMP PARALLEL DO PRIVATE(N) REDUCTION(+:NRET) SCHEDULE(STATIC)
295 DO n=1,npts
296 IF(abs(rlon(n)).LE.360.AND.abs(rlat(n)).LE.90) THEN
297 xpts(n)=1+hi*mod(hi*(rlon(n)-rlon1)+3600,360.)/dlon
298 ypts(n)=1+(rlat(n)-rlat1)/dlat
299 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
300 ypts(n).GE.ymin.AND.ypts(n).LE.ymax) THEN
301 nret=nret+1
302 IF(lrot) CALL equid_cylind_vect_rot(crot(n),srot(n))
303 IF(lmap) CALL equid_cylind_map_jacob(xlon(n),xlat(n),ylon(n),ylat(n))
304 IF(larea) CALL equid_cylind_grid_area(rlat(n),area(n))
305 ELSE
306 xpts(n)=fill
307 ypts(n)=fill
308 ENDIF
309 ELSE
310 xpts(n)=fill
311 ypts(n)=fill
312 ENDIF
313 ENDDO
314 !$OMP END PARALLEL DO
315 ENDIF
316 END SUBROUTINE gdswzd_equid_cylind
317
330 SUBROUTINE equid_cylind_vect_rot(CROT,SROT)
331 IMPLICIT NONE
332
333 REAL, INTENT( OUT) :: CROT, SROT
334
335 crot=1.0
336 srot=0.0
337
338 END SUBROUTINE equid_cylind_vect_rot
339
349 SUBROUTINE equid_cylind_map_jacob(XLON,XLAT,YLON,YLAT)
350 REAL, INTENT( OUT) :: XLON,XLAT,YLON,YLAT
351
352 xlon=1.0/dlon
353 xlat=0.
354 ylon=0.
355 ylat=1.0/dlat
356
357 END SUBROUTINE equid_cylind_map_jacob
358
366 SUBROUTINE equid_cylind_grid_area(RLAT,AREA)
367 IMPLICIT NONE
368
369 REAL, INTENT(IN ) :: RLAT
370 REAL, INTENT( OUT) :: AREA
371
372 REAL, PARAMETER :: PI=3.14159265358979
373 REAL, PARAMETER :: DPR=180./pi
374
375 REAL :: DSLAT, RLATU, RLATD
376
377 rlatu=min(max(rlat+dlat/2,-90.),90.)
378 rlatd=min(max(rlat-dlat/2,-90.),90.)
379 dslat=sin(rlatu/dpr)-sin(rlatd/dpr)
380 area=rerth**2*abs(dslat*dlon)/dpr
381
382 END SUBROUTINE equid_cylind_grid_area
383
385
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.
Equidistant cylindrical grib decoder and grid coordinate transformations.
real dlat
Grid resolution in degrees n/s direction.
subroutine init_grib2(self, g2_desc)
Initializes an equidistant cylindrical grid given a grib2_descriptor object.
subroutine init_grib1(self, g1_desc)
Initializes an equidistant cylindrical grid given a grib1_descriptor object.
real dlon
Grid resolution in degrees e/w direction.
subroutine equid_cylind_map_jacob(xlon, xlat, ylon, ylat)
Computes the map jacobians for a equidistant cylindrical grid.
subroutine equid_cylind_grid_area(rlat, area)
Computes the grid box area for a equidistant cylindrical grid.
subroutine gdswzd_equid_cylind(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 equidistant cylindrical g...
subroutine equid_cylind_vect_rot(crot, srot)
Computes the vector rotation sines and cosines for a equidistant cylindrical grid.
Users derived type grid descriptor objects to abstract away the raw GRIB1 and GRIB2 grid definitions.
Abstract ip_grid type.
Descriptor representing a grib1 grib descriptor section (GDS) with an integer array.
Abstract grid that holds fields and methods common to all grids.