11 use iso_fortran_env,
only: real64
21 integer,
parameter :: kd = real64
24 real(kd) :: rlon0, rlon1, rlat1, clat0, slat0
25 real(kd) :: dlats, dlons, hi
28 procedure :: init_grib1
29 procedure :: init_grib2
35 REAL(KIND=kd) :: clat, clat0, clatr
36 REAL(KIND=kd) :: clon, dlats, dlons, rerth
37 REAL(KIND=kd) :: rlon0, slat, slat0, slatr
55 real(kd) :: rlat1, rlon1, rlon0, slat1, clat1, slat0, clat0, clon1
56 real(kd) :: slatr, clatr, clonr, rlatr, rlonr, dlats, dlons, hs, hi
59 integer :: is1, kscan, irot
61 associate(kgds => g1_desc%gds)
62 self%rerth = 6.3712e6_kd
63 self%eccen_squared = 0.0
68 self%nscan_field_pos = 3
69 self%nscan = mod(kgds(11)/32,2)
71 rlat1=kgds(4)*1.e-3_kd
72 rlon1=kgds(5)*1.e-3_kd
73 rlat0=kgds(7)*1.e-3_kd
74 rlon0=kgds(8)*1.e-3_kd
77 kscan=mod(kgds(11)/256,2)
78 iscan=mod(kgds(11)/128,2)
84 hs=sign(1._kd,mod(rlon1-rlon0+180+3600,360._kd)-180)
85 clon1=cos((rlon1-rlon0)/
dpr)
86 slatr=clat0*slat1-slat0*clat1*clon1
87 clatr=sqrt(1-slatr**2)
88 clonr=(clat0*clat1*clon1+slat0*slat1)/clatr
90 rlonr=hs*
dpr*acos(clonr)
91 dlats=rlatr/(-(jm-1)/2)
92 dlons=rlonr/(-((im * 2 - 1) -1)/2)
127 type(grib2_descriptor),
intent(in) :: g2_desc
129 integer :: iscale, iscan
131 integer :: i_offset_odd
133 associate(igdtmpl => g2_desc%gdt_tmpl, igdtlen => g2_desc%gdt_len)
134 CALL earth_radius(igdtmpl,igdtlen,self%rerth,self%eccen_squared)
151 self%NSCAN=mod(igdtmpl(16)/32,2)
152 self%nscan_field_pos = 3
154 iscale=igdtmpl(10)*igdtmpl(11)
155 IF(iscale==0) iscale=10**6
157 self%RLON0=float(igdtmpl(21))/float(iscale)
158 self%DLATS=float(igdtmpl(18))/float(iscale)
160 self%DLONS=float(igdtmpl(17))/float(iscale) * 0.5_kd
162 self%IROT=mod(igdtmpl(14)/8,2)
164 i_offset_odd=mod(igdtmpl(19)/8,2)
165 self%KSCAN=i_offset_odd
166 iscan=mod(igdtmpl(19)/128,2)
170 rlat0=float(igdtmpl(20))/float(iscale)
173 self%SLAT0=sin(rlat0/dpr)
174 self%CLAT0=cos(rlat0/dpr)
176 self%RLAT1=float(igdtmpl(12))/float(iscale)
177 self%RLON1=float(igdtmpl(13))/float(iscale)
230 FILL,XPTS,YPTS,RLON,RLAT,NRET, &
231 CROT,SROT,XLON,XLAT,YLON,YLAT,AREA)
236 INTEGER,
INTENT(IN ) :: IOPT, NPTS
237 INTEGER,
INTENT( OUT) :: NRET
239 REAL,
INTENT(IN ) :: FILL
240 REAL,
INTENT(INOUT) :: RLON(NPTS),RLAT(NPTS)
241 REAL,
INTENT(INOUT) :: XPTS(NPTS),YPTS(NPTS)
242 REAL,
OPTIONAL,
INTENT( OUT) :: CROT(NPTS),SROT(NPTS)
243 REAL,
OPTIONAL,
INTENT( OUT) :: XLON(NPTS),XLAT(NPTS)
244 REAL,
OPTIONAL,
INTENT( OUT) :: YLON(NPTS),YLAT(NPTS),AREA(NPTS)
246 INTEGER :: IM, JM, IS1, N
250 LOGICAL :: LROT, LMAP, LAREA
252 REAL(KIND=kd) :: rlat1, rlon1
253 REAL(KIND=kd) :: clonr
254 REAL(KIND=kd) :: rlatr, rlonr, sbd, wbd, hs
256 REAL :: XMAX, XMIN, YMAX, YMIN, XPTF, YPTF
258 IF(
PRESENT(crot)) crot=fill
259 IF(
PRESENT(srot)) srot=fill
260 IF(
PRESENT(xlon)) xlon=fill
261 IF(
PRESENT(xlat)) xlat=fill
262 IF(
PRESENT(ylon)) ylon=fill
263 IF(
PRESENT(ylat)) ylat=fill
264 IF(
PRESENT(area)) area=fill
283 CALL rot_equid_cylind_egrid_error(iopt,fill,rlat,rlon,xpts,ypts,npts)
290 IF (wbd > 180.0) wbd = wbd - 360.0
303 IF(
PRESENT(crot).AND.
PRESENT(srot))
THEN
308 IF(
PRESENT(xlon).AND.
PRESENT(xlat).AND.
PRESENT(ylon).AND.
PRESENT(ylat))
THEN
313 IF(
PRESENT(area))
THEN
321 IF(iopt.EQ.0.OR.iopt.EQ.1)
THEN
323 xptf=ypts(n)+(xpts(n)-is1)
324 yptf=ypts(n)-(xpts(n)-is1)+kscan
325 IF(xptf.GE.xmin.AND.xptf.LE.xmax.AND. &
326 yptf.GE.ymin.AND.yptf.LE.ymax)
THEN
327 hs=hi*sign(1.,xptf-(im+1)/2)
328 select type(desc => self%descriptor)
329 type is(grib1_descriptor)
330 rlonr=(xptf-(im+1)/2)*dlons
331 rlatr=(yptf-(jm+1)/2)*dlats
332 type is(grib2_descriptor)
333 rlonr=(xptf-1.0_kd)*dlons + wbd
334 rlatr=(yptf-1.0_kd)*dlats + sbd
339 slat=clat0*slatr+slat0*clatr*clonr
345 ELSEIF(slat.GE.1)
THEN
352 clon=(clat0*clatr*clonr-slat0*slatr)/clat
353 clon=min(max(clon,-1._kd),1._kd)
354 rlon(n)=mod(rlon0+hs*dpr*acos(clon)+3600,360._kd)
355 rlat(n)=dpr*asin(slat)
360 xlon(n),xlat(n),ylon(n),ylat(n))
369 ELSEIF(iopt.EQ.-1)
THEN
371 IF(abs(rlon(n)).LE.360.AND.abs(rlat(n)).LE.90)
THEN
372 hs=sign(1._kd,mod(rlon(n)-rlon0+180+3600,360._kd)-180)
373 clon=cos((rlon(n)-rlon0)/dpr)
374 slat=sin(rlat(n)/dpr)
375 clat=cos(rlat(n)/dpr)
376 slatr=clat0*slat-slat0*clat*clon
381 ELSEIF(slatr.GE.1)
THEN
386 clatr=sqrt(1-slatr**2)
387 clonr=(clat0*clat*clon+slat0*slat)/clatr
388 clonr=min(max(clonr,-1._kd),1._kd)
389 rlonr=hs*dpr*acos(clonr)
390 rlatr=dpr*asin(slatr)
392 select type(desc => self%descriptor)
393 type is(grib1_descriptor)
394 xptf=((rlonr-wbd)/dlons)+1.0_kd
395 yptf=((rlatr-sbd)/dlats)+1.0_kd
396 type is(grib2_descriptor)
397 xptf=(im+1)/2+rlonr/dlons
398 yptf=(jm+1)/2+rlatr/dlats
401 IF(xptf.GE.xmin.AND.xptf.LE.xmax.AND. &
402 yptf.GE.ymin.AND.yptf.LE.ymax)
THEN
403 xpts(n)=is1+(xptf-(yptf-kscan))/2
404 ypts(n)=(xptf+(yptf-kscan))/2
408 xlon(n),xlat(n),ylon(n),ylat(n))
423 SUBROUTINE rot_equid_cylind_egrid_error(IOPT,FILL,RLAT,RLON,XPTS,YPTS,NPTS)
458 INTEGER,
INTENT(IN ) :: IOPT, NPTS
460 REAL,
INTENT(IN ) :: FILL
461 REAL,
INTENT( OUT) :: RLAT(NPTS),RLON(NPTS)
462 REAL,
INTENT( OUT) :: XPTS(NPTS),YPTS(NPTS)
473 END SUBROUTINE rot_equid_cylind_egrid_error
491 REAL ,
INTENT(IN ) :: RLON
492 REAL ,
INTENT( OUT) :: CROT, SROT
494 REAL(KIND=kd) :: slon
498 crot=-sign(1._kd,slatr*slat0)
501 slon=sin((rlon-rlon0)/dpr)
502 crot=(clat0*clat+slat0*slat*clon)/clatr
503 srot=slat0*slon/clatr
524 XLON, XLAT, YLON, YLAT)
527 REAL ,
INTENT(IN ) :: FILL, RLON
528 REAL ,
INTENT( OUT) :: XLON, XLAT, YLON, YLAT
530 REAL(KIND=kd) :: slon, term1, term2
531 REAL(KIND=kd) :: xlatf, xlonf, ylatf, ylonf
533 IF(clatr.LE.0._kd)
THEN
539 slon=sin((rlon-rlon0)/dpr)
540 term1=(clat0*clat+slat0*slat*clon)/clatr
541 term2=slat0*slon/clatr
542 xlonf=term1*clat/(dlons*clatr)
543 xlatf=-term2/(dlons*clatr)
544 ylonf=term2*clat/dlats
564 REAL,
INTENT(IN ) :: FILL
565 REAL,
INTENT( OUT) :: AREA
567 IF(clatr.LE.0._kd)
THEN
570 area=rerth**2*clatr*dlats*dlons*2/dpr**2
Module containing common constants.
real(real64), parameter pi
PI.
real(real64), parameter dpr
Radians to degrees.
Uses derived type grid descriptor objects to abstract away the raw Grib-1 and Grib-2 grid definitions...
Rotated equidistant cylindrical grib decoder and grid coordinate transformations.
subroutine rot_equid_cylind_egrid_map_jacob(FILL, RLON, XLON, XLAT, YLON, YLAT)
Computes the map jacobians for a rotated equidistant cylindrical grid.
subroutine rot_equid_cylind_egrid_grid_area(FILL, AREA)
Computes the grid box area for a rotated equidistant cylindrical grid.
subroutine rot_equid_cylind_egrid_vect_rot(RLON, CROT, SROT)
Computes the vector rotation sines and cosines for a rotated equidistant cylindrical grid.
subroutine gdswzd_rot_equid_cylind_egrid(self, IOPT, NPTS, FILL, XPTS, YPTS, RLON, RLAT, NRET, CROT, SROT, XLON, XLAT, YLON, YLAT, AREA)
Calculates Earth coordinates (iopt = 1) or grid coorindates (iopt = -1) for rotated equidistant cylin...
subroutine init_grib1(self, g1_desc)
Initializes a rotated equidistant cylindrical grid given a grib1_descriptor object.
subroutine init_grib2(self, g2_desc)
Initializes a rotated equidistant cylindrical grid given a grib2_descriptor object.
Descriptor representing a grib1 grib descriptor section (GDS) with an integer array.
Abstract grid that holds fields and methods common to all grids.