NCEPLIBS-ip 5.3.0
All Data Structures Namespaces Files Functions Variables Pages
spectral_interp_mod.F90
Go to the documentation of this file.
1!> @file
2!! @brief Interpolate spectral.
3!! @author Mark Iredell @date 96-04-10
4
5!> @brief Interpolate spectral.
6!!
7!! @author Mark Iredell @date 96-04-10
9 use gdswzd_mod
10 use ip_grid_mod
14 use sp_mod
15 implicit none
16
17 private
18 public :: interpolate_spectral
19
21 module procedure interpolate_spectral_scalar
22 module procedure interpolate_spectral_vector
23 end interface interpolate_spectral
24
25 interface polates4
26 module procedure polates4_grib1
27 module procedure polates4_grib2
28 end interface polates4
29
30 interface polatev4
31 module procedure polatev4_grib1
32 module procedure polatev4_grib2
33 end interface polatev4
34
35contains
36
37 !> Interpolate spectral scalar.
38 !>
39 !> @param[in] ipopt interpolation options; ipopt(1)=0 for triangular;
40 !> ipopt(1)=1 for rhomboidal; ipopt(2) is truncation number
41 !> (defaults to a sensible truncation if ipopt(2)=-1).
42 !> @param[in] grid_in input grid descriptor.
43 !> @param[in] grid_out output grid descriptor.
44 !> @param[in] MI skip number between input grid fields if km>1 or
45 !> dimension of input grid fields if km=1.
46 !> @param[in] MO skip number between output grid fields if km>1 or
47 !> dimension of output grid fields if km=1.
48 !> @param[in] KM number of fields to interpolate.
49 !> @param[in] IBI input bitmap flags (Must be all 0. Routine does
50 !> not do bitmapped interpolation.)
51 !> @param[in] GI input fields to interpolate.
52 !> @param[out] NO number of output points.
53 !> @param[inout] RLAT output latitudes in degrees.
54 !> @param[inout] RLON output longitudes in degrees.
55 !> @param[out] IBO output bitmap flags.
56 !> @param[out] LO output bitmaps.
57 !> @param[out] GO output fields interpolated.
58 !> @param[out] IRET return code. 0/non-0 - successful/not successful.
59 !>
60 !! @author Mark Iredell @date 96-04-10
61 subroutine interpolate_spectral_scalar(IPOPT,grid_in,grid_out, &
62 MI,MO,KM,IBI,GI, &
63 NO,RLAT,RLON,IBO,LO,GO,IRET)
64 INTEGER, INTENT(IN ) :: IPOPT(20)
65 class(ip_grid), intent(in) :: grid_in, grid_out
66 INTEGER, INTENT(IN ) :: MI, MO
67 INTEGER, INTENT(IN ) :: IBI(KM), KM
68 INTEGER, INTENT( OUT) :: IBO(KM), IRET, NO
69 !
70 LOGICAL*1, INTENT( OUT) :: LO(MO,KM)
71 !
72 REAL, INTENT(IN ) :: GI(MI,KM)
73 REAL, INTENT(INOUT) :: RLAT(MO),RLON(MO)
74 REAL, INTENT( OUT) :: GO(MO,KM)
75
76
77 select type(desc_in => grid_in%descriptor)
78 type is(grib1_descriptor)
79 select type(desc_out => grid_out%descriptor)
80 type is(grib1_descriptor)
81 CALL polates4(ipopt,desc_in%gds,desc_out%gds,mi,mo,km,ibi,gi,no,rlat,rlon,ibo,lo,go,iret)
82 end select
83
84 type is(grib2_descriptor)
85 select type(desc_out => grid_out%descriptor)
86 type is(grib2_descriptor)
87 CALL polates4(ipopt,desc_in%gdt_num,desc_in%gdt_tmpl,desc_in%gdt_len, &
88 desc_out%gdt_num,desc_out%gdt_tmpl,desc_out%gdt_len, &
89 mi,mo,km,ibi,gi,no,rlat,rlon,ibo,lo,go,iret)
90 end select
91 end select
92 end subroutine interpolate_spectral_scalar
93
94 !> Interpolate spectral vector.
95 !>
96 !> @param ipopt interpolation options; ipopt(1)=0 for triangular;
97 !> ipopt(1)=1 for rhomboidal; ipopt(2) is truncation number
98 !> (defaults to a sensible truncation if ipopt(2)=-1).
99 !> @param grid_in input grid descriptor.
100 !> @param grid_out output grid descriptor.
101 !> @param MI skip number between input grid fields if km>1 or
102 !> dimension of input grid fields if km=1.
103 !> @param MO skip number between output grid fields if km>1 or
104 !> dimension of output grid fields if km=1.
105 !> @param KM number of fields to interpolate.
106 !> @param IBI input bitmap flags (Must be all 0. Routine does not do
107 !> bitmapped interpolation.)
108 !> @param UI input u-component fields to interpolate.
109 !> @param VI input v-component fields to interpolate.
110 !> @param NO number of output points.
111 !> @param RLAT output latitudes in degrees.
112 !> @param RLON output longitudes in degrees.
113 !> @param CROT vector rotation cosines.
114 !> @param SROT vector rotation sines.
115 !> @param IBO output bitmap flags.
116 !> @param LO output bitmaps.
117 !> @param UO output u-component fields interpolated.
118 !> @param VO output v-component fields interpolated.
119 !> @param IRET return code. 0/non-0 - successful/not successful.
120 !>
121 !! @author Mark Iredell @date 96-04-10
122 subroutine interpolate_spectral_vector(IPOPT,grid_in,grid_out, &
123 MI,MO,KM,IBI,UI,VI, &
124 NO,RLAT,RLON,CROT,SROT,IBO,LO,UO,VO,IRET)
125 class(ip_grid), intent(in) :: grid_in, grid_out
126 INTEGER, INTENT(IN ) :: IPOPT(20), IBI(KM)
127 INTEGER, INTENT(IN ) :: KM, MI, MO
128 INTEGER, INTENT( OUT) :: IRET, IBO(KM), NO
129 !
130 LOGICAL*1, INTENT( OUT) :: LO(MO,KM)
131 !
132 REAL, INTENT(IN ) :: UI(MI,KM),VI(MI,KM)
133 REAL, INTENT( OUT) :: UO(MO,KM),VO(MO,KM)
134 REAL, INTENT(INOUT) :: RLAT(MO),RLON(MO)
135 REAL, INTENT( OUT) :: CROT(MO),SROT(MO)
136
137
138 select type(desc_in => grid_in%descriptor)
139 type is(grib1_descriptor)
140 select type(desc_out => grid_out%descriptor)
141 type is(grib1_descriptor)
142 CALL polatev4_grib1(ipopt,desc_in%gds,desc_out%gds,mi,mo,km,ibi,ui,vi,&
143 no,rlat,rlon,crot,srot,ibo,lo,uo,vo,iret)
144 end select
145
146 type is(grib2_descriptor)
147 select type(desc_out => grid_out%descriptor)
148 type is(grib2_descriptor)
149 CALL polatev4(ipopt,desc_in%gdt_num,desc_in%gdt_tmpl,desc_in%gdt_len, &
150 desc_out%gdt_num,desc_out%gdt_tmpl,desc_out%gdt_len, &
151 mi,mo,km,ibi,ui,vi,&
152 no,rlat,rlon,crot,srot,ibo,lo,uo,vo,iret)
153 end select
154 end select
155
156
157 end subroutine interpolate_spectral_vector
158! @author Mark Iredell @date 96-04-10
159 !> Interpolate scalar fields (spectral).
160 !>
161 !> This subprogram performs spectral interpolation from any grid to
162 !> any grid for scalar fields. It requires that the input fields be
163 !> uniformly global. Options allow choices between triangular shape
164 !> (ipopt(1)=0) and rhomboidal shape (ipopt(1)=1) which has no
165 !> default; a second option is the truncation (ipopt(2)) which
166 !> defaults to a sensible truncation for the input grid (if
167 !> opt(2)=-1).
168 !>
169 !> @note If the output grid is not found in a special list, then the
170 !> transform back to grid is not very fast. This special list
171 !> contains global cylindrical grids, polar stereographic grids
172 !> centered at the pole and mercator grids.
173 !>
174 !> Only horizontal interpolation is performed.
175 !>
176 !> The code recognizes the following projections, where "igdtnumi/o"
177 !> is the GRIB2 grid defintion template number for the input and
178 !> onutput grids, respectively:
179 !> - igdtnumi/o = 00 equidistant cylindrical
180 !> - igdtnumo = 01 rotated equidistant cylindrical. "e" and non-"e" staggered
181 !> - igdtnumo = 10 mercator cylindrical
182 !> - igdtnumo = 20 polar stereographic azimuthal
183 !> - igdtnumo = 30 lambert conformal conical
184 !> - igdtnumi/o = 40 gaussian cylindrical
185 !>
186 !> As an added bonus the number of output grid points and their
187 !> latitudes and longitudes are also returned. On the other hand,
188 !> the output can be a set of station points if igdtnumo < 0, in which
189 !> case the number of points and their latitudes and longitudes must
190 !> be input. Output bitmaps will not be created.
191 !>
192 !> ### Program History Log
193 !> Date | Programmer | Comments
194 !> -----|------------|---------
195 !> 96-04-10 | Iredell | initial
196 !> 2001-06-18 | Iredell | improve detection of special fast transform
197 !> 2015-01-27 | Gayno | replace calls to gdswiz with new merged version of gdswzd.
198 !> 2015-07-13 | Gayno | convert to grib 2. replace grib 1 kgds arrays with grib 2 grid definition template arrays.
199 !>
200 !> @param[in] ipopt (20) interpolation options; ipopt(1)=0 for
201 !> triangular, ipopt(1)=1 for rhomboidal; ipopt(2) is truncation
202 !> number (defaults to sensible if ipopt(2)=-1).
203 !> @param[in] igdtnumi grid definition template number - input
204 !> grid. Corresponds to the gfld%igdtnum component of the
205 !> [NCEPLIBS-g2](https://github.com/NOAA-EMC/NCEPLIBS-g2) library
206 !> gridmod data structure.
207 !> - 00 - equidistant cylindrical
208 !> - 01 - rotated equidistant cylindrical. "e" and non-"e" staggered
209 !> - 10 - mercator cyclindrical
210 !> - 20 - polar stereographic azimuthal
211 !> - 30 - lambert conformal conical
212 !> - 40 - gaussian equidistant cyclindrical
213 !> @param[in] igdtmpli (igdtleni) grid definition template array -
214 !> input grid. corresponds to the gfld%igdtmpl component of the ncep
215 !> g2 library gridmod data structure: (section 3 info). See comments
216 !> in routine ipolates() for complete definition.
217 !> @param[in] igdtleni number of elements of the grid definition
218 !> template array - input grid. corresponds to the gfld%igdtlen
219 !> component of the ncep g2 library gridmod data structure.
220 !> @param[in] igdtnumo grid definition template number - output
221 !> grid. Corresponds to the gfld%igdtnum component of the
222 !> [NCEPLIBS-g2](https://github.com/NOAA-EMC/NCEPLIBS-g2) library
223 !> gridmod data structure. igdtnumo<0 means interpolate to random
224 !> station points. Otherwise, same definition as igdtnumi.
225 !> @param[in] igdtmplo (igdtleno) grid definition template array -
226 !> output grid. Corresponds to the gfld%igdtmpl component of the
227 !> ncep g2 library gridmod data structure (section 3 info). See
228 !> comments in routine ipolates() for complete definition.
229 !> @param[in] igdtleno number of elements of the grid definition
230 !> template array - output grid. Corresponds to the gfld%igdtlen
231 !> component of the
232 !> [NCEPLIBS-g2](https://github.com/NOAA-EMC/NCEPLIBS-g2) library
233 !> gridmod data structure.
234 !> @param[in] mi skip number between input grid fields if km>1 or
235 !> dimension of input grid fields if km=1
236 !> @param[in] mo skip number between output grid fields if km>1 or
237 !> dimension of output grid fields if km=1
238 !> @param[out] km number of fields to interpolate
239 !> @param[out] ibi (km) input bitmap flags (must be all 0)
240 !> @param[out] gi (mi,km) input fields to interpolate
241 !> @param[out] no number of output points (only if igdtnumo>=0)
242 !> @param[out] rlat (mo) output latitudes in degrees (if igdtnumo<0)
243 !> @param[out] rlon (mo) output longitudes in degrees (if igdtnumo<0)
244 !> @param[out] ibo (km) output bitmap flags
245 !> @param[out] lo (mo,km) output bitmaps (always output)
246 !> @param[out] go (mo,km) output fields interpolated
247 !> @param[out] iret return code
248 !> - 0 successful interpolation
249 !> - 2 unrecognized input grid or no grid overlap
250 !> - 3 unrecognized output grid
251 !> - 41 invalid nonglobal input grid
252 !> - 42 invalid spectral method parameters
253 !>
254 !>
255 SUBROUTINE polates4_grib2(IPOPT,IGDTNUMI,IGDTMPLI,IGDTLENI, &
256 IGDTNUMO,IGDTMPLO,IGDTLENO, &
257 MI,MO,KM,IBI,GI, &
258 NO,RLAT,RLON,IBO,LO,GO,IRET)
259 INTEGER, INTENT(IN ) :: IGDTNUMI, IGDTLENI
260 INTEGER, INTENT(IN ) :: IGDTMPLI(IGDTLENI)
261 INTEGER, INTENT(IN ) :: IGDTNUMO, IGDTLENO
262 INTEGER, INTENT(IN ) :: IGDTMPLO(IGDTLENO)
263 INTEGER, INTENT(IN ) :: IPOPT(20)
264 INTEGER, INTENT(IN ) :: MI, MO
265 INTEGER, INTENT(IN ) :: IBI(KM), KM
266 INTEGER, INTENT( OUT) :: IBO(KM), IRET, NO
267 !
268 LOGICAL*1, INTENT( OUT) :: LO(MO,KM)
269 !
270 REAL, INTENT(IN ) :: GI(MI,KM)
271 REAL, INTENT(INOUT) :: RLAT(MO),RLON(MO)
272 REAL, INTENT( OUT) :: GO(MO,KM)
273 !
274 REAL, PARAMETER :: FILL=-9999.
275 REAL, PARAMETER :: PI=3.14159265358979
276 REAL, PARAMETER :: DPR=180./pi
277 !
278 INTEGER :: IDRTI, IDRTO, IG, JG, IM, JM
279 INTEGER :: IGO, JGO, IMO, JMO
280 INTEGER :: ISCAN, JSCAN, NSCAN
281 INTEGER :: ISCANO, JSCANO, NSCANO
282 INTEGER :: ISKIPI, JSKIPI, ISCALE
283 INTEGER :: IMAXI, JMAXI, ISPEC
284 INTEGER :: IP, IPRIME, IPROJ, IROMB, K
285 INTEGER :: MAXWV, N, NI, NJ, NPS
286 !
287 REAL :: DE, DR, DY
288 REAL :: DLAT, DLON, DLATO, DLONO
289 REAL :: GO2(MO,KM), H, HI, HJ
290 REAL :: ORIENT, SLAT, RERTH, E2
291 REAL :: RLAT1, RLON1, RLAT2, RLON2, RLATI
292 REAL :: XMESH, XP, YP
293 REAL :: XPTS(MO), YPTS(MO)
294
295 type(grib2_descriptor) :: desc_in, desc_out
296 class(ip_grid), allocatable :: grid_in, grid_out
297
298 desc_in = init_descriptor(igdtnumi, igdtleni, igdtmpli)
299 desc_out = init_descriptor(igdtnumo, igdtleno, igdtmplo)
300
301 call init_grid(grid_in, desc_in)
302 call init_grid(grid_out, desc_out)
303 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
304 ! COMPUTE NUMBER OF OUTPUT POINTS AND THEIR LATITUDES AND LONGITUDES.
305 iret=0
306 IF(igdtnumo.GE.0) THEN
307 !CALL GDSWZD(IGDTNUMO,IGDTMPLO,IGDTLENO, 0,MO,FILL,XPTS,YPTS,RLON,RLAT,NO)
308 CALL gdswzd(grid_out, 0,mo,fill,xpts,ypts,rlon,rlat,no)
309 IF(no.EQ.0) iret=3
310 ENDIF
311 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
312 ! AFFIRM APPROPRIATE INPUT GRID
313 ! LAT/LON OR GAUSSIAN
314 ! NO BITMAPS
315 ! FULL ZONAL COVERAGE
316 ! FULL MERIDIONAL COVERAGE
317 idrti=igdtnumi
318 IF(idrti==40) idrti=4
319 IF(idrti==0.OR.idrti==4)THEN
320 im=igdtmpli(8)
321 jm=igdtmpli(9)
322 iscale=igdtmpli(10)*igdtmpli(11)
323 IF(iscale==0) iscale=10**6
324 rlon1=float(igdtmpli(13))/float(iscale)
325 rlon2=float(igdtmpli(16))/float(iscale)
326 iscan=mod(igdtmpli(19)/128,2)
327 jscan=mod(igdtmpli(19)/64,2)
328 nscan=mod(igdtmpli(19)/32,2)
329 ELSE
330 iret=41
331 ENDIF
332 DO k=1,km
333 IF(ibi(k).NE.0) iret=41
334 ENDDO
335 IF(iret.EQ.0) THEN
336 IF(iscan.EQ.0) THEN
337 dlon=(mod(rlon2-rlon1-1+3600,360.)+1)/(im-1)
338 ELSE
339 dlon=-(mod(rlon1-rlon2-1+3600,360.)+1)/(im-1)
340 ENDIF
341 ig=nint(360/abs(dlon))
342 iprime=1+mod(-nint(rlon1/dlon)+ig,ig)
343 imaxi=ig
344 jmaxi=jm
345 IF(mod(ig,2).NE.0.OR.im.LT.ig) iret=41
346 ENDIF
347 IF(iret.EQ.0.AND.idrti.EQ.0) THEN
348 iscale=igdtmpli(10)*igdtmpli(11)
349 IF(iscale==0) iscale=10**6
350 rlat1=float(igdtmpli(12))/float(iscale)
351 rlat2=float(igdtmpli(15))/float(iscale)
352 dlat=(rlat2-rlat1)/(jm-1)
353 jg=nint(180/abs(dlat))
354 IF(jm.EQ.jg) idrti=256
355 IF(jm.NE.jg.AND.jm.NE.jg+1) iret=41
356 ELSEIF(iret.EQ.0.AND.idrti.EQ.4) THEN
357 jg=igdtmpli(18)*2
358 IF(jm.NE.jg) iret=41
359 ENDIF
360 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
361 ! SET PARAMETERS
362 IF(iret.EQ.0) THEN
363 iromb=ipopt(1)
364 maxwv=ipopt(2)
365 IF(maxwv.EQ.-1) THEN
366 IF(iromb.EQ.0.AND.idrti.EQ.4) maxwv=(jmaxi-1)
367 IF(iromb.EQ.1.AND.idrti.EQ.4) maxwv=(jmaxi-1)/2
368 IF(iromb.EQ.0.AND.idrti.EQ.0) maxwv=(jmaxi-3)/2
369 IF(iromb.EQ.1.AND.idrti.EQ.0) maxwv=(jmaxi-3)/4
370 IF(iromb.EQ.0.AND.idrti.EQ.256) maxwv=(jmaxi-1)/2
371 IF(iromb.EQ.1.AND.idrti.EQ.256) maxwv=(jmaxi-1)/4
372 ENDIF
373 IF((iromb.NE.0.AND.iromb.NE.1).OR.maxwv.LT.0) iret=42
374 ENDIF
375 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
376 ! INTERPOLATE
377 IF(iret.EQ.0) THEN
378 IF(nscan.EQ.0) THEN
379 iskipi=1
380 jskipi=im
381 ELSE
382 iskipi=jm
383 jskipi=1
384 ENDIF
385 IF(iscan.EQ.1) iskipi=-iskipi
386 IF(jscan.EQ.0) jskipi=-jskipi
387 ispec=0
388 ! SPECIAL CASE OF GLOBAL CYLINDRICAL GRID
389 IF((igdtnumo.EQ.0.OR.igdtnumo.EQ.40).AND. &
390 mod(igdtmplo(8),2).EQ.0.AND.igdtmplo(13).EQ.0.AND.igdtmplo(19).EQ.0) THEN
391 idrto=igdtnumo
392 IF(idrto==40)idrto=4
393 imo=igdtmplo(8)
394 jmo=igdtmplo(9)
395 iscale=igdtmplo(10)*igdtmplo(11)
396 IF(iscale==0) iscale=10**6
397 rlon2=float(igdtmplo(16))/float(iscale)
398 dlono=(mod(rlon2-1+3600,360.)+1)/(imo-1)
399 igo=nint(360/abs(dlono))
400 IF(imo.EQ.igo.AND.idrto.EQ.0) THEN
401 rlat1=float(igdtmplo(12))/float(iscale)
402 rlat2=float(igdtmplo(15))/float(iscale)
403 dlat=(rlat2-rlat1)/(jmo-1)
404 jgo=nint(180/abs(dlat))
405 IF(jmo.EQ.jgo) idrto=256
406 IF(jmo.EQ.jgo.OR.jmo.EQ.jgo+1) ispec=1
407 ELSEIF(imo.EQ.igo.AND.idrto.EQ.4) THEN
408 jgo=igdtmplo(18)*2
409 IF(jmo.EQ.jgo) ispec=1
410 ENDIF
411 IF(ispec.EQ.1) THEN
412 CALL sptrun(iromb,maxwv,idrti,imaxi,jmaxi,idrto,imo,jmo, &
413 km,iprime,iskipi,jskipi,mi,0,0,mo,0,gi,go)
414 ENDIF
415 ! SPECIAL CASE OF POLAR STEREOGRAPHIC GRID
416 ELSEIF(igdtnumo.EQ.20.AND. &
417 igdtmplo(8).EQ.igdtmplo(9).AND.mod(igdtmplo(8),2).EQ.1.AND. &
418 igdtmplo(15).EQ.igdtmplo(16).AND.igdtmplo(18).EQ.64) THEN
419 nps=igdtmplo(8)
420 rlat1=float(igdtmplo(10))*1.e-6
421 rlon1=float(igdtmplo(11))*1.e-6
422 orient=float(igdtmplo(14))*1.e-6
423 xmesh=float(igdtmplo(15))*1.e-3
424 iproj=mod(igdtmplo(17)/128,2)
425 ip=(nps+1)/2
426 h=(-1.)**iproj
427 slat=float(abs(igdtmplo(13)))*1.e-6
428 CALL earth_radius(igdtmplo,igdtleno,rerth,e2)
429 de=(1.+sin(slat/dpr))*rerth
430 dr=de*cos(rlat1/dpr)/(1+h*sin(rlat1/dpr))
431 xp=1-h*sin((rlon1-orient)/dpr)*dr/xmesh
432 yp=1+cos((rlon1-orient)/dpr)*dr/xmesh
433 IF(nint(xp).EQ.ip.AND.nint(yp).EQ.ip) THEN
434 IF(iproj.EQ.0) THEN
435 CALL sptruns(iromb,maxwv,idrti,imaxi,jmaxi,km,nps, &
436 iprime,iskipi,jskipi,mi,mo,0,0,0, &
437 slat,xmesh,orient,gi,go,go2)
438 ELSE
439 CALL sptruns(iromb,maxwv,idrti,imaxi,jmaxi,km,nps, &
440 iprime,iskipi,jskipi,mi,mo,0,0,0, &
441 slat,xmesh,orient,gi,go2,go)
442 ENDIF
443 ispec=1
444 ENDIF
445 ! SPECIAL CASE OF MERCATOR GRID
446 ELSEIF(igdtnumo.EQ.10) THEN
447 ni=igdtmplo(8)
448 nj=igdtmplo(9)
449 rlat1=float(igdtmplo(10))*1.0e-6
450 rlon1=float(igdtmplo(11))*1.0e-6
451 rlon2=float(igdtmplo(15))*1.0e-6
452 rlati=float(igdtmplo(13))*1.0e-6
453 iscano=mod(igdtmplo(16)/128,2)
454 jscano=mod(igdtmplo(16)/64,2)
455 nscano=mod(igdtmplo(16)/32,2)
456 dy=float(igdtmplo(19))*1.0e-3
457 hi=(-1.)**iscano
458 hj=(-1.)**(1-jscano)
459 CALL earth_radius(igdtmplo,igdtleno,rerth,e2)
460 dlono=hi*(mod(hi*(rlon2-rlon1)-1+3600,360.)+1)/(ni-1)
461 dlato=hj*dy/(rerth*cos(rlati/dpr))*dpr
462 IF(nscano.EQ.0) THEN
463 CALL sptrunm(iromb,maxwv,idrti,imaxi,jmaxi,km,ni,nj, &
464 iprime,iskipi,jskipi,mi,mo,0,0,0, &
465 rlat1,rlon1,dlato,dlono,gi,go)
466 ispec=1
467 ENDIF
468 ENDIF
469 ! GENERAL SLOW CASE
470 IF(ispec.EQ.0) THEN
471 CALL sptrung(iromb,maxwv,idrti,imaxi,jmaxi,km,no, &
472 iprime,iskipi,jskipi,mi,mo,0,0,0,rlat,rlon,gi,go)
473 ENDIF
474 DO k=1,km
475 ibo(k)=0
476 DO n=1,no
477 lo(n,k)=.true.
478 ENDDO
479 ENDDO
480 ELSE
481 DO k=1,km
482 ibo(k)=1
483 DO n=1,no
484 lo(n,k)=.false.
485 go(n,k)=0.
486 ENDDO
487 ENDDO
488 ENDIF
489 END SUBROUTINE polates4_grib2
490
491 !> Interpolate scalar fields (spectral).
492 !>
493 !> This subprogram performs spectral interpolation from any grid to
494 !> any grid for scalar fields. It requires that the input fields be
495 !> uniformly global.
496 !>
497 !> Options allow choices between triangular shape (ipopt(1)=0) and
498 !> rhomboidal shape (ipopt(1)=1) which has no default; a second
499 !> option is the truncation (ipopt(2)) which defaults to a sensible
500 !> truncation for the input grid (if opt(2)=-1).
501 !>
502 !> @note If the output grid is not found in a special list, then the
503 !> transform back to grid is not very fast. This special list
504 !> contains global cylindrical grids, polar stereographic grids
505 !> centered at the pole and mercator grids.
506 !>
507 !> Only horizontal interpolation is performed. The grids are defined
508 !> by their grid description sections (passed in integer form as
509 !> decoded by subprogram w3fi63()).
510 !>
511 !> The current code recognizes the following projections:
512 !> - kgds(1) = 000 equidistant cylindrical
513 !> - kgds(1) = 001 mercator cylindrical
514 !> - kgds(1) = 003 lambert conformal conical
515 !> - kgds(1) = 004 gaussian cylindrical (spectral native)
516 !> - kgds(1) = 005 polar stereographic azimuthal
517 !> - kgds(1) = 203 rotated equidistant cylindrical (e-stagger)
518 !> - kgds(1) = 205 rotated equidistant cylindrical (b-stagger)
519 !>
520 !> Where kgds could be either input kgdsi or output kgdso. As an
521 !> added bonus the number of output grid points and their latitudes
522 !> and longitudes are also returned. On the other hand, the output
523 !> can be a set of station points if kgdso(1)<0, in which case the
524 !> number of points and their latitudes and longitudes must be
525 !> input. Output bitmaps will not be created.
526 !>
527 !> ### Program History Log
528 !> Date | Programmer | Comments
529 !> -----|------------|---------
530 !> 96-04-10 | Iredell | Initial
531 !> 2001-06-18 | Iredell | improve detection of special fast transform
532 !> 2015-01-27 | Gayno | replace calls to gdswiz() with new merged version of gdswzd().
533 !>
534 !> @param[in] ipopt (20) interpolation options ipopt(1)=0 for
535 !> triangular, ipopt(1)=1 for rhomboidal; ipopt(2) is truncation
536 !> number (defaults to sensible if ipopt(2)=-1).
537 !> @param[in] kgdsi (200) input gds parameters as decoded by w3fi63
538 !> @param[in] kgdso (200) output gds parameters (kgdso(1)<0 implies random station points)
539 !> @param[in] mi skip number between input grid fields if km>1 or
540 !> dimension of input grid fields if km=1
541 !> @param[in] mo skip number between output grid fields if km>1 or
542 !> dimension of output grid fields if km=1
543 !> @param[in] km number of fields to interpolate
544 !> @param[in] ibi (km) input bitmap flags (must be all 0)
545 !> @param[in] gi (mi,km) input fields to interpolate
546 !> @param[out] no number of output points (only if kgdso(1)<0)
547 !> @param[out] rlat (no) output latitudes in degrees (if kgdso(1)<0)
548 !> @param[out] rlon (no) output longitudes in degrees (if kgdso(1)<0)
549 !> @param[out] ibo (km) output bitmap flags
550 !> @param[out] lo (mo,km) output bitmaps (always output)
551 !> @param[out] go (mo,km) output fields interpolated
552 !> @param[out] iret return code
553 !> - 0 successful interpolation
554 !> - 2 unrecognized input grid or no grid overlap
555 !> - 3 unrecognized output grid
556 !> - 41 invalid nonglobal input grid
557 !> - 42 invalid spectral method parameters
558 !>
559 !> @author Iredell @date 96-04-10
560 suBROUTINE polates4_grib1(IPOPT,KGDSI,KGDSO,MI,MO,KM,IBI,GI, &
561 NO,RLAT,RLON,IBO,LO,GO,IRET)
562 INTEGER, INTENT(IN ) :: IPOPT(20), KGDSI(200)
563 INTEGER, INTENT(IN ) :: KGDSO(200), MI, MO
564 INTEGER, INTENT(IN ) :: IBI(KM), KM
565 INTEGER, INTENT( OUT) :: IBO(KM), IRET
566 !
567 LOGICAL*1, INTENT( OUT) :: LO(MO,KM)
568 !
569 REAL, INTENT(IN ) :: GI(MI,KM)
570 REAL, INTENT(INOUT) :: RLAT(MO),RLON(MO)
571 REAL, INTENT( OUT) :: GO(MO,KM)
572 !
573 REAL, PARAMETER :: FILL=-9999.
574 REAL, PARAMETER :: RERTH=6.3712e6
575 REAL, PARAMETER :: PI=3.14159265358979
576 REAL, PARAMETER :: DPR=180./pi
577 !
578 INTEGER :: IDRTI, IDRTO, IG, JG, IM, JM
579 INTEGER :: IGO, JGO, IMO, JMO
580 INTEGER :: ISCAN, JSCAN, NSCAN
581 INTEGER :: ISCANO, JSCANO, NSCANO
582 INTEGER :: ISKIPI, JSKIPI
583 INTEGER :: IMAXI, JMAXI, ISPEC
584 INTEGER :: IP, IPRIME, IPROJ, IROMB, K
585 INTEGER :: MAXWV, N, NI, NJ, NPS, NO
586 !
587 REAL :: DE, DR, DY
588 REAL :: DLAT, DLON, DLATO, DLONO
589 REAL :: GO2(MO,KM), H, HI, HJ
590 REAL :: ORIENT
591 REAL :: RLAT1, RLON1, RLAT2, RLON2, RLATI
592 REAL :: XMESH, XP, YP
593 REAL :: XPTS(MO), YPTS(MO)
594
595 type(grib1_descriptor) :: desc_in, desc_out
596 class(ip_grid), allocatable :: grid_in, grid_out
597
598 desc_in = init_descriptor(kgdsi)
599 desc_out = init_descriptor(kgdso)
600
601 call init_grid(grid_in, desc_in)
602 call init_grid(grid_out, desc_out)
603
604 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
605 ! COMPUTE NUMBER OF OUTPUT POINTS AND THEIR LATITUDES AND LONGITUDES.
606 iret=0
607 IF(kgdso(1).GE.0) THEN
608 CALL gdswzd(grid_out, 0,mo,fill,xpts,ypts,rlon,rlat,no)
609 IF(no.EQ.0) iret=3
610 ENDIF
611 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
612 ! AFFIRM APPROPRIATE INPUT GRID
613 ! LAT/LON OR GAUSSIAN
614 ! NO BITMAPS
615 ! FULL ZONAL COVERAGE
616 ! FULL MERIDIONAL COVERAGE
617 idrti=kgdsi(1)
618 im=kgdsi(2)
619 jm=kgdsi(3)
620 rlon1=kgdsi(5)*1.e-3
621 rlon2=kgdsi(8)*1.e-3
622 iscan=mod(kgdsi(11)/128,2)
623 jscan=mod(kgdsi(11)/64,2)
624 nscan=mod(kgdsi(11)/32,2)
625 IF(idrti.NE.0.AND.idrti.NE.4) iret=41
626 DO k=1,km
627 IF(ibi(k).NE.0) iret=41
628 ENDDO
629 IF(iret.EQ.0) THEN
630 IF(iscan.EQ.0) THEN
631 dlon=(mod(rlon2-rlon1-1+3600,360.)+1)/(im-1)
632 ELSE
633 dlon=-(mod(rlon1-rlon2-1+3600,360.)+1)/(im-1)
634 ENDIF
635 ig=nint(360/abs(dlon))
636 iprime=1+mod(-nint(rlon1/dlon)+ig,ig)
637 imaxi=ig
638 jmaxi=jm
639 IF(mod(ig,2).NE.0.OR.im.LT.ig) iret=41
640 ENDIF
641 IF(iret.EQ.0.AND.idrti.EQ.0) THEN
642 rlat1=kgdsi(4)*1.e-3
643 rlat2=kgdsi(7)*1.e-3
644 dlat=(rlat2-rlat1)/(jm-1)
645 jg=nint(180/abs(dlat))
646 IF(jm.EQ.jg) idrti=256
647 IF(jm.NE.jg.AND.jm.NE.jg+1) iret=41
648 ELSEIF(iret.EQ.0.AND.idrti.EQ.4) THEN
649 jg=kgdsi(10)*2
650 IF(jm.NE.jg) iret=41
651 ENDIF
652 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
653 ! SET PARAMETERS
654 IF(iret.EQ.0) THEN
655 iromb=ipopt(1)
656 maxwv=ipopt(2)
657 IF(maxwv.EQ.-1) THEN
658 IF(iromb.EQ.0.AND.idrti.EQ.4) maxwv=(jmaxi-1)
659 IF(iromb.EQ.1.AND.idrti.EQ.4) maxwv=(jmaxi-1)/2
660 IF(iromb.EQ.0.AND.idrti.EQ.0) maxwv=(jmaxi-3)/2
661 IF(iromb.EQ.1.AND.idrti.EQ.0) maxwv=(jmaxi-3)/4
662 IF(iromb.EQ.0.AND.idrti.EQ.256) maxwv=(jmaxi-1)/2
663 IF(iromb.EQ.1.AND.idrti.EQ.256) maxwv=(jmaxi-1)/4
664 ENDIF
665 IF((iromb.NE.0.AND.iromb.NE.1).OR.maxwv.LT.0) iret=42
666 ENDIF
667 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
668 ! INTERPOLATE
669 IF(iret.EQ.0) THEN
670 IF(nscan.EQ.0) THEN
671 iskipi=1
672 jskipi=im
673 ELSE
674 iskipi=jm
675 jskipi=1
676 ENDIF
677 IF(iscan.EQ.1) iskipi=-iskipi
678 IF(jscan.EQ.0) jskipi=-jskipi
679 ispec=0
680 ! SPECIAL CASE OF GLOBAL CYLINDRICAL GRID
681 IF((kgdso(1).EQ.0.OR.kgdso(1).EQ.4).AND. &
682 mod(kgdso(2),2).EQ.0.AND.kgdso(5).EQ.0.AND.kgdso(11).EQ.0) THEN
683 idrto=kgdso(1)
684 imo=kgdso(2)
685 jmo=kgdso(3)
686 rlon2=kgdso(8)*1.e-3
687 dlono=(mod(rlon2-1+3600,360.)+1)/(imo-1)
688 igo=nint(360/abs(dlono))
689 IF(imo.EQ.igo.AND.idrto.EQ.0) THEN
690 rlat1=kgdso(4)*1.e-3
691 rlat2=kgdso(7)*1.e-3
692 dlat=(rlat2-rlat1)/(jmo-1)
693 jgo=nint(180/abs(dlat))
694 IF(jmo.EQ.jgo) idrto=256
695 IF(jmo.EQ.jgo.OR.jmo.EQ.jgo+1) ispec=1
696 ELSEIF(imo.EQ.igo.AND.idrto.EQ.4) THEN
697 jgo=kgdso(10)*2
698 IF(jmo.EQ.jgo) ispec=1
699 ENDIF
700 IF(ispec.EQ.1) THEN
701 CALL sptrun(iromb,maxwv,idrti,imaxi,jmaxi,idrto,imo,jmo, &
702 km,iprime,iskipi,jskipi,mi,0,0,mo,0,gi,go)
703 ENDIF
704 ! SPECIAL CASE OF POLAR STEREOGRAPHIC GRID
705 ELSEIF(kgdso(1).EQ.5.AND. &
706 kgdso(2).EQ.kgdso(3).AND.mod(kgdso(2),2).EQ.1.AND. &
707 kgdso(8).EQ.kgdso(9).AND.kgdso(11).EQ.64) THEN
708 nps=kgdso(2)
709 rlat1=kgdso(4)*1.e-3
710 rlon1=kgdso(5)*1.e-3
711 orient=kgdso(7)*1.e-3
712 xmesh=kgdso(8)
713 iproj=mod(kgdso(10)/128,2)
714 ip=(nps+1)/2
715 h=(-1.)**iproj
716 de=(1.+sin(60./dpr))*rerth
717 dr=de*cos(rlat1/dpr)/(1+h*sin(rlat1/dpr))
718 xp=1-h*sin((rlon1-orient)/dpr)*dr/xmesh
719 yp=1+cos((rlon1-orient)/dpr)*dr/xmesh
720 IF(nint(xp).EQ.ip.AND.nint(yp).EQ.ip) THEN
721 IF(iproj.EQ.0) THEN
722 CALL sptruns(iromb,maxwv,idrti,imaxi,jmaxi,km,nps, &
723 iprime,iskipi,jskipi,mi,mo,0,0,0, &
724 60.,xmesh,orient,gi,go,go2)
725 ELSE
726 CALL sptruns(iromb,maxwv,idrti,imaxi,jmaxi,km,nps, &
727 iprime,iskipi,jskipi,mi,mo,0,0,0, &
728 60.,xmesh,orient,gi,go2,go)
729 ENDIF
730 ispec=1
731 ENDIF
732 ! SPECIAL CASE OF MERCATOR GRID
733 ELSEIF(kgdso(1).EQ.1) THEN
734 ni=kgdso(2)
735 nj=kgdso(3)
736 rlat1=kgdso(4)*1.e-3
737 rlon1=kgdso(5)*1.e-3
738 rlon2=kgdso(8)*1.e-3
739 rlati=kgdso(9)*1.e-3
740 iscano=mod(kgdso(11)/128,2)
741 jscano=mod(kgdso(11)/64,2)
742 nscano=mod(kgdso(11)/32,2)
743 dy=kgdso(13)
744 hi=(-1.)**iscano
745 hj=(-1.)**(1-jscano)
746 dlono=hi*(mod(hi*(rlon2-rlon1)-1+3600,360.)+1)/(ni-1)
747 dlato=hj*dy/(rerth*cos(rlati/dpr))*dpr
748 IF(nscano.EQ.0) THEN
749 CALL sptrunm(iromb,maxwv,idrti,imaxi,jmaxi,km,ni,nj, &
750 iprime,iskipi,jskipi,mi,mo,0,0,0, &
751 rlat1,rlon1,dlato,dlono,gi,go)
752 ispec=1
753 ENDIF
754 ENDIF
755 ! GENERAL SLOW CASE
756 IF(ispec.EQ.0) THEN
757 CALL sptrung(iromb,maxwv,idrti,imaxi,jmaxi,km,no, &
758 iprime,iskipi,jskipi,mi,mo,0,0,0,rlat,rlon,gi,go)
759 ENDIF
760 DO k=1,km
761 ibo(k)=0
762 DO n=1,no
763 lo(n,k)=.true.
764 ENDDO
765 ENDDO
766 ELSE
767 DO k=1,km
768 ibo(k)=1
769 DO n=1,no
770 lo(n,k)=.false.
771 go(n,k)=0.
772 ENDDO
773 ENDDO
774 ENDIF
775 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
776 END SUBROUTINE polates4_grib1
777
778
779 !> Interpolate vector fields (spectral).
780 !>
781 !> This subprogram performs spectral interpolation from any grid to
782 !> any grid for vector fields. It requires that the input fields be
783 !> uniformly global. Options allow choices between triangular shape
784 !> (ipopt(1)=0) and rhomboidal shape (ipopt(1)=1) which has no
785 !> default; a second option is the truncation (ipopt(2)) which
786 !> defaults to a sensible truncation for the input grid (if
787 !> opt(2)=-1).
788 !>
789 !> @note If the output grid is not found in a special list, then the
790 !> transform back to grid is not very fast. This special list
791 !> contains global cylindrical grids, polar stereographic grids
792 !> centered at the pole and mercator grids. Only horizontal
793 !> interpolation is performed.
794 !>
795 !> The input and output grids are defined by their grib 2 grid
796 !> definition template as decoded by the ncep g2 library. The code
797 !> recognizes the following projections, where "igdtnumi/o" is the
798 !> grib 2 grid defintion template number for the input and output
799 !> grids, respectively:
800 !> - igdtnumi/o=00 equidistant cylindrical
801 !> - igdtnumo =01 rotated equidistant cylindrical. "e" and non-"e" staggered
802 !> - igdtnumo =10 mercator cylindrical
803 !> - igdtnumo =20 polar stereographic azimuthal
804 !> - igdtnumo =30 lambert conformal conical
805 !> - igdtnumi/o=40 gaussian cylindrical
806 !>
807 !> The input and output vectors are rotated so that they are either
808 !> resolved relative to the defined grid in the direction of
809 !> increasing x and y coordinates or resolved relative to easterly
810 !> and northerly directions, as designated by their respective grid
811 !> description sections.
812 !>
813 !> As an added bonus the number of output grid points and their
814 !> latitudes and longitudes are also returned along with their
815 !> vector rotation parameters. On the other hand, the output can be
816 !> a set of station points if igdtnumo<0, in which case the number
817 !> of points and their latitudes and longitudes must be input along
818 !> with their vector rotation parameters.
819 !>
820 !> Output bitmaps will only be created when the output grid extends
821 !> outside of the domain of the input grid. the output field is set
822 !> to 0 where the output bitmap is off.
823 !>
824 !> ### Program History Log
825 !> Date | Programmer | Comments
826 !> -----|------------|---------
827 !> 96-04-10 | iredell | initial
828 !> 2001-06-18 | iredell | improve detection of special fast transform
829 !> 2015-01-27 | gayno | replace calls to gdswiz() with new merged routine gdswzd().
830 !> 2015-07-13 | gayno | convert to grib 2. replace grib 1 kgds arrays with grib 2 grid definition template arrays.
831 !>
832 !> @param[in] ipopt (20) interpolation options ipopt(1)=0 for
833 !> triangular, ipopt(1)=1 for rhomboidal; ipopt(2) is truncation
834 !> number (defaults to sensible if ipopt(2)=-1).
835 !> @param[in] igdtnumi grid definition template number - input
836 !> grid. Corresponds to the gfld%igdtnum component of the ncep g2
837 !> library gridmod data structure:
838 !> - 00 equidistant cylindrical
839 !> - 01 rotated equidistant cylindrical. "e" and non-"e" staggered
840 !> - 10 mercator cyclindrical
841 !> - 20 polar stereographic azimuthal
842 !> - 30 lambert conformal conical
843 !> - 40 gaussian equidistant cyclindrical
844 !> @param[in] igdtmpli (igdtleni) grid definition template array - input
845 !> grid. corresponds to the gfld%igdtmpl component of the ncep g2
846 !> library gridmod data structure (section 3 info). see comments in
847 !> routine ipolatev for complete definition.
848 !> @param[in] igdtleni number of elements of the grid definition
849 !> template array - input grid. corresponds to the gfld%igdtlen
850 !> component of the ncep g2 library gridmod data structure.
851 !> @param[in] igdtnumo grid definition template number - output
852 !> grid. Corresponds to the gfld%igdtnum component of the ncep g2
853 !> library gridmod data structure. igdtnumo<0 means interpolate to
854 !> random station points. Otherwise, same definition as "igdtnumi".
855 !> @param[in] igdtmplo (igdtleno) grid definition template array -
856 !> output grid. corresponds to the gfld%igdtmpl component of the
857 !> ncep g2 library gridmod data structure (section 3 info). see
858 !> comments in routine ipolatev() for complete definition.
859 !> @param[in] igdtleno number of elements of the grid definition
860 !> template array - output grid. Corresponds to the gfld%igdtlen
861 !> component of the ncep g2 library gridmod data structure.
862 !> @param[in] mi skip number between input grid fields if km>1 or
863 !> dimension of input grid fields if km=1.
864 !> @param[in] mo skip number between output grid fields if km>1 or
865 !> dimension of output grid fields if km=1.
866 !> @param[in] km number of fields to interpolate
867 !> @param[in] ibi (km) input bitmap flags (must be all 0)
868 !> @param[in] ui (mi,km) input u-component fields to interpolate
869 !> @param[in] vi (mi,km) input v-component fields to interpolate
870 !> @param[out] no number of output points (only if igdtnumo>=0)
871 !> @param[inout] rlat (mo) output latitudes in degrees (if igdtnumo<0)
872 !> @param[inout] rlon (mo) output longitudes in degrees (if igdtnumo<0)
873 !> @param[inout] crot (mo) vector rotation cosines (if igdtnumo<0)
874 !> @param[inout] srot (mo) vector rotation sines (if igdtnumo<0)
875 !> (ugrid=crot*uearth-srot*vearth; vgrid=srot*uearth+crot*vearth)
876 !> @param[out] ibo (km) output bitmap flags
877 !> @param[out] lo (mo,km) output bitmaps (always output)
878 !> @param[out] uo (mo,km) output u-component fields interpolated
879 !> @param[out] vo (mo,km) output v-component fields interpolated
880 !> @param[out] iret return code
881 !> - 0 successful interpolation
882 !> - 2 unrecognized input grid or no grid overlap
883 !> - 3 unrecognized output grid
884 !> - 41 invalid nonglobal input grid
885 !> - 42 invalid spectral method parameters
886 !>
887 !> @author IREDELL @date 96-04-10
888 SUBROUTINE polatev4_grib2(IPOPT,IGDTNUMI,IGDTMPLI,IGDTLENI, &
889 IGDTNUMO,IGDTMPLO,IGDTLENO, &
890 MI,MO,KM,IBI,UI,VI, &
891 NO,RLAT,RLON,CROT,SROT,IBO,LO,UO,VO,IRET)
892 INTEGER, INTENT(IN ) :: IPOPT(20), IBI(KM)
893 INTEGER, INTENT(IN ) :: KM, MI, MO
894 INTEGER, INTENT( OUT) :: IRET, IBO(KM), NO
895 INTEGER, INTENT(IN ) :: IGDTNUMI, IGDTLENI
896 INTEGER, INTENT(IN ) :: IGDTMPLI(IGDTLENI)
897 INTEGER, INTENT(IN ) :: IGDTNUMO, IGDTLENO
898 INTEGER, INTENT(IN ) :: IGDTMPLO(IGDTLENO)
899 !
900 LOGICAL*1, INTENT( OUT) :: LO(MO,KM)
901 !
902 REAL, INTENT(IN ) :: UI(MI,KM),VI(MI,KM)
903 REAL, INTENT( OUT) :: UO(MO,KM),VO(MO,KM)
904 REAL, INTENT(INOUT) :: RLAT(MO),RLON(MO)
905 REAL, INTENT( OUT) :: CROT(MO),SROT(MO)
906 !
907 REAL, PARAMETER :: FILL=-9999.
908 REAL, PARAMETER :: PI=3.14159265358979
909 REAL, PARAMETER :: DPR=180./pi
910 !
911 INTEGER :: IDRTO, IROMB, ISKIPI, ISPEC
912 INTEGER :: IDRTI, IMAXI, JMAXI, IM, JM
913 INTEGER :: IPRIME, IG, IMO, JMO, IGO, JGO
914 INTEGER :: ISCAN, JSCAN, NSCAN
915 INTEGER :: ISCANO, JSCANO, NSCANO
916 INTEGER :: ISCALE, IP, IPROJ, JSKIPI, JG
917 INTEGER :: K, MAXWV, N, NI, NJ, NPS
918 !
919 REAL :: DLAT, DLON, DLATO, DLONO, DE, DR, DY
920 REAL :: E2, H, HI, HJ, DUMM(1)
921 REAL :: ORIENT, RERTH, SLAT
922 REAL :: RLAT1, RLON1, RLAT2, RLON2, RLATI
923 REAL :: UROT, VROT, UO2(MO,KM),VO2(MO,KM)
924 REAL :: XMESH, XP, YP, XPTS(MO),YPTS(MO)
925
926 type(grib2_descriptor) :: desc_in, desc_out
927 class(ip_grid), allocatable :: grid_in, grid_out
928
929 desc_in = init_descriptor(igdtnumi, igdtleni, igdtmpli)
930 desc_out = init_descriptor(igdtnumo, igdtleno, igdtmplo)
931
932 call init_grid(grid_in, desc_in)
933 call init_grid(grid_out, desc_out)
934
935 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
936 ! COMPUTE NUMBER OF OUTPUT POINTS AND THEIR LATITUDES AND LONGITUDES.
937 iret=0
938 IF(igdtnumo.GE.0) THEN
939 CALL gdswzd(grid_out, 0,mo,fill,xpts,ypts, &
940 rlon,rlat,no,crot,srot)
941 IF(no.EQ.0) iret=3
942 ENDIF
943 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
944 ! AFFIRM APPROPRIATE INPUT GRID
945 ! LAT/LON OR GAUSSIAN
946 ! NO BITMAPS
947 ! FULL ZONAL COVERAGE
948 ! FULL MERIDIONAL COVERAGE
949 idrti=igdtnumi
950 IF(idrti==40) idrti=4
951 IF(idrti==0.OR.idrti==4)THEN
952 im=igdtmpli(8)
953 jm=igdtmpli(9)
954 iscale=igdtmpli(10)*igdtmpli(11)
955 IF(iscale==0) iscale=10**6
956 rlon1=float(igdtmpli(13))/float(iscale)
957 rlon2=float(igdtmpli(16))/float(iscale)
958 iscan=mod(igdtmpli(19)/128,2)
959 jscan=mod(igdtmpli(19)/64,2)
960 nscan=mod(igdtmpli(19)/32,2)
961 ELSE
962 iret=41
963 ENDIF
964 DO k=1,km
965 IF(ibi(k).NE.0) iret=41
966 ENDDO
967 IF(iret.EQ.0) THEN
968 IF(iscan.EQ.0) THEN
969 dlon=(mod(rlon2-rlon1-1+3600,360.)+1)/(im-1)
970 ELSE
971 dlon=-(mod(rlon1-rlon2-1+3600,360.)+1)/(im-1)
972 ENDIF
973 ig=nint(360/abs(dlon))
974 iprime=1+mod(-nint(rlon1/dlon)+ig,ig)
975 imaxi=ig
976 jmaxi=jm
977 IF(mod(ig,2).NE.0.OR.im.LT.ig) iret=41
978 ENDIF
979 IF(iret.EQ.0.AND.idrti.EQ.0) THEN
980 iscale=igdtmpli(10)*igdtmpli(11)
981 IF(iscale==0) iscale=10**6
982 rlat1=float(igdtmpli(12))/float(iscale)
983 rlat2=float(igdtmpli(15))/float(iscale)
984 dlat=(rlat2-rlat1)/(jm-1)
985 jg=nint(180/abs(dlat))
986 IF(jm.EQ.jg) idrti=256
987 IF(jm.NE.jg.AND.jm.NE.jg+1) iret=41
988 ELSEIF(iret.EQ.0.AND.idrti.EQ.4) THEN
989 jg=igdtmpli(18)*2
990 IF(jm.NE.jg) iret=41
991 ENDIF
992 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
993 ! SET PARAMETERS
994 IF(iret.EQ.0) THEN
995 iromb=ipopt(1)
996 maxwv=ipopt(2)
997 IF(maxwv.EQ.-1) THEN
998 IF(iromb.EQ.0.AND.idrti.EQ.4) maxwv=(jmaxi-1)
999 IF(iromb.EQ.1.AND.idrti.EQ.4) maxwv=(jmaxi-1)/2
1000 IF(iromb.EQ.0.AND.idrti.EQ.0) maxwv=(jmaxi-3)/2
1001 IF(iromb.EQ.1.AND.idrti.EQ.0) maxwv=(jmaxi-3)/4
1002 IF(iromb.EQ.0.AND.idrti.EQ.256) maxwv=(jmaxi-1)/2
1003 IF(iromb.EQ.1.AND.idrti.EQ.256) maxwv=(jmaxi-1)/4
1004 ENDIF
1005 IF((iromb.NE.0.AND.iromb.NE.1).OR.maxwv.LT.0) iret=42
1006 ENDIF
1007 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1008 ! INTERPOLATE
1009 IF(iret.EQ.0) THEN
1010 IF(nscan.EQ.0) THEN
1011 iskipi=1
1012 jskipi=im
1013 ELSE
1014 iskipi=jm
1015 jskipi=1
1016 ENDIF
1017 IF(iscan.EQ.1) iskipi=-iskipi
1018 IF(jscan.EQ.0) jskipi=-jskipi
1019 ispec=0
1020 ! SPECIAL CASE OF GLOBAL CYLINDRICAL GRID
1021 IF((igdtnumo.EQ.0.OR.igdtnumo.EQ.40).AND. &
1022 mod(igdtmplo(8),2).EQ.0.AND.igdtmplo(13).EQ.0.AND. &
1023 igdtmplo(19).EQ.0) THEN
1024 idrto=igdtnumo
1025 IF(idrto==40)idrto=4
1026 imo=igdtmplo(8)
1027 jmo=igdtmplo(9)
1028 iscale=igdtmplo(10)*igdtmplo(11)
1029 IF(iscale==0) iscale=10**6
1030 rlon2=float(igdtmplo(16))/float(iscale)
1031 dlono=(mod(rlon2-1+3600,360.)+1)/(imo-1)
1032 igo=nint(360/abs(dlono))
1033 IF(imo.EQ.igo.AND.idrto.EQ.0) THEN
1034 rlat1=float(igdtmplo(12))/float(iscale)
1035 rlat2=float(igdtmplo(15))/float(iscale)
1036 dlat=(rlat2-rlat1)/(jmo-1)
1037 jgo=nint(180/abs(dlat))
1038 IF(jmo.EQ.jgo) idrto=256
1039 IF(jmo.EQ.jgo.OR.jmo.EQ.jgo+1) ispec=1
1040 ELSEIF(imo.EQ.igo.AND.idrto.EQ.4) THEN
1041 jgo=igdtmplo(18)*2
1042 IF(jmo.EQ.jgo) ispec=1
1043 ENDIF
1044 IF(ispec.EQ.1) THEN
1045 CALL sptrunv(iromb,maxwv,idrti,imaxi,jmaxi,idrto,imo,jmo, &
1046 km,iprime,iskipi,jskipi,mi,0,0,mo,0,ui,vi, &
1047 .true.,uo,vo,.false.,dumm,dumm,.false.,dumm,dumm)
1048 ENDIF
1049 ! SPECIAL CASE OF POLAR STEREOGRAPHIC GRID
1050 ELSEIF(igdtnumo.EQ.20.AND. &
1051 igdtmplo(8).EQ.igdtmplo(9).AND.mod(igdtmplo(8),2).EQ.1.AND. &
1052 igdtmplo(15).EQ.igdtmplo(16).AND.igdtmplo(18).EQ.64.AND. &
1053 mod(igdtmplo(12)/8,2).EQ.1) THEN
1054 nps=igdtmplo(8)
1055 rlat1=float(igdtmplo(10))*1.e-6
1056 rlon1=float(igdtmplo(11))*1.e-6
1057 orient=float(igdtmplo(14))*1.e-6
1058 xmesh=float(igdtmplo(15))*1.e-3
1059 iproj=mod(igdtmplo(17)/128,2)
1060 ip=(nps+1)/2
1061 h=(-1.)**iproj
1062 slat=float(abs(igdtmplo(13)))*1.e-6
1063 CALL earth_radius(igdtmplo,igdtleno,rerth,e2)
1064 de=(1.+sin(slat/dpr))*rerth
1065 dr=de*cos(rlat1/dpr)/(1+h*sin(rlat1/dpr))
1066 xp=1-h*sin((rlon1-orient)/dpr)*dr/xmesh
1067 yp=1+cos((rlon1-orient)/dpr)*dr/xmesh
1068 IF(nint(xp).EQ.ip.AND.nint(yp).EQ.ip) THEN
1069 IF(iproj.EQ.0) THEN
1070 CALL sptrunsv(iromb,maxwv,idrti,imaxi,jmaxi,km,nps, &
1071 iprime,iskipi,jskipi,mi,mo,0,0,0, &
1072 slat,xmesh,orient,ui,vi,.true.,uo,vo,uo2,vo2, &
1073 .false.,dumm,dumm,dumm,dumm, &
1074 .false.,dumm,dumm,dumm,dumm)
1075 ELSE
1076 CALL sptrunsv(iromb,maxwv,idrti,imaxi,jmaxi,km,nps, &
1077 iprime,iskipi,jskipi,mi,mo,0,0,0, &
1078 slat,xmesh,orient,ui,vi,.true.,uo2,vo2,uo,vo, &
1079 .false.,dumm,dumm,dumm,dumm, &
1080 .false.,dumm,dumm,dumm,dumm)
1081 ENDIF
1082 ispec=1
1083 ENDIF
1084 ! SPECIAL CASE OF MERCATOR GRID
1085 ELSEIF(igdtnumo.EQ.10) THEN
1086 ni=igdtmplo(8)
1087 nj=igdtmplo(9)
1088 rlat1=float(igdtmplo(10))*1.0e-6
1089 rlon1=float(igdtmplo(11))*1.0e-6
1090 rlon2=float(igdtmplo(15))*1.0e-6
1091 rlati=float(igdtmplo(13))*1.0e-6
1092 iscano=mod(igdtmplo(16)/128,2)
1093 jscano=mod(igdtmplo(16)/64,2)
1094 nscano=mod(igdtmplo(16)/32,2)
1095 dy=float(igdtmplo(19))*1.0e-3
1096 hi=(-1.)**iscano
1097 hj=(-1.)**(1-jscano)
1098 CALL earth_radius(igdtmplo,igdtleno,rerth,e2)
1099 dlono=hi*(mod(hi*(rlon2-rlon1)-1+3600,360.)+1)/(ni-1)
1100 dlato=hj*dy/(rerth*cos(rlati/dpr))*dpr
1101 IF(nscano.EQ.0) THEN
1102 CALL sptrunmv(iromb,maxwv,idrti,imaxi,jmaxi,km,ni,nj, &
1103 iprime,iskipi,jskipi,mi,mo,0,0,0, &
1104 rlat1,rlon1,dlato,dlono,ui,vi, &
1105 .true.,uo,vo,.false.,dumm,dumm,.false.,dumm,dumm)
1106 ispec=1
1107 ENDIF
1108 ENDIF
1109 ! GENERAL SLOW CASE
1110 IF(ispec.EQ.0) THEN
1111 CALL sptrungv(iromb,maxwv,idrti,imaxi,jmaxi,km,no, &
1112 iprime,iskipi,jskipi,mi,mo,0,0,0,rlat,rlon, &
1113 ui,vi,.true.,uo,vo,.false.,dumm,dumm,.false.,dumm,dumm)
1114 DO k=1,km
1115 ibo(k)=0
1116 DO n=1,no
1117 lo(n,k)=.true.
1118 urot=crot(n)*uo(n,k)-srot(n)*vo(n,k)
1119 vrot=srot(n)*uo(n,k)+crot(n)*vo(n,k)
1120 uo(n,k)=urot
1121 vo(n,k)=vrot
1122 ENDDO
1123 ENDDO
1124 ENDIF
1125 ELSE
1126 DO k=1,km
1127 ibo(k)=1
1128 DO n=1,no
1129 lo(n,k)=.false.
1130 uo(n,k)=0.
1131 vo(n,k)=0.
1132 ENDDO
1133 ENDDO
1134 ENDIF
1135 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1136 END SUBROUTINE polatev4_grib2
1137
1138 !> Interpolate vector fields (spectral).
1139 !>
1140 !> This subprogram performs spectral interpolation from any grid to
1141 !> any grid for vector fields. It requires that the input fields be
1142 !> uniformly global. Options allow choices between triangular shape
1143 !> (ipopt(1)=0) and rhomboidal shape (ipopt(1)=1) which has no
1144 !> default; a second option is the truncation (ipopt(2)) which
1145 !> defaults to a sensible truncation for the input grid (if
1146 !> opt(2)=-1).
1147 !>
1148 !> @note If the output grid is not found in a special list, then the
1149 !> transform back to grid is not very fast. This special list
1150 !> contains global cylindrical grids, polar stereographic grids
1151 !> centered at the pole and mercator grids.
1152 !>
1153 !> Only horizontal interpolation is performed. The grids are defined
1154 !> by their grid description sections (passed in integer form as
1155 !> decoded by subprogram w3fi63).
1156 !>
1157 !> The current code recognizes the following projections:
1158 !> - (KGDS(1)=000) EQUIDISTANT CYLINDRICAL
1159 !> - (KGDS(1)=001) MERCATOR CYLINDRICAL
1160 !> - (KGDS(1)=003) LAMBERT CONFORMAL CONICAL
1161 !> - (KGDS(1)=004) GAUSSIAN CYLINDRICAL (SPECTRAL NATIVE)
1162 !> - (KGDS(1)=005) POLAR STEREOGRAPHIC AZIMUTHAL
1163 !> - (KGDS(1)=203) ROTATED EQUIDISTANT CYLINDRICAL (E-STAGGER)
1164 !> - (KGDS(1)=205) ROTATED EQUIDISTANT CYLINDRICAL (B-STAGGER)
1165 !>
1166 !> Where kgds could be either input kgdsi or output kgdso.
1167 !>
1168 !> The input and output vectors are rotated so that they are either
1169 !> resolved relative to the defined grid in the direction of
1170 !> increasing x and y coordinates or resolved relative to easterly
1171 !> and northerly directions, as designated by their respective grid
1172 !> description sections. As an added bonus the number of output grid
1173 !> points and their latitudes and longitudes are also returned along
1174 !> with their vector rotation parameters. On the other hand, the
1175 !> output can be a set of station points if kgdso(1)<0, in which
1176 !> case the number of points and their latitudes and longitudes must
1177 !> be input along with their vector rotation parameters.
1178 !>
1179 !> Output bitmaps will only be created when the output grid extends
1180 !> outside of the domain of the input grid. The output field is set
1181 !> to 0 where the output bitmap is off.
1182 !>
1183 !> ### Program History Log
1184 !> Date | Programmer | Comments
1185 !> -----|------------|---------
1186 !> 96-04-10 | iredell | initial.
1187 !> 2001-06-18 | iredell | improve detection of special fast transform
1188 !> 2015-01-27 | gayno | replace calls to gdswiz() with new merged routine gdswzd().
1189 !>
1190 !> @param[in] ipopt (20) interpolation options ipopt(1)=0 for
1191 !> triangular, ipopt(1)=1 for rhomboidal; ipopt(2) is truncation
1192 !> number (defaults to sensible if ipopt(2)=-1).
1193 !> @param[in] kgdsi (200) input gds parameters as decoded by w3fi63.
1194 !> @param[in] kgdso (200) output gds parameters (kgdso(1)<0 implies
1195 !> random station points).
1196 !> @param[in] mi skip number between input grid fields if km>1 or
1197 !> dimension of input grid fields if km=1.
1198 !> @param[in] mo skip number between output grid fields if km>1 or
1199 !> dimension of output grid fields if km=1.
1200 !> @param[in] km number of fields to interpolate
1201 !> @param[in] ibi (km) input bitmap flags (must be all 0)
1202 !> @param[in] ui (mi,km) input u-component fields to interpolate
1203 !> @param[in] vi (mi,km) input v-component fields to interpolate
1204 !> @param[out] no number of output points (only if kgdso(1)<0)
1205 !> @param[out] rlat (no) output latitudes in degrees (if kgdso(1)<0)
1206 !> @param[out] rlon (no) output longitudes in degrees (if kgdso(1)<0)
1207 !> @param[out] crot (no) vector rotation cosines (if kgdso(1)<0)
1208 !> @param[out] srot (no) vector rotation sines (if kgdso(1)<0)
1209 !> (ugrid=crot*uearth-srot*vearth; vgrid=srot*uearth+crot*vearth)
1210 !> @param[out] ibo (km) output bitmap flags
1211 !> @param[out] lo (mo,km) output bitmaps (always output)
1212 !> @param[out] uo (mo,km) output u-component fields interpolated
1213 !> @param[out] vo (mo,km) output v-component fields interpolated
1214 !> @param[out] iret return code
1215 !> - 0 successful interpolation
1216 !> - 2 unrecognized input grid or no grid overlap
1217 !> - 3 unrecognized output grid
1218 !> - 41 invalid nonglobal input grid
1219 !> - 42 invalid spectral method parameters
1220 !>
1221 !> @author IREDELL @date 96-04-10
1222 SUBROUTINE polatev4_grib1(IPOPT,KGDSI,KGDSO,MI,MO,KM,IBI,UI,VI, &
1223 NO,RLAT,RLON,CROT,SROT,IBO,LO,UO,VO,IRET)
1224 INTEGER, INTENT(IN ) :: IPOPT(20), IBI(KM)
1225 INTEGER, INTENT(IN ) :: KM, MI, MO
1226 INTEGER, INTENT( OUT) :: IRET, IBO(KM)
1227 INTEGER, INTENT(IN) :: KGDSI(200),KGDSO(200)
1228 !
1229 LOGICAL*1, INTENT( OUT) :: LO(MO,KM)
1230 !
1231 REAL, INTENT(IN ) :: UI(MI,KM),VI(MI,KM)
1232 REAL, INTENT( OUT) :: UO(MO,KM),VO(MO,KM)
1233 REAL, INTENT(INOUT) :: RLAT(MO),RLON(MO)
1234 REAL, INTENT( OUT) :: CROT(MO),SROT(MO)
1235 !
1236 REAL, PARAMETER :: FILL=-9999.
1237 REAL, PARAMETER :: RERTH=6.3712e6
1238 REAL, PARAMETER :: PI=3.14159265358979
1239 REAL, PARAMETER :: DPR=180./pi
1240 !
1241 INTEGER :: IDRTO, IROMB, ISKIPI, ISPEC
1242 INTEGER :: IDRTI, IMAXI, JMAXI, IM, JM
1243 INTEGER :: IPRIME, IG, IMO, JMO, IGO, JGO
1244 INTEGER :: ISCAN, JSCAN, NSCAN
1245 INTEGER :: ISCANO, JSCANO, NSCANO
1246 INTEGER :: IP, IPROJ, JSKIPI, JG
1247 INTEGER :: K, MAXWV, N, NI, NJ, NO, NPS
1248 !
1249 REAL :: DLAT, DLON, DLATO, DLONO, DE, DR, DY
1250 REAL :: H, HI, HJ, DUMM(1)
1251 REAL :: ORIENT
1252 REAL :: RLAT1, RLON1, RLAT2, RLON2, RLATI
1253 REAL :: UROT, VROT, UO2(MO,KM),VO2(MO,KM)
1254 REAL :: XMESH, XP, YP, XPTS(MO),YPTS(MO)
1255
1256 type(grib1_descriptor) :: desc_in, desc_out
1257 class(ip_grid), allocatable :: grid_in, grid_out
1258
1259 desc_in = init_descriptor(kgdsi)
1260 desc_out = init_descriptor(kgdso)
1261
1262 call init_grid(grid_in, desc_in)
1263 call init_grid(grid_out, desc_out)
1264 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1265 ! COMPUTE NUMBER OF OUTPUT POINTS AND THEIR LATITUDES AND LONGITUDES.
1266 iret=0
1267 IF(kgdso(1).GE.0) THEN
1268 CALL gdswzd(grid_out, 0,mo,fill,xpts,ypts,rlon,rlat,no,crot,srot)
1269 IF(no.EQ.0) iret=3
1270 ENDIF
1271 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1272 ! AFFIRM APPROPRIATE INPUT GRID
1273 ! LAT/LON OR GAUSSIAN
1274 ! NO BITMAPS
1275 ! FULL ZONAL COVERAGE
1276 ! FULL MERIDIONAL COVERAGE
1277 idrti=kgdsi(1)
1278 im=kgdsi(2)
1279 jm=kgdsi(3)
1280 rlon1=kgdsi(5)*1.e-3
1281 rlon2=kgdsi(8)*1.e-3
1282 iscan=mod(kgdsi(11)/128,2)
1283 jscan=mod(kgdsi(11)/64,2)
1284 nscan=mod(kgdsi(11)/32,2)
1285 IF(idrti.NE.0.AND.idrti.NE.4) iret=41
1286 DO k=1,km
1287 IF(ibi(k).NE.0) iret=41
1288 ENDDO
1289 IF(iret.EQ.0) THEN
1290 IF(iscan.EQ.0) THEN
1291 dlon=(mod(rlon2-rlon1-1+3600,360.)+1)/(im-1)
1292 ELSE
1293 dlon=-(mod(rlon1-rlon2-1+3600,360.)+1)/(im-1)
1294 ENDIF
1295 ig=nint(360/abs(dlon))
1296 iprime=1+mod(-nint(rlon1/dlon)+ig,ig)
1297 imaxi=ig
1298 jmaxi=jm
1299 IF(mod(ig,2).NE.0.OR.im.LT.ig) iret=41
1300 ENDIF
1301 IF(iret.EQ.0.AND.idrti.EQ.0) THEN
1302 rlat1=kgdsi(4)*1.e-3
1303 rlat2=kgdsi(7)*1.e-3
1304 dlat=(rlat2-rlat1)/(jm-1)
1305 jg=nint(180/abs(dlat))
1306 IF(jm.EQ.jg) idrti=256
1307 IF(jm.NE.jg.AND.jm.NE.jg+1) iret=41
1308 ELSEIF(iret.EQ.0.AND.idrti.EQ.4) THEN
1309 jg=kgdsi(10)*2
1310 IF(jm.NE.jg) iret=41
1311 ENDIF
1312 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1313 ! SET PARAMETERS
1314 IF(iret.EQ.0) THEN
1315 iromb=ipopt(1)
1316 maxwv=ipopt(2)
1317 IF(maxwv.EQ.-1) THEN
1318 IF(iromb.EQ.0.AND.idrti.EQ.4) maxwv=(jmaxi-1)
1319 IF(iromb.EQ.1.AND.idrti.EQ.4) maxwv=(jmaxi-1)/2
1320 IF(iromb.EQ.0.AND.idrti.EQ.0) maxwv=(jmaxi-3)/2
1321 IF(iromb.EQ.1.AND.idrti.EQ.0) maxwv=(jmaxi-3)/4
1322 IF(iromb.EQ.0.AND.idrti.EQ.256) maxwv=(jmaxi-1)/2
1323 IF(iromb.EQ.1.AND.idrti.EQ.256) maxwv=(jmaxi-1)/4
1324 ENDIF
1325 IF((iromb.NE.0.AND.iromb.NE.1).OR.maxwv.LT.0) iret=42
1326 ENDIF
1327 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1328 ! INTERPOLATE
1329 IF(iret.EQ.0) THEN
1330 IF(nscan.EQ.0) THEN
1331 iskipi=1
1332 jskipi=im
1333 ELSE
1334 iskipi=jm
1335 jskipi=1
1336 ENDIF
1337 IF(iscan.EQ.1) iskipi=-iskipi
1338 IF(jscan.EQ.0) jskipi=-jskipi
1339 ispec=0
1340 ! SPECIAL CASE OF GLOBAL CYLINDRICAL GRID
1341 IF((kgdso(1).EQ.0.OR.kgdso(1).EQ.4).AND. &
1342 mod(kgdso(2),2).EQ.0.AND.kgdso(5).EQ.0.AND. &
1343 kgdso(11).EQ.0) THEN
1344 idrto=kgdso(1)
1345 imo=kgdso(2)
1346 jmo=kgdso(3)
1347 rlon2=kgdso(8)*1.e-3
1348 dlono=(mod(rlon2-1+3600,360.)+1)/(imo-1)
1349 igo=nint(360/abs(dlono))
1350 IF(imo.EQ.igo.AND.idrto.EQ.0) THEN
1351 rlat1=kgdso(4)*1.e-3
1352 rlat2=kgdso(7)*1.e-3
1353 dlat=(rlat2-rlat1)/(jmo-1)
1354 jgo=nint(180/abs(dlat))
1355 IF(jmo.EQ.jgo) idrto=256
1356 IF(jmo.EQ.jgo.OR.jmo.EQ.jgo+1) ispec=1
1357 ELSEIF(imo.EQ.igo.AND.idrto.EQ.4) THEN
1358 jgo=kgdso(10)*2
1359 IF(jmo.EQ.jgo) ispec=1
1360 ENDIF
1361 IF(ispec.EQ.1) THEN
1362 CALL sptrunv(iromb,maxwv,idrti,imaxi,jmaxi,idrto,imo,jmo, &
1363 km,iprime,iskipi,jskipi,mi,0,0,mo,0,ui,vi, &
1364 .true.,uo,vo,.false.,dumm,dumm,.false.,dumm,dumm)
1365 ENDIF
1366 ! SPECIAL CASE OF POLAR STEREOGRAPHIC GRID
1367 ELSEIF(kgdso(1).EQ.5.AND. &
1368 kgdso(2).EQ.kgdso(3).AND.mod(kgdso(2),2).EQ.1.AND. &
1369 kgdso(8).EQ.kgdso(9).AND.kgdso(11).EQ.64.AND. &
1370 mod(kgdso(6)/8,2).EQ.1) THEN
1371 nps=kgdso(2)
1372 rlat1=kgdso(4)*1.e-3
1373 rlon1=kgdso(5)*1.e-3
1374 orient=kgdso(7)*1.e-3
1375 xmesh=kgdso(8)
1376 iproj=mod(kgdso(10)/128,2)
1377 ip=(nps+1)/2
1378 h=(-1.)**iproj
1379 de=(1.+sin(60./dpr))*rerth
1380 dr=de*cos(rlat1/dpr)/(1+h*sin(rlat1/dpr))
1381 xp=1-h*sin((rlon1-orient)/dpr)*dr/xmesh
1382 yp=1+cos((rlon1-orient)/dpr)*dr/xmesh
1383 IF(nint(xp).EQ.ip.AND.nint(yp).EQ.ip) THEN
1384 IF(iproj.EQ.0) THEN
1385 CALL sptrunsv(iromb,maxwv,idrti,imaxi,jmaxi,km,nps, &
1386 iprime,iskipi,jskipi,mi,mo,0,0,0, &
1387 60.,xmesh,orient,ui,vi,.true.,uo,vo,uo2,vo2, &
1388 .false.,dumm,dumm,dumm,dumm, &
1389 .false.,dumm,dumm,dumm,dumm)
1390 ELSE
1391 CALL sptrunsv(iromb,maxwv,idrti,imaxi,jmaxi,km,nps, &
1392 iprime,iskipi,jskipi,mi,mo,0,0,0, &
1393 60.,xmesh,orient,ui,vi,.true.,uo2,vo2,uo,vo, &
1394 .false.,dumm,dumm,dumm,dumm, &
1395 .false.,dumm,dumm,dumm,dumm)
1396 ENDIF
1397 ispec=1
1398 ENDIF
1399 ! SPECIAL CASE OF MERCATOR GRID
1400 ELSEIF(kgdso(1).EQ.1) THEN
1401 ni=kgdso(2)
1402 nj=kgdso(3)
1403 rlat1=kgdso(4)*1.e-3
1404 rlon1=kgdso(5)*1.e-3
1405 rlon2=kgdso(8)*1.e-3
1406 rlati=kgdso(9)*1.e-3
1407 iscano=mod(kgdso(11)/128,2)
1408 jscano=mod(kgdso(11)/64,2)
1409 nscano=mod(kgdso(11)/32,2)
1410 dy=kgdso(13)
1411 hi=(-1.)**iscano
1412 hj=(-1.)**(1-jscano)
1413 dlono=hi*(mod(hi*(rlon2-rlon1)-1+3600,360.)+1)/(ni-1)
1414 dlato=hj*dy/(rerth*cos(rlati/dpr))*dpr
1415 IF(nscano.EQ.0) THEN
1416 CALL sptrunmv(iromb,maxwv,idrti,imaxi,jmaxi,km,ni,nj, &
1417 iprime,iskipi,jskipi,mi,mo,0,0,0, &
1418 rlat1,rlon1,dlato,dlono,ui,vi, &
1419 .true.,uo,vo,.false.,dumm,dumm,.false.,dumm,dumm)
1420 ispec=1
1421 ENDIF
1422 ENDIF
1423 ! GENERAL SLOW CASE
1424 IF(ispec.EQ.0) THEN
1425 CALL sptrungv(iromb,maxwv,idrti,imaxi,jmaxi,km,no, &
1426 iprime,iskipi,jskipi,mi,mo,0,0,0,rlat,rlon, &
1427 ui,vi,.true.,uo,vo,.false.,dumm,dumm,.false.,dumm,dumm)
1428 DO k=1,km
1429 ibo(k)=0
1430 DO n=1,no
1431 lo(n,k)=.true.
1432 urot=crot(n)*uo(n,k)-srot(n)*vo(n,k)
1433 vrot=srot(n)*uo(n,k)+crot(n)*vo(n,k)
1434 uo(n,k)=urot
1435 vo(n,k)=vrot
1436 ENDDO
1437 ENDDO
1438 ENDIF
1439 ELSE
1440 DO k=1,km
1441 ibo(k)=1
1442 DO n=1,no
1443 lo(n,k)=.false.
1444 uo(n,k)=0.
1445 vo(n,k)=0.
1446 ENDDO
1447 ENDDO
1448 ENDIF
1449 END SUBROUTINE polatev4_grib1
1450end module spectral_interp_mod
Determine earth radius and shape.
subroutine, public earth_radius(igdtmpl, igdtlen, radius, eccen_squared)
Determine earth radius and shape.
Driver module for gdswzd routines.
Users derived type grid descriptor objects to abstract away the raw GRIB1 and GRIB2 grid definitions.
Routines for creating an ip_grid given a Grib descriptor.
Abstract ip_grid type.
Interpolate spectral.
subroutine polates4_grib1(ipopt, kgdsi, kgdso, mi, mo, km, ibi, gi, no, rlat, rlon, ibo, lo, go, iret)
Interpolate scalar fields (spectral).
subroutine polatev4_grib1(ipopt, kgdsi, kgdso, mi, mo, km, ibi, ui, vi, no, rlat, rlon, crot, srot, ibo, lo, uo, vo, iret)
Interpolate vector fields (spectral).
subroutine interpolate_spectral_scalar(ipopt, grid_in, grid_out, mi, mo, km, ibi, gi, no, rlat, rlon, ibo, lo, go, iret)
Interpolate spectral scalar.
subroutine polates4_grib2(ipopt, igdtnumi, igdtmpli, igdtleni, igdtnumo, igdtmplo, igdtleno, mi, mo, km, ibi, gi, no, rlat, rlon, ibo, lo, go, iret)
Interpolate scalar fields (spectral).
subroutine interpolate_spectral_vector(ipopt, grid_in, grid_out, mi, mo, km, ibi, ui, vi, no, rlat, rlon, crot, srot, ibo, lo, uo, vo, iret)
Interpolate spectral vector.
subroutine polatev4_grib2(ipopt, igdtnumi, igdtmpli, igdtleni, igdtnumo, igdtmplo, igdtleno, mi, mo, km, ibi, ui, vi, no, rlat, rlon, crot, srot, ibo, lo, uo, vo, iret)
Interpolate vector fields (spectral).
subroutine sptrun(iromb, maxwv, idrti, imaxi, jmaxi, idrto, imaxo, jmaxo, kmax, iprime, iskipi, jskipi, kskipi, iskipo, jskipo, kskipo, jcpu, gridi, grido)
This subprogram spectrally truncates scalar fields on a global cylindrical grid, returning the fields...
Definition sptrun.f:58
subroutine sptrung(iromb, maxwv, idrti, imaxi, jmaxi, kmax, nmax, iprime, iskipi, jskipi, kskipi, kgskip, nrskip, ngskip, jcpu, rlat, rlon, gridi, gp)
This subprogram spectrally truncates scalar fields on a global cylindrical grid, returning the fields...
Definition sptrung.f:68
subroutine sptrungv(iromb, maxwv, idrti, imaxi, jmaxi, kmax, nmax, iprime, iskipi, jskipi, kskipi, kgskip, nrskip, ngskip, jcpu, rlat, rlon, gridui, gridvi, luv, up, vp, ldz, dp, zp, lps, pp, sp)
THIS SUBPROGRAM SPECTRALLY TRUNCATES VECTORS FIELDS ON A GLOBAL CYLINDRICAL GRID, RETURNING THE FIELD...
Definition sptrungv.f:85
subroutine sptrunm(iromb, maxwv, idrti, imaxi, jmaxi, kmax, mi, mj, iprime, iskipi, jskipi, kskipi, kgskip, niskip, njskip, jcpu, rlat1, rlon1, dlat, dlon, gridi, gm)
This subprogram spectrally truncates scalar fields on a global cylindrical grid, returning the fields...
Definition sptrunm.f:80
subroutine sptrunmv(iromb, maxwv, idrti, imaxi, jmaxi, kmax, mi, mj, iprime, iskipi, jskipi, kskipi, kgskip, niskip, njskip, jcpu, rlat1, rlon1, dlat, dlon, gridui, gridvi, luv, um, vm, ldz, dm, zm, lps, pm, sm)
THIS SUBPROGRAM SPECTRALLY TRUNCATES VECTOR FIELDS ON A GLOBAL CYLINDRICAL GRID, RETURNING THE FIELDS...
Definition sptrunmv.f:96
subroutine sptruns(iromb, maxwv, idrti, imaxi, jmaxi, kmax, nps, iprime, iskipi, jskipi, kskipi, kgskip, niskip, njskip, jcpu, true, xmesh, orient, gridi, gn, gs)
This subprogram spectrally truncates scalar fields on a global cylindrical grid, returning the fields...
Definition sptruns.f:75
subroutine sptrunsv(iromb, maxwv, idrti, imaxi, jmaxi, kmax, nps, iprime, iskipi, jskipi, kskipi, kgskip, niskip, njskip, jcpu, true, xmesh, orient, gridui, gridvi, luv, un, vn, us, vs, ldz, dn, zn, ds, zs, lps, pn, sn, ps, ss)
This subprogram spectrally truncates vector fields on a global cylindrical grid, returning the fields...
Definition sptrunsv.f:94
subroutine sptrunv(iromb, maxwv, idrti, imaxi, jmaxi, idrto, imaxo, jmaxo, kmax, iprime, iskipi, jskipi, kskipi, iskipo, jskipo, kskipo, jcpu, gridui, gridvi, luv, griduo, gridvo, ldz, griddo, gridzo, lps, gridpo, gridso)
This subprogram spectrally truncates vector fields on a global cylindrical grid, returning the fields...
Definition sptrunv.f:96
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 grid that holds fields and methods common to all grids.