1module ip_polar_stereo_grid_mod
13 real :: rlat1, rlon1, orient, h, dxs, dys, slatr
16 procedure :: init_grib1
17 procedure :: init_grib2
18 procedure :: gdswzd => gdswzd_polar_stereo
24 REAL :: E2, RERTH , H, ORIENT
28 subroutine init_grib1(self, g1_desc)
29 class(ip_polar_stereo_grid),
intent(inout) :: self
30 type(grib1_descriptor),
intent(in) :: g1_desc
32 REAL,
PARAMETER :: SLAT=60.0
34 real :: dx, dy, hi, hj
35 integer :: iproj, iscan, jscan
37 associate(kgds => g1_desc%gds)
38 self%ELLIPTICAL=mod(kgds(6)/64,2).EQ.1
40 if (.not. self%elliptical)
then
42 self%eccen_squared = 0d0
51 self%RLAT1=kgds(4)*1.e-3
52 self%RLON1=kgds(5)*1.e-3
54 self%IROT=mod(kgds(6)/8,2)
58 self%ORIENT=kgds(7)*1.e-3
63 iproj=mod(kgds(10)/128,2)
64 iscan=mod(kgds(11)/128,2)
65 jscan=mod(kgds(11)/64,2)
71 IF(self%H.EQ.-1)self%ORIENT=self%ORIENT+180.
79 self%nscan = mod(kgds(11) / 32, 2)
80 self%nscan_field_pos = self%nscan
84 end subroutine init_grib1
86 subroutine init_grib2(self, g2_desc)
87 class(ip_polar_stereo_grid),
intent(inout) :: self
88 type(grib2_descriptor),
intent(in) :: g2_desc
90 real :: slat, dx, dy, hi, hj
91 integer :: iproj, iscan, jscan
93 associate(igdtmpl => g2_desc%gdt_tmpl, igdtlen => g2_desc%gdt_len)
94 call earth_radius(igdtmpl, igdtlen, self%rerth, self%eccen_squared)
96 self%ELLIPTICAL = self%eccen_squared > 0.0
101 self%RLAT1=float(igdtmpl(10))*1.e-6
102 self%RLON1=float(igdtmpl(11))*1.e-6
104 self%IROT=mod(igdtmpl(12)/8,2)
106 slat=float(abs(igdtmpl(13)))*1.e-6
109 self%ORIENT=float(igdtmpl(14))*1.e-6
111 dx=float(igdtmpl(15))*1.e-3
112 dy=float(igdtmpl(16))*1.e-3
114 iproj=mod(igdtmpl(17)/128,2)
115 iscan=mod(igdtmpl(18)/128,2)
116 jscan=mod(igdtmpl(18)/64,2)
125 self%nscan = mod(igdtmpl(18) / 32, 2)
126 self%nscan_field_pos = self%nscan
132 end subroutine init_grib2
135 SUBROUTINE gdswzd_polar_stereo(self,IOPT,NPTS, &
136 FILL,XPTS,YPTS,RLON,RLAT,NRET, &
137 CROT,SROT,XLON,XLAT,YLON,YLAT,AREA)
257 class(ip_polar_stereo_grid),
intent(in) :: self
258 INTEGER,
INTENT(IN ) :: IOPT, NPTS
259 INTEGER,
INTENT( OUT) :: NRET
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)
271 LOGICAL :: ELLIPTICAL, LROT, LMAP, LAREA
273 REAL :: ALAT, ALAT1, ALONG, DIFF
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
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
289 elliptical = self%elliptical
305 e2 = self%eccen_squared
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
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))
325 yp = 1.0 + rho*cos(h*along)/dys
326 xp = 1.0 - rho*sin(h*along)/dxs
333 IF(
PRESENT(crot).AND.
PRESENT(srot))
THEN
338 IF(
PRESENT(xlon).AND.
PRESENT(xlat).AND.
PRESENT(ylon).AND.
PRESENT(ylat))
THEN
343 IF(
PRESENT(area))
THEN
350 IF(iopt.EQ.0.OR.iopt.EQ.1)
THEN
351 IF(.NOT.elliptical)
THEN
354 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
355 ypts(n).GE.ymin.AND.ypts(n).LE.ymax)
THEN
359 IF(dr2.LT.de2*1.e-6)
THEN
363 rlon(n)=mod(orient+h*dpr*atan2(di,-dj)+3600,360.)
364 rlat(n)=h*dpr*asin((de2-dr2)/(de2+dr2))
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))
381 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
382 ypts(n).GE.ymin.AND.ypts(n).LE.ymax)
THEN
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
391 along=orient+h*atan(di/(-dj))*dpr
392 IF(dj>0) along=along+180.
394 alat1=pi2-2.0*atan(t)
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
404 IF(rlon(n)<0.0) rlon(n)=rlon(n)+360.
405 IF(rlon(n)>360.0) rlon(n)=rlon(n)-360.0
407 IF(lrot)
CALL polar_stereo_vect_rot(rlon(n),crot(n),srot(n))
417 ELSEIF(iopt.EQ.-1)
THEN
418 IF(.NOT.elliptical)
THEN
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)
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
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))
447 IF(abs(rlon(n)).LE.360.AND.abs(rlat(n)).LE.90.AND. &
448 h*rlat(n).NE.-90)
THEN
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)
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
459 IF(lrot)
CALL polar_stereo_vect_rot(rlon(n),crot(n),srot(n))
473 END SUBROUTINE gdswzd_polar_stereo
475 SUBROUTINE polar_stereo_error(IOPT,FILL,RLAT,RLON,XPTS,YPTS,NPTS)
508 INTEGER,
INTENT(IN ) :: IOPT, NPTS
510 REAL,
INTENT(IN ) :: FILL
511 REAL,
INTENT( OUT) :: RLAT(NPTS),RLON(NPTS)
512 REAL,
INTENT( OUT) :: XPTS(NPTS),YPTS(NPTS)
523 END SUBROUTINE polar_stereo_error
525 SUBROUTINE polar_stereo_vect_rot(RLON, CROT, SROT)
558 REAL,
INTENT(IN ) :: RLON
559 REAL,
INTENT( OUT) :: CROT, SROT
562 crot=h*cos((rlon-orient)/dpr)
563 srot=sin((rlon-orient)/dpr)
569 END SUBROUTINE polar_stereo_vect_rot
571 SUBROUTINE polar_stereo_map_jacob(RLON,RLAT,DR2,XLON,XLAT,YLON,YLAT)
608 REAL,
INTENT(IN ) :: RLON, RLAT, DR2
609 REAL,
INTENT( OUT) :: XLON, XLAT, YLON, YLAT
613 IF(dr2.LT.de2*1.e-6)
THEN
616 xlat=-sin((rlon-orient)/dpr)/dpr*de/dxs/2
618 ylat=h*cos((rlon-orient)/dpr)/dpr*de/dys/2
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
628 END SUBROUTINE polar_stereo_map_jacob
630 SUBROUTINE polar_stereo_grid_area(RLAT, DR2, AREA)
663 REAL,
INTENT(IN ) :: RLAT, DR2
664 REAL,
INTENT( OUT) :: AREA
668 IF(dr2.LT.de2*1.e-6)
THEN
669 area=rerth**2*abs(dxs)*abs(dys)*4/de2
672 area=rerth**2*clat**2*abs(dxs)*abs(dys)/dr2
675 END SUBROUTINE polar_stereo_grid_area
678end module ip_polar_stereo_grid_mod
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 grid that holds fields and methods common to all grids.