20 use iso_fortran_env,
only: real64
30 integer,
parameter ::
kd = real64
77 real(kd) :: rlat1, rlon1, rlat0, rlat2, rlon2, nbd, ebd
78 real(kd) :: hs, hs2, slat1, slat2, slatr, clon1, clon2, clat1, clat2, clatr, clonr, rlonr, rlatr
80 associate(kgds => g1_desc%gds)
81 self%rerth = 6.3712e6_kd
82 self%eccen_squared = 0d0
84 rlat1=kgds(4)*1.e-3_kd
85 rlon1=kgds(5)*1.e-3_kd
86 rlat0=kgds(7)*1.e-3_kd
87 self%RLON0=kgds(8)*1.e-3_kd
88 rlat2=kgds(12)*1.e-3_kd
89 rlon2=kgds(13)*1.e-3_kd
91 self%IROT=mod(kgds(6)/8,2)
97 self%SLAT0=sin(rlat0/
dpr)
98 self%CLAT0=cos(rlat0/
dpr)
100 hs=sign(1._kd,mod(rlon1-self%RLON0+180+3600,360._kd)-180)
101 clon1=cos((rlon1-self%RLON0)/
dpr)
102 slatr=self%CLAT0*slat1-self%SLAT0*clat1*clon1
103 clatr=sqrt(1-slatr**2)
104 clonr=(self%CLAT0*clat1*clon1+self%SLAT0*slat1)/clatr
105 rlatr=
dpr*asin(slatr)
106 rlonr=hs*
dpr*acos(clonr)
112 hs2=sign(1._kd,mod(rlon2-self%RLON0+180+3600,360._kd)-180)
113 clon2=cos((rlon2-self%RLON0)/
dpr)
114 slatr=self%CLAT0*slat2-self%SLAT0*clat2*clon2
115 clatr=sqrt(1-slatr**2)
116 clonr=(self%CLAT0*clat2*clon2+self%SLAT0*slat2)/clatr
118 ebd=hs2*
dpr*acos(clonr)
119 self%DLATS=(nbd-self%SBD)/float(self%JM-1)
120 self%DLONS=(ebd-self%WBD)/float(self%IM-1)
125 self%nscan = mod(kgds(11) / 32, 2)
126 self%nscan_field_pos = self%nscan
141 type(grib2_descriptor),
intent(in) :: g2_desc
143 real(kd) :: rlat1, rlon1, rlat0, rlat2, rlon2, nbd, ebd
145 integer :: i_offset_odd, i_offset_even, j_offset
147 associate(igdtmpl => g2_desc%gdt_tmpl, igdtlen => g2_desc%gdt_len)
149 CALL earth_radius(igdtmpl,igdtlen,self%rerth,self%eccen_squared)
151 i_offset_odd=mod(igdtmpl(19)/8,2)
152 i_offset_even=mod(igdtmpl(19)/4,2)
153 j_offset=mod(igdtmpl(19)/2,2)
155 iscale=igdtmpl(10)*igdtmpl(11)
156 IF(iscale==0) iscale=10**6
158 rlat1=float(igdtmpl(12))/float(iscale)
159 rlon1=float(igdtmpl(13))/float(iscale)
160 rlat0=float(igdtmpl(20))/float(iscale)
163 self%RLON0=float(igdtmpl(21))/float(iscale)
165 rlat2=float(igdtmpl(15))/float(iscale)
166 rlon2=float(igdtmpl(16))/float(iscale)
168 self%IROT=mod(igdtmpl(14)/8,2)
172 self%SLAT0=sin(rlat0/dpr)
173 self%CLAT0=cos(rlat0/dpr)
176 IF (self%WBD > 180.0) self%WBD = self%WBD - 360.0
182 self%DLATS=(nbd-self%SBD)/float(self%JM-1)
183 self%DLONS=(ebd-self%WBD)/float(self%IM-1)
185 IF(i_offset_odd==1) self%WBD=self%WBD+(0.5_kd*self%DLONS)
186 IF(j_offset==1) self%SBD=self%SBD+(0.5_kd*self%DLATS)
192 self%nscan = mod(igdtmpl(19) / 32, 2)
193 self%nscan_field_pos = self%nscan
257 FILL,XPTS,YPTS,RLON,RLAT,NRET, &
258 CROT,SROT,XLON,XLAT,YLON,YLAT,AREA)
262 INTEGER,
INTENT(IN ) :: IOPT, NPTS
263 INTEGER,
INTENT( OUT) :: NRET
265 REAL,
INTENT(IN ) :: FILL
266 REAL,
INTENT(INOUT) :: RLON(NPTS),RLAT(NPTS)
267 REAL,
INTENT(INOUT) :: XPTS(NPTS),YPTS(NPTS)
268 REAL,
OPTIONAL,
INTENT( OUT) :: CROT(NPTS),SROT(NPTS)
269 REAL,
OPTIONAL,
INTENT( OUT) :: XLON(NPTS),XLAT(NPTS)
270 REAL,
OPTIONAL,
INTENT( OUT) :: YLON(NPTS),YLAT(NPTS),AREA(NPTS)
274 LOGICAL :: LROT, LMAP, LAREA
277 REAL(KIND=
kd) :: clonr,clatr,slatr
278 REAL(KIND=
kd) :: clat,slat,clon
279 REAL(KIND=
kd) :: rlatr,rlonr
280 REAL(KIND=
kd) :: wbd,sbd
281 REAL :: XMIN,XMAX,YMIN,YMAX
283 IF(
PRESENT(crot)) crot=fill
284 IF(
PRESENT(srot)) srot=fill
285 IF(
PRESENT(xlon)) xlon=fill
286 IF(
PRESENT(xlat)) xlat=fill
287 IF(
PRESENT(ylon)) ylon=fill
288 IF(
PRESENT(ylat)) ylat=fill
289 IF(
PRESENT(area)) area=fill
331 IF(
PRESENT(crot).AND.
PRESENT(srot))
THEN
336 IF(
PRESENT(xlon).AND.
PRESENT(xlat).AND.
PRESENT(ylon).AND.
PRESENT(ylat))
THEN
341 IF(
PRESENT(area))
THEN
348 IF(iopt.EQ.0.OR.iopt.EQ.1)
THEN
352 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
353 ypts(n).GE.ymin.AND.ypts(n).LE.ymax)
THEN
354 rlonr=wbd+(xpts(n)-1._kd)*
dlons
355 rlatr=sbd+(ypts(n)-1._kd)*
dlats
356 IF(rlonr <= 0._kd)
THEN
370 ELSEIF(slat.GE.1)
THEN
378 clon=min(max(clon,-1._kd),1._kd)
379 rlon(n)=real(mod(
rlon0+hs*dpr*acos(clon)+3600,360._kd))
380 rlat(n)=real(dpr*asin(slat))
384 clat, slat, clon, crot(n), srot(n))
386 clat, slat, clon, xlon(n), xlat(n), ylon(n), ylat(n))
396 ELSEIF(iopt.EQ.-1)
THEN
400 IF(abs(rlon(n)).LE.360.AND.abs(rlat(n)).LE.90)
THEN
401 hs=sign(1._kd,mod(rlon(n)-
rlon0+180+3600,360._kd)-180)
402 clon=cos((rlon(n)-
rlon0)/dpr)
403 slat=sin(rlat(n)/dpr)
404 clat=cos(rlat(n)/dpr)
410 ELSEIF(slatr.GE.1)
THEN
415 clatr=sqrt(1-slatr**2)
417 clonr=min(max(clonr,-1._kd),1._kd)
418 rlonr=hs*dpr*acos(clonr)
419 rlatr=dpr*asin(slatr)
421 xpts(n)=real((rlonr-wbd)/
dlons+1._kd)
422 ypts(n)=real((rlatr-sbd)/
dlats+1._kd)
423 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
424 ypts(n).GE.ymin.AND.ypts(n).LE.ymax)
THEN
427 clat, slat, clon, crot(n), srot(n))
429 clat, slat, clon, xlon(n), xlat(n), ylon(n), ylat(n))
465 INTEGER,
INTENT(IN ) :: IOPT, NPTS
467 REAL,
INTENT(IN ) :: FILL
468 REAL,
INTENT( OUT) :: RLAT(NPTS),RLON(NPTS)
469 REAL,
INTENT( OUT) :: XPTS(NPTS),YPTS(NPTS)
511 REAL(KIND=
kd),
INTENT(IN ) :: clat, clatr, clon, slat, slatr
512 REAL ,
INTENT(IN ) :: RLON
513 REAL ,
INTENT( OUT) :: CROT, SROT
515 REAL(KIND=
kd) :: slon
518 IF(clatr.LE.0._kd)
THEN
519 crot=real(-sign(1._kd,slatr*
slat0))
522 slon=sin((rlon-
rlon0)/dpr)
524 srot=real(
slat0*slon/clatr)
559 SLAT, CLON, XLON, XLAT, YLON, YLAT)
562 REAL(KIND=
kd),
INTENT(IN ) :: clatr, clat, slat, clon
563 REAL ,
INTENT(IN ) :: FILL, RLON
564 REAL ,
INTENT( OUT) :: XLON, XLAT, YLON, YLAT
566 REAL(KIND=
kd) :: slon, term1, term2
568 IF(clatr.LE.0._kd)
THEN
574 slon=sin((rlon-
rlon0)/dpr)
576 term2=
slat0*slon/clatr
577 xlon=real(term1*clat/(
dlons*clatr))
578 xlat=real(-term2/(
dlons*clatr))
579 ylon=real(term2*clat/
dlats)
580 ylat=real(term1/
dlats)
606 REAL(KIND=
kd),
INTENT(IN ) :: clatr
607 REAL,
INTENT(IN ) :: FILL
608 REAL,
INTENT( OUT) :: AREA
610 IF(clatr.LE.0._kd)
THEN
void gdswzd(int igdtnum, int *igdtmpl, int igdtlen, int iopt, int npts, float fill, float *xpts, float *ypts, float *rlon, float *rlat, int *nret, float *crot, float *srot, float *xlon, float *xlat, float *ylon, float *ylat, float *area)
gdswzd() interface for C for _4 build of library.
Module containing common constants.
real, parameter dpr
Radians to degrees.
Determine earth radius and shape.
Users derived type grid descriptor objects to abstract away the raw GRIB1 and GRIB2 grid definitions.
Rotated equidistant cylindrical GRIB decoder and grid coordinate transformations for Arakawa grids A ...
subroutine rot_equid_cylind_error(IOPT, FILL, RLAT, RLON, XPTS, YPTS, NPTS)
Error handler.
subroutine rot_equid_cylind_vect_rot(RLON, CLATR, SLATR, CLAT, SLAT, CLON, CROT, SROT)
Vector rotation fields for rotated equidistant cylindrical grids - non "e" stagger.
subroutine gdswzd_rot_equid_cylind(self, IOPT, NPTS, FILL, XPTS, YPTS, RLON, RLAT, NRET, CROT, SROT, XLON, XLAT, YLON, YLAT, AREA)
GDS wizard for rotated equidistant cylindrical.
real(kind=kd) rlon0
Local copy of rlon0.
real(kind=kd) slat0
Local copy of slat0.
subroutine rot_equid_cylind_map_jacob(FILL, RLON, CLATR, CLAT, SLAT, CLON, XLON, XLAT, YLON, YLAT)
Map jacobians for rotated equidistant cylindrical grids - non "e" stagger.
real(kind=kd) dlons
Local copy of dlons.
real(kind=kd) dlats
Local copy of dlats.
integer irot
Local copy of irot.
subroutine init_grib1(self, g1_desc)
Initializes a Rotated equidistant cylindrical grid given a grib1_descriptor object.
subroutine rot_equid_cylind_grid_area(CLATR, FILL, AREA)
Grid box area for rotated equidistant cylindrical grids - non "e" stagger.
subroutine init_grib2(self, g2_desc)
Initializes a Rotated equidistant cylindrical grid given a grib2_descriptor object.
real(kind=kd) rerth
Radius of the Earth.
integer, parameter kd
Fortran kind for reals.
real(kind=kd) clat0
Local copy of clat0.
Descriptor representing a grib1 grib descriptor section (GDS) with an integer array.
Abstract grid that holds fields and methods common to all grids.