NCEPLIBS-ip 4.0.0
ip_polar_stereo_grid_mod.f90
1module ip_polar_stereo_grid_mod
5 use earth_radius_mod
6 implicit none
7
8 private
10
11 type, extends(ip_grid) :: ip_polar_stereo_grid
12 logical :: elliptical
13 real :: rlat1, rlon1, orient, h, dxs, dys, slatr
14 integer :: irot
15 contains
16 procedure :: init_grib1
17 procedure :: init_grib2
18 procedure :: gdswzd => gdswzd_polar_stereo
20
21 INTEGER :: IROT
22
23 REAL :: DE2, DXS, DYS
24 REAL :: E2, RERTH , H, ORIENT
25
26CONTAINS
27
28 subroutine init_grib1(self, g1_desc)
29 class(ip_polar_stereo_grid), intent(inout) :: self
30 type(grib1_descriptor), intent(in) :: g1_desc
31
32 REAL, PARAMETER :: SLAT=60.0 ! standard latitude according grib1 standard
33
34 real :: dx, dy, hi, hj
35 integer :: iproj, iscan, jscan
36
37 associate(kgds => g1_desc%gds)
38 self%ELLIPTICAL=mod(kgds(6)/64,2).EQ.1
39
40 if (.not. self%elliptical) then
41 self%rerth = 6.3712e6
42 self%eccen_squared = 0d0
43 else
44 self%rerth = rerth_wgs84
45 self%eccen_squared = e2_wgs84 !wgs84 datum
46 end if
47
48 self%IM=kgds(2)
49 self%JM=kgds(3)
50
51 self%RLAT1=kgds(4)*1.e-3
52 self%RLON1=kgds(5)*1.e-3
53
54 self%IROT=mod(kgds(6)/8,2)
55
56 self%SLATR=slat/dpr
57
58 self%ORIENT=kgds(7)*1.e-3
59
60 dx=kgds(8)
61 dy=kgds(9)
62
63 iproj=mod(kgds(10)/128,2)
64 iscan=mod(kgds(11)/128,2)
65 jscan=mod(kgds(11)/64,2)
66
67 self%H=(-1.)**iproj
68 hi=(-1.)**iscan
69 hj=(-1.)**(1-jscan)
70
71 IF(self%H.EQ.-1)self%ORIENT=self%ORIENT+180.
72
73 self%DXS=dx*hi
74 self%DYS=dy*hj
75
76 self%iwrap= 0
77 self%jwrap1 = 0
78 self%jwrap2 = 0
79 self%nscan = mod(kgds(11) / 32, 2)
80 self%nscan_field_pos = self%nscan
81 self%kscan = 0
82 end associate
83
84 end subroutine init_grib1
85
86 subroutine init_grib2(self, g2_desc)
87 class(ip_polar_stereo_grid), intent(inout) :: self
88 type(grib2_descriptor), intent(in) :: g2_desc
89
90 real :: slat, dx, dy, hi, hj
91 integer :: iproj, iscan, jscan
92
93 associate(igdtmpl => g2_desc%gdt_tmpl, igdtlen => g2_desc%gdt_len)
94 call earth_radius(igdtmpl, igdtlen, self%rerth, self%eccen_squared)
95
96 self%ELLIPTICAL = self%eccen_squared > 0.0
97
98 self%IM=igdtmpl(8)
99 self%JM=igdtmpl(9)
100
101 self%RLAT1=float(igdtmpl(10))*1.e-6
102 self%RLON1=float(igdtmpl(11))*1.e-6
103
104 self%IROT=mod(igdtmpl(12)/8,2)
105
106 slat=float(abs(igdtmpl(13)))*1.e-6
107 self%SLATR=slat/dpr
108
109 self%ORIENT=float(igdtmpl(14))*1.e-6
110
111 dx=float(igdtmpl(15))*1.e-3
112 dy=float(igdtmpl(16))*1.e-3
113
114 iproj=mod(igdtmpl(17)/128,2)
115 iscan=mod(igdtmpl(18)/128,2)
116 jscan=mod(igdtmpl(18)/64,2)
117
118 self%H=(-1.)**iproj
119 hi=(-1.)**iscan
120 hj=(-1.)**(1-jscan)
121
122 self%DXS=dx*hi
123 self%DYS=dy*hj
124
125 self%nscan = mod(igdtmpl(18) / 32, 2)
126 self%nscan_field_pos = self%nscan
127 self%iwrap = 0
128 self%jwrap1 = 0
129 self%jwrap2 = 0
130 self%kscan = 0
131 end associate
132 end subroutine init_grib2
133
134
135 SUBROUTINE gdswzd_polar_stereo(self,IOPT,NPTS, &
136 FILL,XPTS,YPTS,RLON,RLAT,NRET, &
137 CROT,SROT,XLON,XLAT,YLON,YLAT,AREA)
138 !$$$ SUBPROGRAM DOCUMENTATION BLOCK
139 !
140 ! SUBPROGRAM: GDSWZD_POLAR_STEREO GDS WIZARD FOR POLAR STEREOGRAPHIC
141 ! AZIMUTHAL
142 ! PRGMMR: IREDELL ORG: W/NMC23 DATE: 96-04-10
143 !
144 ! ABSTRACT: THIS SUBPROGRAM DECODES THE GRIB 2 GRID DEFINITION
145 ! TEMPLATE (PASSED IN INTEGER FORM AS DECODED BY THE
146 ! NCEP G2 LIBRARY) AND RETURNS ONE OF THE FOLLOWING:
147 ! (IOPT=+1) EARTH COORDINATES OF SELECTED GRID COORDINATES
148 ! (IOPT=-1) GRID COORDINATES OF SELECTED EARTH COORDINATES
149 ! WORKS FOR POLAR STEREOGRAPHIC AZIMUTHAL PROJECTIONS.
150 ! IF THE SELECTED COORDINATES ARE MORE THAN ONE GRIDPOINT
151 ! BEYOND THE THE EDGES OF THE GRID DOMAIN, THEN THE RELEVANT
152 ! OUTPUT ELEMENTS ARE SET TO FILL VALUES.
153 ! THE ACTUAL NUMBER OF VALID POINTS COMPUTED IS RETURNED TOO.
154 ! OPTIONALLY, THE VECTOR ROTATIONS, MAP JACOBIANS, AND
155 ! GRID BOX AREAS MAY BE RETURNED AS WELL. ROUTINE WORKS
156 ! FOR BOTH SPHERICAL AND ELLIPTICAL EARTHS WITH THE
157 ! EXCEPTION OF THE MAP JACOBIANS AND GRID BOX AREAS, WHICH
158 ! ARE ONLY COMPUTED FOR SPHERICAL EARTHS. TO COMPUTE
159 ! THE VECTOR ROTATIONS, THE OPTIONAL ARGUMENTS 'SROT' AND 'CROT'
160 ! MUST BE PRESENT. TO COMPUTE THE MAP JACOBIANS, THE
161 ! OPTIONAL ARGUMENTS 'XLON', 'XLAT', 'YLON', 'YLAT' MUST BE PRESENT.
162 ! TO COMPUTE THE GRID BOX AREAS, THE OPTIONAL ARGUMENT
163 ! 'AREA' MUST BE PRESENT.
164 !
165 ! PROGRAM HISTORY LOG:
166 ! 96-04-10 IREDELL
167 ! 97-10-20 IREDELL INCLUDE MAP OPTIONS
168 ! 09-05-13 GAYNO ENSURE AREA ALWAYS POSITIVE
169 ! 2015-01-21 GAYNO MERGER OF GDSWIZ05 AND GDSWZD05. MAKE
170 ! CROT,SORT,XLON,XLAT,YLON,YLAT AND AREA
171 ! OPTIONAL ARGUMENTS. MAKE PART OF A MODULE.
172 ! MOVE VECTOR ROTATION, MAP JACOBIAN AND GRID
173 ! BOX AREA COMPUTATIONS TO SEPARATE SUBROUTINES.
174 ! INCLUDE OPTION FOR ELLIPTICAL EARTHS.
175 ! 2015-07-13 GAYNO CONVERT TO GRIB 2. REPLACE GRIB 1 KGDS ARRAY
176 ! WITH GRIB 2 GRID DEFINITION TEMPLATE ARRAY.
177 ! RENAME ROUTINE AS "GDSWZD_POLAR_STEREO".
178 ! 2018-07-20 WESLEY ADD THREADING.
179 !
180 ! USAGE: CALL GDSWZD_POLAR_STEREO(IGDTNUM,IGDTMPL,IGDTLEN,IOPT,NPTS,
181 ! & FILL,XPTS,YPTS,RLON,RLAT,NRET,
182 ! & CROT,SROT,XLON,XLAT,YLON,YLAT,AREA)
183 !
184 ! INPUT ARGUMENT LIST:
185 ! IGDTNUM - INTEGER GRID DEFINITION TEMPLATE NUMBER.
186 ! CORRESPONDS TO THE GFLD%IGDTNUM COMPONENT OF THE
187 ! NCEP G2 LIBRARY GRIDMOD DATA STRUCTURE.
188 ! MUST BE "20" FOR POLAR STEREOGRAPHIC GRIDS.
189 ! IGDTMPL - INTEGER (IGDTLEN) GRID DEFINITION TEMPLATE ARRAY.
190 ! CORRESPONDS TO THE GFLD%IGDTMPL COMPONENT OF THE
191 ! NCEP G2 LIBRARY GRIDMOD DATA STRUCTURE FOR SECTION
192 ! THREE:
193 ! (1): SHAPE OF EARTH, OCTET 15
194 ! (2): SCALE FACTOR OF SPHERICAL EARTH RADIUS,
195 ! OCTET 16
196 ! (3): SCALED VALUE OF RADIUS OF SPHERICAL EARTH,
197 ! OCTETS 17-20
198 ! (4): SCALE FACTOR OF MAJOR AXIS OF ELLIPTICAL EARTH,
199 ! OCTET 21
200 ! (5): SCALED VALUE OF MAJOR AXIS OF ELLIPTICAL EARTH,
201 ! OCTETS 22-25
202 ! (6): SCALE FACTOR OF MINOR AXIS OF ELLIPTICAL EARTH,
203 ! OCTET 26
204 ! (7): SCALED VALUE OF MINOR AXIS OF ELLIPTICAL EARTH,
205 ! OCTETS 27-30
206 ! (8): NUMBER OF POINTS ALONG X-AXIS, OCTETS 31-34
207 ! (9): NUMBER OF POINTS ALONG Y-AXIS, OCTETS 35-38
208 ! (10): LATITUDE OF FIRST GRID POINT, OCTETS 39-42
209 ! (11): LONGITUDE OF FIRST GRID POINT, OCTETS 43-46
210 ! (12): RESOLUTION AND COMPONENT FLAGS, OCTET 47
211 ! (13): TRUE LATITUDE, OCTETS 48-51
212 ! (14): ORIENTATION LONGITUDE, OCTETS 52-55
213 ! (15): X-DIRECTION GRID LENGTH, OCTETS 56-59
214 ! (16): Y-DIRECTION GRID LENGTH, OCTETS 60-63
215 ! (17): PROJECTION CENTER FLAG, OCTET 64
216 ! (18): SCANNING MODE FLAGS, OCTET 65
217 ! IGDTLEN - INTEGER NUMBER OF ELEMENTS (18) OF THE GRID DEFINITION
218 ! TEMPLATE ARRAY. CORRESPONDS TO THE GFLD%IGDTLEN
219 ! COMPONENT OF THE NCEP G2 LIBRARY GRIDMOD DATA STRUCTURE.
220 ! IOPT - INTEGER OPTION FLAG
221 ! (+1 TO COMPUTE EARTH COORDS OF SELECTED GRID COORDS)
222 ! (-1 TO COMPUTE GRID COORDS OF SELECTED EARTH COORDS)
223 ! NPTS - INTEGER MAXIMUM NUMBER OF COORDINATES
224 ! FILL - REAL FILL VALUE TO SET INVALID OUTPUT DATA
225 ! (MUST BE IMPOSSIBLE VALUE; SUGGESTED VALUE: -9999.)
226 ! XPTS - REAL (NPTS) GRID X POINT COORDINATES IF IOPT>0
227 ! YPTS - REAL (NPTS) GRID Y POINT COORDINATES IF IOPT>0
228 ! RLON - REAL (NPTS) EARTH LONGITUDES IN DEGREES E IF IOPT<0
229 ! (ACCEPTABLE RANGE: -360. TO 360.)
230 ! RLAT - REAL (NPTS) EARTH LATITUDES IN DEGREES N IF IOPT<0
231 ! (ACCEPTABLE RANGE: -90. TO 90.)
232 !
233 ! OUTPUT ARGUMENT LIST:
234 ! XPTS - REAL (NPTS) GRID X POINT COORDINATES IF IOPT<0
235 ! YPTS - REAL (NPTS) GRID Y POINT COORDINATES IF IOPT<0
236 ! RLON - REAL (NPTS) EARTH LONGITUDES IN DEGREES E IF IOPT>0
237 ! RLAT - REAL (NPTS) EARTH LATITUDES IN DEGREES N IF IOPT>0
238 ! NRET - INTEGER NUMBER OF VALID POINTS COMPUTED
239 ! CROT - REAL, OPTIONAL (NPTS) CLOCKWISE VECTOR ROTATION COSINES
240 ! SROT - REAL, OPTIONAL (NPTS) CLOCKWISE VECTOR ROTATION SINES
241 ! (UGRID=CROT*UEARTH-SROT*VEARTH;
242 ! VGRID=SROT*UEARTH+CROT*VEARTH)
243 ! XLON - REAL, OPTIONAL (NPTS) DX/DLON IN 1/DEGREES
244 ! XLAT - REAL, OPTIONAL (NPTS) DX/DLAT IN 1/DEGREES
245 ! YLON - REAL, OPTIONAL (NPTS) DY/DLON IN 1/DEGREES
246 ! YLAT - REAL, OPTIONAL (NPTS) DY/DLAT IN 1/DEGREES
247 ! AREA - REAL, OPTIONAL (NPTS) AREA WEIGHTS IN M**2
248 ! (PROPORTIONAL TO THE SQUARE OF THE MAP FACTOR)
249 !
250 ! ATTRIBUTES:
251 ! LANGUAGE: FORTRAN 90
252 !
253 !$$$
254 IMPLICIT NONE
255 !
256
257 class(ip_polar_stereo_grid), intent(in) :: self
258 INTEGER, INTENT(IN ) :: IOPT, NPTS
259 INTEGER, INTENT( OUT) :: NRET
260 !
261 REAL, INTENT(IN ) :: FILL
262 REAL, INTENT(INOUT) :: RLON(NPTS),RLAT(NPTS)
263 REAL, INTENT(INOUT) :: XPTS(NPTS),YPTS(NPTS)
264 REAL, OPTIONAL, INTENT( OUT) :: CROT(NPTS),SROT(NPTS)
265 REAL, OPTIONAL, INTENT( OUT) :: XLON(NPTS),XLAT(NPTS)
266 REAL, OPTIONAL, INTENT( OUT) :: YLON(NPTS),YLAT(NPTS),AREA(NPTS)
267 !
268 INTEGER :: IM, JM
269 INTEGER :: ITER, N
270 !
271 LOGICAL :: ELLIPTICAL, LROT, LMAP, LAREA
272 !
273 REAL :: ALAT, ALAT1, ALONG, DIFF
274 REAL :: DI, DJ, DE
275 REAL :: DR, E, E_OVER_2
276 REAL :: MC, SLAT, SLATR
277 REAL :: RLAT1, RLON1, RHO, T, TC
278 REAL :: XMAX, XMIN, YMAX, YMIN
279 REAL :: XP, YP, DR2
280 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
281 IF(PRESENT(crot)) crot=fill
282 IF(PRESENT(srot)) srot=fill
283 IF(PRESENT(xlon)) xlon=fill
284 IF(PRESENT(xlat)) xlat=fill
285 IF(PRESENT(ylon)) ylon=fill
286 IF(PRESENT(ylat)) ylat=fill
287 IF(PRESENT(area)) area=fill
288
289 elliptical = self%elliptical
290 im=self%im
291 jm=self%jm
292
293 rlat1=self%rlat1
294 rlon1=self%rlon1
295
296 irot=self%irot
297 slatr=self%slatr
298 orient=self%orient
299
300 h=self%h
301 dxs=self%dxs
302 dys=self%dys
303
304 rerth = self%rerth
305 e2 = self%eccen_squared
306 !
307 ! FIND X/Y OF POLE
308 IF (.NOT.elliptical) THEN
309 de=(1.+sin(slatr))*rerth
310 dr=de*cos(rlat1/dpr)/(1+h*sin(rlat1/dpr))
311 xp=1-h*sin((rlon1-orient)/dpr)*dr/dxs
312 yp=1+cos((rlon1-orient)/dpr)*dr/dys
313 de2=de**2
314 ELSE
315 e=sqrt(e2)
316 e_over_2=e*0.5
317 alat=h*rlat1/dpr
318 along = (rlon1-orient)/dpr
319 t=tan(pi4-alat/2.)/((1.-e*sin(alat))/ &
320 (1.+e*sin(alat)))**(e_over_2)
321 tc=tan(pi4-slatr/2.)/((1.-e*sin(slatr))/ &
322 (1.+e*sin(slatr)))**(e_over_2)
323 mc=cos(slatr)/sqrt(1.0-e2*(sin(slatr)**2))
324 rho=rerth*mc*t/tc
325 yp = 1.0 + rho*cos(h*along)/dys
326 xp = 1.0 - rho*sin(h*along)/dxs
327 ENDIF ! ELLIPTICAL
328 xmin=0
329 xmax=im+1
330 ymin=0
331 ymax=jm+1
332 nret=0
333 IF(PRESENT(crot).AND.PRESENT(srot))THEN
334 lrot=.true.
335 ELSE
336 lrot=.false.
337 ENDIF
338 IF(PRESENT(xlon).AND.PRESENT(xlat).AND.PRESENT(ylon).AND.PRESENT(ylat))THEN
339 lmap=.true.
340 ELSE
341 lmap=.false.
342 ENDIF
343 IF(PRESENT(area))THEN
344 larea=.true.
345 ELSE
346 larea=.false.
347 ENDIF
348 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
349 ! TRANSLATE GRID COORDINATES TO EARTH COORDINATES
350 IF(iopt.EQ.0.OR.iopt.EQ.1) THEN
351 IF(.NOT.elliptical)THEN
352 !$OMP PARALLEL DO PRIVATE(N,DI,DJ,DR2) REDUCTION(+:NRET) SCHEDULE(STATIC)
353 DO n=1,npts
354 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
355 ypts(n).GE.ymin.AND.ypts(n).LE.ymax) THEN
356 di=(xpts(n)-xp)*dxs
357 dj=(ypts(n)-yp)*dys
358 dr2=di**2+dj**2
359 IF(dr2.LT.de2*1.e-6) THEN
360 rlon(n)=0.
361 rlat(n)=h*90.
362 ELSE
363 rlon(n)=mod(orient+h*dpr*atan2(di,-dj)+3600,360.)
364 rlat(n)=h*dpr*asin((de2-dr2)/(de2+dr2))
365 ENDIF
366 nret=nret+1
367 IF(lrot) CALL polar_stereo_vect_rot(rlon(n),crot(n),srot(n))
368 IF(lmap) CALL polar_stereo_map_jacob(rlon(n),rlat(n),dr2, &
369 xlon(n),xlat(n),ylon(n),ylat(n))
370 IF(larea) CALL polar_stereo_grid_area(rlat(n),dr2,area(n))
371 ELSE
372 rlon(n)=fill
373 rlat(n)=fill
374 ENDIF
375 ENDDO
376 !$OMP END PARALLEL DO
377 ELSE ! ELLIPTICAL
378 !$OMP PARALLEL DO PRIVATE(N,DI,DJ,RHO,T,ALONG,ALAT1,ALAT,DIFF) &
379 !$OMP& REDUCTION(+:NRET) SCHEDULE(STATIC)
380 DO n=1,npts
381 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
382 ypts(n).GE.ymin.AND.ypts(n).LE.ymax) THEN
383 di=(xpts(n)-xp)*dxs
384 dj=(ypts(n)-yp)*dys
385 rho=sqrt(di*di+dj*dj)
386 t=(rho*tc)/(rerth*mc)
387 IF(abs(ypts(n)-yp)<0.01)THEN
388 IF(di>0.0) along=orient+h*90.0
389 IF(di<=0.0) along=orient-h*90.0
390 ELSE
391 along=orient+h*atan(di/(-dj))*dpr
392 IF(dj>0) along=along+180.
393 END IF
394 alat1=pi2-2.0*atan(t)
395 DO iter=1,10
396 alat = pi2 - 2.0*atan(t*(((1.0-e*sin(alat1))/ &
397 (1.0+e*sin(alat1)))**(e_over_2)))
398 diff = abs(alat-alat1)*dpr
399 IF (diff < 0.000001) EXIT
400 alat1=alat
401 ENDDO
402 rlat(n)=h*alat*dpr
403 rlon(n)=along
404 IF(rlon(n)<0.0) rlon(n)=rlon(n)+360.
405 IF(rlon(n)>360.0) rlon(n)=rlon(n)-360.0
406 nret=nret+1
407 IF(lrot) CALL polar_stereo_vect_rot(rlon(n),crot(n),srot(n))
408 ELSE
409 rlon(n)=fill
410 rlat(n)=fill
411 ENDIF
412 ENDDO
413 !$OMP END PARALLEL DO
414 ENDIF ! ELLIPTICAL
415 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
416 ! TRANSLATE EARTH COORDINATES TO GRID COORDINATES
417 ELSEIF(iopt.EQ.-1) THEN
418 IF(.NOT.elliptical)THEN
419 !$OMP PARALLEL DO PRIVATE(N,DR,DR2) REDUCTION(+:NRET) SCHEDULE(STATIC)
420 DO n=1,npts
421 IF(abs(rlon(n)).LE.360.AND.abs(rlat(n)).LE.90.AND. &
422 h*rlat(n).NE.-90) THEN
423 dr=de*tan((90-h*rlat(n))/2/dpr)
424 dr2=dr**2
425 xpts(n)=xp+h*sin((rlon(n)-orient)/dpr)*dr/dxs
426 ypts(n)=yp-cos((rlon(n)-orient)/dpr)*dr/dys
427 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
428 ypts(n).GE.ymin.AND.ypts(n).LE.ymax) THEN
429 nret=nret+1
430 IF(lrot) CALL polar_stereo_vect_rot(rlon(n),crot(n),srot(n))
431 IF(lmap) CALL polar_stereo_map_jacob(rlon(n),rlat(n),dr2, &
432 xlon(n),xlat(n),ylon(n),ylat(n))
433 IF(larea) CALL polar_stereo_grid_area(rlat(n),dr2,area(n))
434 ELSE
435 xpts(n)=fill
436 ypts(n)=fill
437 ENDIF
438 ELSE
439 xpts(n)=fill
440 ypts(n)=fill
441 ENDIF
442 ENDDO
443 !$OMP END PARALLEL DO
444 ELSE ! ELLIPTICAL CASE
445 !$OMP PARALLEL DO PRIVATE(N,ALAT,ALONG,T,RHO) REDUCTION(+:NRET) SCHEDULE(STATIC)
446 DO n=1,npts
447 IF(abs(rlon(n)).LE.360.AND.abs(rlat(n)).LE.90.AND. &
448 h*rlat(n).NE.-90) THEN
449 alat = h*rlat(n)/dpr
450 along = (rlon(n)-orient)/dpr
451 t=tan(pi4-alat*0.5)/((1.-e*sin(alat))/ &
452 (1.+e*sin(alat)))**(e_over_2)
453 rho=rerth*mc*t/tc
454 xpts(n)= xp + rho*sin(h*along) / dxs
455 ypts(n)= yp - rho*cos(h*along) / dys
456 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
457 ypts(n).GE.ymin.AND.ypts(n).LE.ymax) THEN
458 nret=nret+1
459 IF(lrot) CALL polar_stereo_vect_rot(rlon(n),crot(n),srot(n))
460 ELSE
461 xpts(n)=fill
462 ypts(n)=fill
463 ENDIF
464 ELSE
465 xpts(n)=fill
466 ypts(n)=fill
467 ENDIF
468 ENDDO
469 !$OMP END PARALLEL DO
470 ENDIF
471 ENDIF
472 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
473 END SUBROUTINE gdswzd_polar_stereo
474 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
475 SUBROUTINE polar_stereo_error(IOPT,FILL,RLAT,RLON,XPTS,YPTS,NPTS)
476 !$$$ SUBPROGRAM DOCUMENTATION BLOCK
477 !
478 ! SUBPROGRAM: POLAR_STEREO_ERROR ERROR HANDLER
479 ! PRGMMR: GAYNO ORG: W/NMC23 DATE: 2015-07-13
480 !
481 ! ABSTRACT: UPON AN ERROR, THIS SUBPROGRAM ASSIGNS
482 ! A "FILL" VALUE TO THE OUTPUT FIELDS.
483
484 ! PROGRAM HISTORY LOG:
485 ! 2015-07-13 GAYNO INITIAL VERSION
486 !
487 ! USAGE: CALL POLAR_STEREO_ERROR(IOPT,FILL,RLAT,RLON,XPTS,YPTS,NPTS)
488 !
489 ! INPUT ARGUMENT LIST:
490 ! IOPT - INTEGER OPTION FLAG
491 ! (+1 TO COMPUTE EARTH COORDS OF SELECTED GRID COORDS)
492 ! (-1 TO COMPUTE GRID COORDS OF SELECTED EARTH COORDS)
493 ! NPTS - INTEGER MAXIMUM NUMBER OF COORDINATES
494 ! FILL - REAL FILL VALUE TO SET INVALID OUTPUT DATA
495 ! (MUST BE IMPOSSIBLE VALUE; SUGGESTED VALUE: -9999.)
496 ! OUTPUT ARGUMENT LIST:
497 ! RLON - REAL (NPTS) EARTH LONGITUDES IN DEGREES E IF IOPT<0
498 ! RLAT - REAL (NPTS) EARTH LATITUDES IN DEGREES N IF IOPT<0
499 ! XPTS - REAL (NPTS) GRID X POINT COORDINATES IF IOPT>0
500 ! YPTS - REAL (NPTS) GRID Y POINT COORDINATES IF IOPT>0
501 !
502 ! ATTRIBUTES:
503 ! LANGUAGE: FORTRAN 90
504 !
505 !$$$
506 IMPLICIT NONE
507 !
508 INTEGER, INTENT(IN ) :: IOPT, NPTS
509 !
510 REAL, INTENT(IN ) :: FILL
511 REAL, INTENT( OUT) :: RLAT(NPTS),RLON(NPTS)
512 REAL, INTENT( OUT) :: XPTS(NPTS),YPTS(NPTS)
513 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
514 IF(iopt>=0) THEN
515 rlon=fill
516 rlat=fill
517 ENDIF
518 IF(iopt<=0) THEN
519 xpts=fill
520 ypts=fill
521 ENDIF
522 ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
523 END SUBROUTINE polar_stereo_error
524 !
525 SUBROUTINE polar_stereo_vect_rot(RLON, CROT, SROT)
526 !$$$ SUBPROGRAM DOCUMENTATION BLOCK
527 !
528 ! SUBPROGRAM: POLAR_STEREO_VECT_ROT VECTOR ROTATION FIELDS FOR
529 ! POLAR STEREOGRAPHIC GRIDS.
530 !
531 ! PRGMMR: GAYNO ORG: W/NMC23 DATE: 2015-01-21
532 !
533 ! ABSTRACT: THIS SUBPROGRAM COMPUTES THE VECTOR ROTATION SINES AND
534 ! COSINES FOR A POLAR STEREOGRAPHIC AZIMUTHAL GRID.
535 !
536 ! PROGRAM HISTORY LOG:
537 ! 2015-01-21 GAYNO INITIAL VERSION
538 ! 2015-09-17 GAYNO RENAME AS "POLAR_STEREO_VECT_ROT"
539 !
540 ! USAGE: CALL POLAR_STEREO_VECT_ROT(RLON,CROT,SROT)
541 !
542 ! INPUT ARGUMENT LIST:
543 ! RLON - GRID POINT LONGITUDE IN DEGREES (REAL)
544 !
545 ! OUTPUT ARGUMENT LIST:
546 ! CROT - CLOCKWISE VECTOR ROTATION COSINES (REAL)
547 ! SROT - CLOCKWISE VECTOR ROTATION SINES (REAL)
548 ! (UGRID=CROT*UEARTH-SROT*VEARTH;
549 ! VGRID=SROT*UEARTH+CROT*VEARTH)
550 !
551 ! ATTRIBUTES:
552 ! LANGUAGE: FORTRAN 90
553 !
554 !$$$
555 !
556 IMPLICIT NONE
557
558 REAL, INTENT(IN ) :: RLON
559 REAL, INTENT( OUT) :: CROT, SROT
560
561 IF(irot.EQ.1) THEN
562 crot=h*cos((rlon-orient)/dpr)
563 srot=sin((rlon-orient)/dpr)
564 ELSE
565 crot=1.
566 srot=0.
567 ENDIF
568
569 END SUBROUTINE polar_stereo_vect_rot
570 !
571 SUBROUTINE polar_stereo_map_jacob(RLON,RLAT,DR2,XLON,XLAT,YLON,YLAT)
572 !$$$ SUBPROGRAM DOCUMENTATION BLOCK
573 !
574 ! SUBPROGRAM: POLAR_STEREO_MAP_JACOB MAP JACOBIANS FOR
575 ! POLAR STEREOGRAPHIC GRIDS.
576 !
577 ! PRGMMR: GAYNO ORG: W/NMC23 DATE: 2015-01-21
578 !
579 ! ABSTRACT: THIS SUBPROGRAM COMPUTES THE MAP JACOBIANS FOR
580 ! A POLAR STEREOGRAPHIC AZIMUTHAL GRID (SPHERICAL
581 ! EARTH).
582 !
583 ! PROGRAM HISTORY LOG:
584 ! 2015-01-21 GAYNO INITIAL VERSION
585 ! 2015-09-17 GAYNO RENAME AS "POLAR_STEREO_MAP_JACOB"
586 ! 2018-07-20 WESLEY PASS IN DR2 FOR THREADING.
587 !
588 ! USAGE: CALL POLAR_STEREO_MAP_JACOB(RLON,RLAT,DR2,XLON,XLAT,YLON,YLAT)
589 !
590 ! INPUT ARGUMENT LIST:
591 ! RLON - LONGITUDE IN DEGREES (REAL)
592 ! RLAT - LATITUDE IN DEGREES (REAL)
593 ! DR2 - SQUARED DISTANCE FROM POLE (REAL)
594 !
595 ! OUTPUT ARGUMENT LIST:
596 ! XLON - DX/DLON IN 1/DEGREES (REAL)
597 ! XLAT - DX/DLAT IN 1/DEGREES (REAL)
598 ! YLON - DY/DLON IN 1/DEGREES (REAL)
599 ! YLAT - DY/DLAT IN 1/DEGREES (REAL)
600 !
601 ! ATTRIBUTES:
602 ! LANGUAGE: FORTRAN 90
603 !
604 !$$$
605 !
606 IMPLICIT NONE
607
608 REAL, INTENT(IN ) :: RLON, RLAT, DR2
609 REAL, INTENT( OUT) :: XLON, XLAT, YLON, YLAT
610
611 REAL :: CLAT, DE, DR
612
613 IF(dr2.LT.de2*1.e-6) THEN
614 de=sqrt(de2)
615 xlon=0.
616 xlat=-sin((rlon-orient)/dpr)/dpr*de/dxs/2
617 ylon=0.
618 ylat=h*cos((rlon-orient)/dpr)/dpr*de/dys/2
619 ELSE
620 dr=sqrt(dr2)
621 clat=cos(rlat/dpr)
622 xlon=h*cos((rlon-orient)/dpr)/dpr*dr/dxs
623 xlat=-sin((rlon-orient)/dpr)/dpr*dr/dxs/clat
624 ylon=sin((rlon-orient)/dpr)/dpr*dr/dys
625 ylat=h*cos((rlon-orient)/dpr)/dpr*dr/dys/clat
626 ENDIF
627
628 END SUBROUTINE polar_stereo_map_jacob
629 !
630 SUBROUTINE polar_stereo_grid_area(RLAT, DR2, AREA)
631 !$$$ SUBPROGRAM DOCUMENTATION BLOCK
632 !
633 ! SUBPROGRAM: POLAR_STEREO_GRID_AREA GRID BOX AREA FOR
634 ! POLAR STEREOGRAPHIC GRIDS
635 !
636 ! PRGMMR: GAYNO ORG: W/NMC23 DATE: 2015-01-21
637 !
638 ! ABSTRACT: THIS SUBPROGRAM COMPUTES THE GRID BOX AREA FOR
639 ! A POLAR STEREOGRAPHIC AZIMUTHAL GRID (SPHERICAL
640 ! EARTH).
641 !
642 ! PROGRAM HISTORY LOG:
643 ! 2015-01-21 GAYNO INITIAL VERSION
644 ! 2015-09-17 GAYNO RENAME AS "POLAR_STEREO_GRID_AREA".
645 ! 2018-07-20 WESLEY PASS IN DR2 FOR THREADING.
646 !
647 ! USAGE: CALL POLAR_STEREO_GRID_AREA(RLAT,DR2,AREA)
648 !
649 ! INPUT ARGUMENT LIST:
650 ! RLAT - LATITUDE OF GRID POINT IN DEGREES (REAL)
651 ! DR2 - SQUARED DISTANCE FROM POLE (REAL)
652 !
653 ! OUTPUT ARGUMENT LIST:
654 ! AREA - AREA WEIGHTS IN M**2 (REAL)
655 !
656 ! ATTRIBUTES:
657 ! LANGUAGE: FORTRAN 90
658 !
659 !$$$
660 !
661 IMPLICIT NONE
662
663 REAL, INTENT(IN ) :: RLAT, DR2
664 REAL, INTENT( OUT) :: AREA
665
666 REAL :: CLAT
667
668 IF(dr2.LT.de2*1.e-6) THEN
669 area=rerth**2*abs(dxs)*abs(dys)*4/de2
670 ELSE
671 clat=cos(rlat/dpr)
672 area=rerth**2*clat**2*abs(dxs)*abs(dys)/dr2
673 ENDIF
674
675 END SUBROUTINE polar_stereo_grid_area
676
677
678end module ip_polar_stereo_grid_mod
679
Module containing common constants.
real(real64), parameter pi2
PI / 2.0.
real(real64), parameter pi4
PI / 4.0.
real(real64), parameter rerth_wgs84
Radius of the Earth defined by WGS-84.
real(real64), parameter pi
PI.
real(real64), parameter dpr
Radians to degrees.
real(real64), parameter e2_wgs84
Eccentricity squared of Earth defined by WGS-84.
Uses derived type grid descriptor objects to abstract away the raw Grib-1 and Grib-2 grid definitions...
Abstract ip_grid type.
Definition: ip_grid_mod.f90:8
Abstract grid that holds fields and methods common to all grids.
Definition: ip_grid_mod.f90:45