NCEPLIBS-ip 4.0.0
ipxwafs3.f90
1 SUBROUTINE ipxwafs3(IDIR, NUMPTS_THIN, NUMPTS_FULL, KM, NUM_OPT, OPT_PTS, &
2 IGDTLEN, IGDTMPL_THIN, DATA_THIN, IB_THIN, BITMAP_THIN, &
3 IGDTMPL_FULL, DATA_FULL, IB_FULL, BITMAP_FULL, IRET)
4!$$$ SUBPROGRAM DOCUMENTATION BLOCK
5!
6! SUBPROGRAM: IPXWAFS3 EXPAND OR CONTRACT WAFS GRIDS
7! PRGMMR: IREDELL ORG: W/NMC23 DATE: 96-04-10
8!
9! ABSTRACT: THIS SUBPROGRAM TRANSFORMS BETWEEN THE THINNED WAFS GRIDS
10! USED FOR TRANSMITTING TO THE AVIATION COMMUNITY
11! AND THEIR FULL EXPANSION AS USED FOR GENERAL INTERPOLATION
12! AND GRAPHICS. THE THINNED WAFS GRIDS ARE LATITUDE-LONGITUDE
13! GRIDS WHERE THE NUMBER OF POINTS IN EACH ROW DECREASE
14! TOWARD THE POLE. THIS INFORMATION IS STORED
15! IN THE GRIB 2 GRID DEFINITION TEMPLATE (SECTION 3)
16! STARTING AT OCTET 73. THE FULL GRID COUNTERPARTS
17! HAVE AN EQUAL NUMBER OF POINTS PER ROW.
18! THE TRANSFORM BETWEEN THE FULL AND THINNED WAFS
19! GRID IS DONE BY NEAREST NEIGHBOR AND IS
20! NOT REVERSIBLE. THIS ROUTINE WORKS WITH
21! BITMAPPED DATA.
22!
23! PROGRAM HISTORY LOG:
24! 07-07-13 TROJAN - INITIAL VERSION BASED ON IPXWAFS2
25! 2015-JUL GAYNO - CONVERT TO GRIB 2
26!
27! USAGE: CALL IPXWAFS3(IDIR, NUMPTS_THIN, NUMPTS_FULL, KM, NUM_OPT, OPT_PTS, &
28! IGDTLEN, IGDTMPL_THIN, DATA_THIN, IB_THIN, BITMAP_THIN, &
29! IGDTMPL_FULL, DATA_FULL, IB_FULL, BITMAP_FULL, IRET)
30!
31! INPUT ARGUMENT LIST:
32! IDIR - INTEGER TRANSFORM OPTION
33! (+1 TO EXPAND THINNED FIELDS TO FULL FIELDS)
34! (-1 TO CONTRACT FULL FIELDS TO THINNED FIELDS)
35! NUMPTS_THIN - INTEGER NUMBER OF GRID POINTS - THINNED GRID. MUST BE
36! 3447.
37! NUMPTS_FULL - INTEGER NUMBER OF GRID POINTS - FULL GRID. MUST
38! BE 5329.
39! KM - INTEGER NUMBER OF FIELDS TO TRANSFORM
40! NUM_OPT - INTEGER NUMBER OF VALUES TO DESCRIBE THE THINNED
41! GRID. MUST BE 73. DIMENSION OF ARRAY OPT_PTS.
42! OPT_PTS - INTEGER (NUM_OPT) NUMBER OF GRID POINTS PER ROW -
43! THINNED GRID - IF IDIR=+1
44! IGDTLEN - INTEGER GRID DEFINTION TEMPLATE ARRAY LENGTH. MUST BE
45! 19 FOR LAT/LON GRIDS. CORRESPONDS TO THE GFLD%IGDTLEN
46! COMPONENT OF THE NCEP G2 LIBRARY GRIDMOD DATA STRUCTURE.
47! SAME FOR THIN AND FULL GRIDS WHICH ARE BOTH LAT/LON.
48! IGDTMPL_THIN - INTEGER (IGDTLEN) GRID DEFINITION TEMPLATE ARRAY -
49! THINNED GRID - IF IDIR=+1. CORRESPONDS TO THE
50! GFLD%IGDTMPL COMPONENT OF THE NCEP G2 LIBRARY
51! GRIDMOD DATA STRUCTURE (SECTION 3 INFO):
52! (1): SHAPE OF EARTH, OCTET 15
53! (2): SCALE FACTOR OF SPHERICAL EARTH RADIUS,
54! OCTET 16
55! (3): SCALED VALUE OF RADIUS OF SPHERICAL EARTH,
56! OCTETS 17-20
57! (4): SCALE FACTOR OF MAJOR AXIS OF ELLIPTICAL EARTH,
58! OCTET 21
59! (5): SCALED VALUE OF MAJOR AXIS OF ELLIPTICAL EARTH,
60! OCTETS 22-25
61! (6): SCALE FACTOR OF MINOR AXIS OF ELLIPTICAL EARTH,
62! OCTET 26
63! (7): SCALED VALUE OF MINOR AXIS OF ELLIPTICAL EARTH,
64! OCTETS 27-30
65! (8): SET TO MISSING FOR THINNED GRID., OCTS 31-34
66! (9): NUMBER OF POINTS ALONG A MERIDIAN, OCTS 35-38
67! (10): BASIC ANGLE OF INITIAL PRODUCTION DOMAIN,
68! OCTETS 39-42.
69! (11): SUBDIVISIONS OF BASIC ANGLE, OCTETS 43-46
70! (12): LATITUDE OF FIRST GRID POINT, OCTETS 47-50
71! (13): LONGITUDE OF FIRST GRID POINT, OCTETS 51-54
72! (14): RESOLUTION AND COMPONENT FLAGS, OCTET 55
73! (15): LATITUDE OF LAST GRID POINT, OCTETS 56-59
74! (16): LONGITUDE OF LAST GRID POINT, OCTETS 60-63
75! (17): SET TO MISSING FOR THINNED GRID, OCTETS 64-67
76! (18): J-DIRECTION INCREMENT, OCTETS 68-71
77! (19): SCANNING MODE, OCTET 72
78! DATA_THIN - REAL (NUMPTS_THIN,KM) THINNED GRID FIELDS IF IDIR=+1
79! IB_THIN - INTEGER (KM) BITMAP FLAGS THINNED GRID - IF IDIR=+1
80! BITMAP_THIN - LOGICAL (NUMPTS_THIN,KM) BITMAP FIELDS THIN GRID - IF IDIR=+1
81! IGDTMPL_FULL - INTEGER (IGDTLEN) GRID DEFINITION TEMPLATE ARRAY -
82! FULL GRID - IF IDIR=-1. CORRESPONDS TO THE
83! GFLD%IGDTMPL COMPONENT OF THE NCEP G2 LIBRARY
84! GRIDMOD DATA STRUCTURE. SAME AS IGDTMPL_THIN
85! EXCEPT:
86! (8): NUMBER OF POINTS ALONG A PARALLEL, OCTS 31-34
87! (17): I-DIRECTION INCREMENT, OCTETS 64-67
88! DATA_FULL - REAL (NUMPTS_FULL,KM) FULL GRID FIELDS IF IDIR=-1
89! IB_FULL - INTEGER (KM) BITMAP FLAGS FULL GRID - IF IDIR=-1
90! BITMAP_FULL - LOGICAL (NUMPTS_FULL,KM) BITMAP FIELDS FULL GRID - IF IDIR=-1
91!
92! OUTPUT ARGUMENT LIST:
93! OPT_PTS - INTEGER (NUM_OPT) NUMBER OF GRID POINTS PER ROW -
94! THINNED GRID - IF IDIR=-1
95! IGDTMPL_THIN - INTEGER (IGDTLEN) GRID DEFINITION TEMPLATE ARRAY -
96! THINNED GRID - IF IDIR=-1. CORRESPONDS TO THE
97! GFLD%IGDTMPL COMPONENT OF THE NCEP G2 LIBRARY
98! GRIDMOD DATA STRUCTURE. DEFINED ABOVE.
99! DATA_THIN - REAL (NUMPTS_THIN,KM) THINNED GRID FIELDS IF IDIR=-1
100! IB_THIN - INTEGER (KM) BITMAP FLAGS THINNED GRID - IF IDIR=-1
101! BITMAP_THIN - LOGICAL (NUMPTS_THIN,KM) BITMAP FIELDS THIN GRID - IF IDIR=-1
102! IGDTMPL_FULL - INTEGER (IGDTLEN) GRID DEFINITION TEMPLATE ARRAY -
103! FULL GRID - IF IDIR=+1. CORRESPONDS TO THE
104! GFLD%IGDTMPL COMPONENT OF THE NCEP G2 LIBRARY
105! GRIDMOD DATA STRUCTURE. DEFINED ABOVE.
106! DATA_FULL - REAL (NUMPTS_FULL,KM) FULL GRID FIELDS IF IDIR=+1
107! IB_FULL - INTEGER (KM) BITMAP FLAGS FULL GRID - IF IDIR=+1
108! BITMAP_FULL - LOGICAL (NUMPTS_FULL,KM) BITMAP FIELDS FULL GRID - IF IDIR=+1
109! IRET - INTEGER RETURN CODE
110! 0 SUCCESSFUL TRANSFORMATION
111! 1 IMPROPER GRID SPECIFICATION
112!
113! ATTRIBUTES:
114! LANGUAGE: FORTRAN 90
115!
116!$$$
117 IMPLICIT NONE
118!
119 INTEGER, INTENT(IN ) :: NUM_OPT
120 INTEGER, INTENT(INOUT) :: OPT_PTS(NUM_OPT)
121 INTEGER, INTENT(IN ) :: IDIR, KM, NUMPTS_THIN, NUMPTS_FULL
122 INTEGER, INTENT(IN ) :: IGDTLEN
123 INTEGER, INTENT(INOUT) :: IGDTMPL_THIN(IGDTLEN)
124 INTEGER, INTENT(INOUT) :: IGDTMPL_FULL(IGDTLEN)
125 INTEGER, INTENT(INOUT) :: IB_THIN(KM), IB_FULL(KM)
126 INTEGER, INTENT( OUT) :: IRET
127!
128 LOGICAL(KIND=1), INTENT(INOUT) :: BITMAP_THIN(NUMPTS_THIN,KM)
129 LOGICAL(KIND=1), INTENT(INOUT) :: BITMAP_FULL(NUMPTS_FULL,KM)
130!
131 REAL, INTENT(INOUT) :: DATA_THIN(NUMPTS_THIN,KM)
132 REAL, INTENT(INOUT) :: DATA_FULL(NUMPTS_FULL,KM)
133!
134 INTEGER, PARAMETER :: MISSING=-1
135!
136 INTEGER :: SCAN_MODE, I, J, K, IDLAT, IDLON
137 INTEGER :: IA, IB, IM, IM1, IM2, NPWAFS(73)
138 INTEGER :: IS1, IS2, ISCAN, ISCALE
139!
140 LOGICAL :: TEST1, TEST2
141!
142 REAL :: DLON, HI
143 REAL :: RAT1, RAT2, RLON1, RLON2
144 REAL :: WA, WB, X1, X2
145!
146 DATA npwafs/ &
147 73, 73, 73, 73, 73, 73, 73, 73, 72, 72, 72, 71, 71, 71, 70,&
148 70, 69, 69, 68, 67, 67, 66, 65, 65, 64, 63, 62, 61, 60, 60,&
149 59, 58, 57, 56, 55, 54, 52, 51, 50, 49, 48, 47, 45, 44, 43,&
150 42, 40, 39, 38, 36, 35, 33, 32, 30, 29, 28, 26, 25, 23, 22,&
151 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2/
152! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
153! TRANSFORM GDS
154 iret=0
155! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
156! REG LAT/LON GRIDS HAVE 19 GDT ELEMENTS.
157 IF (igdtlen /= 19 .OR. numpts_thin/=3447 .OR. numpts_full/=5329) THEN
158 iret=1
159 RETURN
160 ENDIF
161! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
162! EXPAND THINNED GDS TO FULL GDS
163 IF(idir.GT.0) THEN
164 scan_mode=igdtmpl_thin(19)
165 iscale=igdtmpl_thin(10)*igdtmpl_thin(11)
166 IF(iscale==0) iscale=10**6
167 idlat=nint(1.25*float(iscale))
168 test1=all(opt_pts==npwafs)
169 test2=all(opt_pts==npwafs(73:1:-1))
170! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
171! SOME CHECKS TO ENSURE THIS IS A WAFS GRID
172 IF(scan_mode==64 .AND. igdtmpl_thin(9)==73 .AND. &
173 idlat==igdtmpl_thin(18) .AND. (test1 .OR. test2) ) THEN
174 igdtmpl_full=igdtmpl_thin
175 im=73
176 igdtmpl_full(8)=im
177 rlon1=float(igdtmpl_full(13))/float(iscale)
178 rlon2=float(igdtmpl_full(16))/float(iscale)
179 iscan=mod(igdtmpl_full(19)/128,2)
180 hi=(-1.)**iscan
181 dlon=hi*(mod(hi*(rlon2-rlon1)-1+3600,360.)+1)/(im-1)
182 igdtmpl_full(17)=nint(dlon*float(iscale))
183 ELSE
184 iret=1
185 ENDIF
186! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
187! CONTRACT FULL GDS TO THINNED GDS
188 ELSEIF(idir.LT.0) THEN
189 scan_mode=igdtmpl_full(19)
190 iscale=igdtmpl_full(10)*igdtmpl_full(11)
191 IF(iscale==0) iscale=10**6
192 idlat=nint(1.25*float(iscale))
193 idlon=idlat
194! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
195! SOME CHECKS TO ENSURE THIS IS A WAFS GRID
196 IF(scan_mode==64 .AND. igdtmpl_full(8)==73 .AND. igdtmpl_full(9)==73 .AND. &
197 num_opt==73 .AND. idlat==igdtmpl_full(18) .AND. idlon==igdtmpl_full(17))THEN
198 igdtmpl_thin=igdtmpl_full
199 igdtmpl_thin(8)=missing
200 igdtmpl_thin(17)=missing
201 IF(igdtmpl_thin(12)==0) THEN ! IS LATITUDE OF ROW 1 THE EQUATOR?
202 opt_pts=npwafs
203 ELSE
204 opt_pts=npwafs(73:1:-1)
205 ENDIF
206 ELSE
207 iret=1
208 ENDIF
209 ENDIF
210! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
211! TRANSFORM FIELDS
212 IF(iret.EQ.0) THEN
213! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
214! EXPAND THINNED FIELDS TO FULL FIELDS
215 IF(idir.EQ.1) THEN
216 DO k=1,km
217 is1=0
218 is2=0
219 ib_full(k)=0
220 DO j=1,igdtmpl_full(9)
221 im1=opt_pts(j)
222 im2=igdtmpl_full(8)
223 rat1=float(im1-1)/float(im2-1)
224 DO i=1,im2
225 x1=(i-1)*rat1+1
226 ia=x1
227 ia=min(max(ia,1),im1-1)
228 ib=ia+1
229 wa=ib-x1
230 wb=x1-ia
231 IF(wa.GE.wb) THEN
232 IF(ib_thin(k).EQ.0.OR.bitmap_thin(is1+ia,k)) THEN
233 data_full(is2+i,k)=data_thin(is1+ia,k)
234 bitmap_full(is2+i,k)=.true.
235 ELSE
236 data_full(is2+i,k)=0.0
237 bitmap_full(is2+i,k)=.false.
238 ib_full(k)=1
239 ENDIF
240 ELSE
241 IF(ib_thin(k).EQ.0.OR.bitmap_thin(is1+ib,k)) THEN
242 data_full(is2+i,k)=data_thin(is1+ib,k)
243 bitmap_full(is2+i,k)=.true.
244 ELSE
245 data_full(is2+i,k)=0.0
246 bitmap_full(is2+i,k)=.false.
247 ib_full(k)=1
248 ENDIF
249 ENDIF
250 ENDDO
251 is1=is1+im1
252 is2=is2+im2
253 ENDDO
254 ENDDO
255! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
256! CONTRACT FULL FIELDS TO THINNED FIELDS
257 ELSEIF(idir.EQ.-1) THEN
258 DO k=1,km
259 is1=0
260 is2=0
261 ib_thin(k)=0
262 DO j=1,igdtmpl_full(9)
263 im1=opt_pts(j)
264 im2=igdtmpl_full(8)
265 rat2=float(im2-1)/float(im1-1)
266 DO i=1,im1
267 x2=(i-1)*rat2+1
268 ia=x2
269 ia=min(max(ia,1),im2-1)
270 ib=ia+1
271 wa=ib-x2
272 wb=x2-ia
273 IF(wa.GE.wb) THEN
274 IF(ib_full(k).EQ.0.OR.bitmap_full(is2+ia,k)) THEN
275 data_thin(is1+i,k)=data_full(is2+ia,k)
276 bitmap_thin(is1+i,k)=.true.
277 ELSE
278 data_thin(is1+i,k)=0.0
279 bitmap_thin(is1+i,k)=.false.
280 ib_thin(k)=1
281 ENDIF
282 ELSE
283 IF(ib_full(k).EQ.0.OR.bitmap_full(is2+ib,k)) THEN
284 data_thin(is1+i,k)=data_full(is2+ib,k)
285 bitmap_thin(is1+i,k)=.true.
286 ELSE
287 data_thin(is1+i,k)=0.0
288 bitmap_thin(is1+i,k)=.false.
289 ib_thin(k)=1
290 ENDIF
291 ENDIF
292 ENDDO
293 is1=is1+im1
294 is2=is2+im2
295 ENDDO
296 ENDDO
297 ENDIF
298 ENDIF
299! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
300 END SUBROUTINE ipxwafs3