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
142 type(grib2_descriptor),
intent(in) :: g2_desc
144 if (ncep_post_arakawa.and.(g2_desc%gdt_num.eq.32769))
then
162 type(grib2_descriptor),
intent(in) :: g2_desc
164 real(kd) :: rlat1, rlon1, rlat0, rlat2, rlon2, nbd, ebd
166 integer :: i_offset_odd, i_offset_even, j_offset
168 associate(igdtmpl => g2_desc%gdt_tmpl, igdtlen => g2_desc%gdt_len)
170 CALL earth_radius(igdtmpl,igdtlen,self%rerth,self%eccen_squared)
172 i_offset_odd=mod(igdtmpl(19)/8,2)
173 i_offset_even=mod(igdtmpl(19)/4,2)
174 j_offset=mod(igdtmpl(19)/2,2)
176 iscale=igdtmpl(10)*igdtmpl(11)
177 IF(iscale==0) iscale=10**6
179 rlat1=float(igdtmpl(12))/float(iscale)
180 rlon1=float(igdtmpl(13))/float(iscale)
181 rlat0=float(igdtmpl(20))/float(iscale)
184 self%RLON0=float(igdtmpl(21))/float(iscale)
186 rlat2=float(igdtmpl(15))/float(iscale)
187 rlon2=float(igdtmpl(16))/float(iscale)
189 self%IROT=mod(igdtmpl(14)/8,2)
193 self%SLAT0=sin(rlat0/dpr)
194 self%CLAT0=cos(rlat0/dpr)
197 IF (self%WBD > 180.0) self%WBD = self%WBD - 360.0
203 self%DLATS=(nbd-self%SBD)/float(self%JM-1)
204 self%DLONS=(ebd-self%WBD)/float(self%IM-1)
206 IF(i_offset_odd==1) self%WBD=self%WBD+(0.5_kd*self%DLONS)
207 IF(j_offset==1) self%SBD=self%SBD+(0.5_kd*self%DLATS)
213 self%nscan = mod(igdtmpl(19) / 32, 2)
214 self%nscan_field_pos = self%nscan
229 type(grib2_descriptor),
intent(in) :: g2_desc
231 real(kd) :: rlat1, rlon1, rlat0, rlat2, rlon2, nbd, ebd
233 integer :: i_offset_odd, i_offset_even, j_offset
234 real(kd) :: hs, hs2, slat1, slat2, slatr, clon1, clon2, clat1, clat2, clatr, clonr, rlonr, rlatr
236 associate(igdtmpl => g2_desc%gdt_tmpl, igdtlen => g2_desc%gdt_len)
238 CALL earth_radius(igdtmpl,igdtlen,self%rerth,self%eccen_squared)
240 i_offset_odd=mod(igdtmpl(19)/8,2)
241 i_offset_even=mod(igdtmpl(19)/4,2)
242 j_offset=mod(igdtmpl(19)/2,2)
244 iscale=igdtmpl(10)*igdtmpl(11)
245 IF(iscale==0) iscale=10**6
247 rlat1=float(igdtmpl(12))/float(iscale)
248 rlon1=float(igdtmpl(13))/float(iscale)
249 rlat0=float(igdtmpl(15))/float(iscale)
251 self%RLON0=float(igdtmpl(16))/float(iscale)
253 rlat2=float(igdtmpl(20))/float(iscale)
254 rlon2=float(igdtmpl(21))/float(iscale)
256 self%IROT=mod(igdtmpl(14)/8,2)
263 self%SLAT0=sin(rlat0/dpr)
264 self%CLAT0=cos(rlat0/dpr)
266 hs=sign(1._kd,mod(rlon1-self%RLON0+180+3600,360._kd)-180)
268 clon1=cos((rlon1-self%RLON0)/dpr)
269 slatr=self%CLAT0*slat1-self%SLAT0*clat1*clon1
270 clatr=sqrt(1-slatr**2)
271 clonr=(self%CLAT0*clat1*clon1+self%SLAT0*slat1)/clatr
272 rlatr=dpr*asin(slatr)
273 rlonr=hs*dpr*acos(clonr)
276 IF (self%WBD > 180.0) self%WBD = self%WBD - 360.0
281 hs2=sign(1._kd,mod(rlon2-self%RLON0+180+3600,360._kd)-180)
282 clon2=cos((rlon2-self%RLON0)/dpr)
283 slatr=self%CLAT0*slat2-self%SLAT0*clat2*clon2
284 clatr=sqrt(1-slatr**2)
285 clonr=(self%CLAT0*clat2*clon2+self%SLAT0*slat2)/clatr
287 ebd=hs2*dpr*acos(clonr)
288 self%DLATS=(nbd-self%SBD)/float(self%JM-1)
289 self%DLONS=(ebd-self%WBD)/float(self%IM-1)
291 IF(i_offset_odd==1) self%WBD=self%WBD+(0.5_kd*self%DLONS)
292 IF(j_offset==1) self%SBD=self%SBD+(0.5_kd*self%DLATS)
298 self%nscan = mod(igdtmpl(19) / 32, 2)
299 self%nscan_field_pos = self%nscan
363 FILL,XPTS,YPTS,RLON,RLAT,NRET, &
364 CROT,SROT,XLON,XLAT,YLON,YLAT,AREA)
368 INTEGER,
INTENT(IN ) :: IOPT, NPTS
369 INTEGER,
INTENT( OUT) :: NRET
371 REAL,
INTENT(IN ) :: FILL
372 REAL,
INTENT(INOUT) :: RLON(NPTS),RLAT(NPTS)
373 REAL,
INTENT(INOUT) :: XPTS(NPTS),YPTS(NPTS)
374 REAL,
OPTIONAL,
INTENT( OUT) :: CROT(NPTS),SROT(NPTS)
375 REAL,
OPTIONAL,
INTENT( OUT) :: XLON(NPTS),XLAT(NPTS)
376 REAL,
OPTIONAL,
INTENT( OUT) :: YLON(NPTS),YLAT(NPTS),AREA(NPTS)
380 LOGICAL :: LROT, LMAP, LAREA
383 REAL(KIND=
kd) :: clonr,clatr,slatr
384 REAL(KIND=
kd) :: clat,slat,clon
385 REAL(KIND=
kd) :: rlatr,rlonr
386 REAL(KIND=
kd) :: wbd,sbd
387 REAL :: XMIN,XMAX,YMIN,YMAX
389 IF(
PRESENT(crot)) crot=fill
390 IF(
PRESENT(srot)) srot=fill
391 IF(
PRESENT(xlon)) xlon=fill
392 IF(
PRESENT(xlat)) xlat=fill
393 IF(
PRESENT(ylon)) ylon=fill
394 IF(
PRESENT(ylat)) ylat=fill
395 IF(
PRESENT(area)) area=fill
437 IF(
PRESENT(crot).AND.
PRESENT(srot))
THEN
442 IF(
PRESENT(xlon).AND.
PRESENT(xlat).AND.
PRESENT(ylon).AND.
PRESENT(ylat))
THEN
447 IF(
PRESENT(area))
THEN
454 IF(iopt.EQ.0.OR.iopt.EQ.1)
THEN
458 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
459 ypts(n).GE.ymin.AND.ypts(n).LE.ymax)
THEN
460 rlonr=wbd+(xpts(n)-1._kd)*
dlons
461 rlatr=sbd+(ypts(n)-1._kd)*
dlats
462 IF(rlonr <= 0._kd)
THEN
476 ELSEIF(slat.GE.1)
THEN
484 clon=min(max(clon,-1._kd),1._kd)
485 rlon(n)=real(mod(
rlon0+hs*dpr*acos(clon)+3600,360._kd))
486 rlat(n)=real(dpr*asin(slat))
490 clat, slat, clon, crot(n), srot(n))
492 clat, slat, clon, xlon(n), xlat(n), ylon(n), ylat(n))
502 ELSEIF(iopt.EQ.-1)
THEN
506 IF(abs(rlon(n)).LE.360.AND.abs(rlat(n)).LE.90)
THEN
507 hs=sign(1._kd,mod(rlon(n)-
rlon0+180+3600,360._kd)-180)
508 clon=cos((rlon(n)-
rlon0)/dpr)
509 slat=sin(rlat(n)/dpr)
510 clat=cos(rlat(n)/dpr)
516 ELSEIF(slatr.GE.1)
THEN
521 clatr=sqrt(1-slatr**2)
523 clonr=min(max(clonr,-1._kd),1._kd)
524 rlonr=hs*dpr*acos(clonr)
525 rlatr=dpr*asin(slatr)
527 xpts(n)=real((rlonr-wbd)/
dlons+1._kd)
528 ypts(n)=real((rlatr-sbd)/
dlats+1._kd)
529 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
530 ypts(n).GE.ymin.AND.ypts(n).LE.ymax)
THEN
533 clat, slat, clon, crot(n), srot(n))
535 clat, slat, clon, xlon(n), xlat(n), ylon(n), ylat(n))
571 INTEGER,
INTENT(IN ) :: IOPT, NPTS
573 REAL,
INTENT(IN ) :: FILL
574 REAL,
INTENT( OUT) :: RLAT(NPTS),RLON(NPTS)
575 REAL,
INTENT( OUT) :: XPTS(NPTS),YPTS(NPTS)
617 REAL(KIND=
kd),
INTENT(IN ) :: clat, clatr, clon, slat, slatr
618 REAL ,
INTENT(IN ) :: RLON
619 REAL ,
INTENT( OUT) :: CROT, SROT
621 REAL(KIND=
kd) :: slon
624 IF(clatr.LE.0._kd)
THEN
625 crot=real(-sign(1._kd,slatr*
slat0))
628 slon=sin((rlon-
rlon0)/dpr)
630 srot=real(
slat0*slon/clatr)
665 SLAT, CLON, XLON, XLAT, YLON, YLAT)
668 REAL(KIND=
kd),
INTENT(IN ) :: clatr, clat, slat, clon
669 REAL ,
INTENT(IN ) :: FILL, RLON
670 REAL ,
INTENT( OUT) :: XLON, XLAT, YLON, YLAT
672 REAL(KIND=
kd) :: slon, term1, term2
674 IF(clatr.LE.0._kd)
THEN
680 slon=sin((rlon-
rlon0)/dpr)
682 term2=
slat0*slon/clatr
683 xlon=real(term1*clat/(
dlons*clatr))
684 xlat=real(-term2/(
dlons*clatr))
685 ylon=real(term2*clat/
dlats)
686 ylat=real(term1/
dlats)
712 REAL(KIND=
kd),
INTENT(IN ) :: clatr
713 REAL,
INTENT(IN ) :: FILL
714 REAL,
INTENT( OUT) :: AREA
716 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.
Determine earth radius and shape.
Module containing common constants.
real, parameter dpr
Radians to degrees.
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 init_grib2_ncep_post(self, g2_desc)
Initializes a Rotated equidistant cylindrical grid given a grib2_descriptor object.
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.
subroutine init_grib2_default(self, g2_desc)
Initializes a Rotated equidistant cylindrical grid given a grib2_descriptor object.
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.