1module ip_rot_equid_cylind_grid_mod
2 use iso_fortran_env,
only: real64
12 integer,
parameter :: kd = real64
15 real(kd) :: clat0, dlats, dlons, rlon0, slat0, wbd, sbd
18 procedure :: init_grib1
19 procedure :: init_grib2
20 procedure :: gdswzd => gdswzd_rot_equid_cylind
25 REAL(KIND=kd) :: rerth
26 REAL(KIND=kd) :: clat0, dlats, dlons
27 REAL(KIND=kd) :: rlon0, slat0
32 subroutine init_grib1(self, g1_desc)
33 class(ip_rot_equid_cylind_grid),
intent(inout) :: self
34 type(grib1_descriptor),
intent(in) :: g1_desc
36 real(kd) :: rlat1, rlon1, rlat0, rlat2, rlon2, nbd, ebd
37 real(kd) :: hs, hs2, slat1, slat2, slatr, clon1, clon2, clat1, clat2, clatr, clonr, rlonr, rlatr
40 associate(kgds => g1_desc%gds)
41 self%rerth = 6.3712e6_kd
42 self%eccen_squared = 0d0
44 rlat1=kgds(4)*1.e-3_kd
45 rlon1=kgds(5)*1.e-3_kd
46 rlat0=kgds(7)*1.e-3_kd
47 self%RLON0=kgds(8)*1.e-3_kd
48 rlat2=kgds(12)*1.e-3_kd
49 rlon2=kgds(13)*1.e-3_kd
51 self%IROT=mod(kgds(6)/8,2)
57 self%SLAT0=sin(rlat0/
dpr)
58 self%CLAT0=cos(rlat0/
dpr)
60 hs=sign(1._kd,mod(rlon1-self%RLON0+180+3600,360._kd)-180)
61 clon1=cos((rlon1-self%RLON0)/
dpr)
62 slatr=self%CLAT0*slat1-self%SLAT0*clat1*clon1
63 clatr=sqrt(1-slatr**2)
64 clonr=(self%CLAT0*clat1*clon1+self%SLAT0*slat1)/clatr
66 rlonr=hs*
dpr*acos(clonr)
72 hs2=sign(1._kd,mod(rlon2-self%RLON0+180+3600,360._kd)-180)
73 clon2=cos((rlon2-self%RLON0)/
dpr)
74 slatr=self%CLAT0*slat2-self%SLAT0*clat2*clon2
75 clatr=sqrt(1-slatr**2)
76 clonr=(self%CLAT0*clat2*clon2+self%SLAT0*slat2)/clatr
78 ebd=hs2*
dpr*acos(clonr)
79 self%DLATS=(nbd-self%SBD)/float(self%JM-1)
80 self%DLONS=(ebd-self%WBD)/float(self%IM-1)
85 self%nscan = mod(kgds(11) / 32, 2)
86 self%nscan_field_pos = self%nscan
90 end subroutine init_grib1
92 subroutine init_grib2(self, g2_desc)
93 class(ip_rot_equid_cylind_grid),
intent(inout) :: self
94 type(grib2_descriptor),
intent(in) :: g2_desc
96 real(kd) :: rlat1, rlon1, rlat0, rlat2, rlon2, nbd, ebd
98 integer :: i_offset_odd, i_offset_even, j_offset
100 associate(igdtmpl => g2_desc%gdt_tmpl, igdtlen => g2_desc%gdt_len)
102 CALL earth_radius(igdtmpl,igdtlen,self%rerth,self%eccen_squared)
104 i_offset_odd=mod(igdtmpl(19)/8,2)
105 i_offset_even=mod(igdtmpl(19)/4,2)
106 j_offset=mod(igdtmpl(19)/2,2)
108 iscale=igdtmpl(10)*igdtmpl(11)
109 IF(iscale==0) iscale=10**6
111 rlat1=float(igdtmpl(12))/float(iscale)
112 rlon1=float(igdtmpl(13))/float(iscale)
113 rlat0=float(igdtmpl(20))/float(iscale)
116 self%RLON0=float(igdtmpl(21))/float(iscale)
118 rlat2=float(igdtmpl(15))/float(iscale)
119 rlon2=float(igdtmpl(16))/float(iscale)
121 self%IROT=mod(igdtmpl(14)/8,2)
125 self%SLAT0=sin(rlat0/dpr)
126 self%CLAT0=cos(rlat0/dpr)
129 IF (self%WBD > 180.0) self%WBD = self%WBD - 360.0
135 self%DLATS=(nbd-self%SBD)/float(self%JM-1)
136 self%DLONS=(ebd-self%WBD)/float(self%IM-1)
138 IF(i_offset_odd==1) self%WBD=self%WBD+(0.5_kd*self%DLONS)
139 IF(j_offset==1) self%SBD=self%SBD+(0.5_kd*self%DLATS)
145 self%nscan = mod(igdtmpl(19) / 32, 2)
146 self%nscan_field_pos = self%nscan
148 end subroutine init_grib2
152 SUBROUTINE gdswzd_rot_equid_cylind(self,IOPT,NPTS, &
153 FILL,XPTS,YPTS,RLON,RLAT,NRET, &
154 CROT,SROT,XLON,XLAT,YLON,YLAT,AREA)
278 class(ip_rot_equid_cylind_grid),
intent(in) :: self
279 INTEGER,
INTENT(IN ) :: IOPT, NPTS
280 INTEGER,
INTENT( OUT) :: NRET
282 REAL,
INTENT(IN ) :: FILL
283 REAL,
INTENT(INOUT) :: RLON(NPTS),RLAT(NPTS)
284 REAL,
INTENT(INOUT) :: XPTS(NPTS),YPTS(NPTS)
285 REAL,
OPTIONAL,
INTENT( OUT) :: CROT(NPTS),SROT(NPTS)
286 REAL,
OPTIONAL,
INTENT( OUT) :: XLON(NPTS),XLAT(NPTS)
287 REAL,
OPTIONAL,
INTENT( OUT) :: YLON(NPTS),YLAT(NPTS),AREA(NPTS)
291 LOGICAL :: LROT, LMAP, LAREA
295 REAL(KIND=kd) :: clonr,clatr,slatr
296 REAL(KIND=kd) :: clat,slat,clon
297 REAL(KIND=kd) :: rlatr,rlonr
298 REAL(KIND=kd) :: wbd,sbd
299 REAL :: XMIN,XMAX,YMIN,YMAX
301 IF(
PRESENT(crot)) crot=fill
302 IF(
PRESENT(srot)) srot=fill
303 IF(
PRESENT(xlon)) xlon=fill
304 IF(
PRESENT(xlat)) xlat=fill
305 IF(
PRESENT(ylon)) ylon=fill
306 IF(
PRESENT(ylat)) ylat=fill
307 IF(
PRESENT(area)) area=fill
345 CALL rot_equid_cylind_error(iopt,fill,rlat,rlon,xpts,ypts,npts)
349 IF(
PRESENT(crot).AND.
PRESENT(srot))
THEN
354 IF(
PRESENT(xlon).AND.
PRESENT(xlat).AND.
PRESENT(ylon).AND.
PRESENT(ylat))
THEN
359 IF(
PRESENT(area))
THEN
366 IF(iopt.EQ.0.OR.iopt.EQ.1)
THEN
370 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
371 ypts(n).GE.ymin.AND.ypts(n).LE.ymax)
THEN
372 rlonr=wbd+(xpts(n)-1._kd)*dlons
373 rlatr=sbd+(ypts(n)-1._kd)*dlats
374 IF(rlonr <= 0._kd)
THEN
382 slat=clat0*slatr+slat0*clatr*clonr
388 ELSEIF(slat.GE.1)
THEN
395 clon=(clat0*clatr*clonr-slat0*slatr)/clat
396 clon=min(max(clon,-1._kd),1._kd)
397 rlon(n)=mod(rlon0+hs*dpr*acos(clon)+3600,360._kd)
398 rlat(n)=dpr*asin(slat)
401 IF(lrot)
CALL rot_equid_cylind_vect_rot(rlon(n), clatr, slatr, &
402 clat, slat, clon, crot(n), srot(n))
403 IF(lmap)
CALL rot_equid_cylind_map_jacob(fill, rlon(n), clatr, &
404 clat, slat, clon, xlon(n), xlat(n), ylon(n), ylat(n))
405 IF(larea)
CALL rot_equid_cylind_grid_area(clatr, fill, area(n))
414 ELSEIF(iopt.EQ.-1)
THEN
418 IF(abs(rlon(n)).LE.360.AND.abs(rlat(n)).LE.90)
THEN
419 hs=sign(1._kd,mod(rlon(n)-rlon0+180+3600,360._kd)-180)
420 clon=cos((rlon(n)-rlon0)/dpr)
421 slat=sin(rlat(n)/dpr)
422 clat=cos(rlat(n)/dpr)
423 slatr=clat0*slat-slat0*clat*clon
428 ELSEIF(slatr.GE.1)
THEN
433 clatr=sqrt(1-slatr**2)
434 clonr=(clat0*clat*clon+slat0*slat)/clatr
435 clonr=min(max(clonr,-1._kd),1._kd)
436 rlonr=hs*dpr*acos(clonr)
437 rlatr=dpr*asin(slatr)
439 xpts(n)=(rlonr-wbd)/dlons+1._kd
440 ypts(n)=(rlatr-sbd)/dlats+1._kd
441 IF(xpts(n).GE.xmin.AND.xpts(n).LE.xmax.AND. &
442 ypts(n).GE.ymin.AND.ypts(n).LE.ymax)
THEN
444 IF(lrot)
CALL rot_equid_cylind_vect_rot(rlon(n), clatr, slatr, &
445 clat, slat, clon, crot(n), srot(n))
446 IF(lmap)
CALL rot_equid_cylind_map_jacob(fill, rlon(n), clatr, &
447 clat, slat, clon, xlon(n), xlat(n), ylon(n), ylat(n))
448 IF(larea)
CALL rot_equid_cylind_grid_area(clatr, fill, area(n))
461 END SUBROUTINE gdswzd_rot_equid_cylind
463 SUBROUTINE rot_equid_cylind_error(IOPT,FILL,RLAT,RLON,XPTS,YPTS,NPTS)
496 INTEGER,
INTENT(IN ) :: IOPT, NPTS
498 REAL,
INTENT(IN ) :: FILL
499 REAL,
INTENT( OUT) :: RLAT(NPTS),RLON(NPTS)
500 REAL,
INTENT( OUT) :: XPTS(NPTS),YPTS(NPTS)
511 END SUBROUTINE rot_equid_cylind_error
513 SUBROUTINE rot_equid_cylind_vect_rot(RLON, CLATR, SLATR, CLAT, SLAT, &
557 REAL(KIND=kd),
INTENT(IN ) :: clat, clatr, clon, slat, slatr
558 REAL ,
INTENT(IN ) :: RLON
559 REAL ,
INTENT( OUT) :: CROT, SROT
561 REAL(KIND=kd) :: slon
564 IF(clatr.LE.0._kd)
THEN
565 crot=-sign(1._kd,slatr*slat0)
568 slon=sin((rlon-rlon0)/dpr)
569 crot=(clat0*clat+slat0*slat*clon)/clatr
570 srot=slat0*slon/clatr
577 END SUBROUTINE rot_equid_cylind_vect_rot
579 SUBROUTINE rot_equid_cylind_map_jacob(FILL, RLON, CLATR, CLAT, &
580 SLAT, CLON, XLON, XLAT, YLON, YLAT)
623 REAL(KIND=kd),
INTENT(IN ) :: clatr, clat, slat, clon
624 REAL ,
INTENT(IN ) :: FILL, RLON
625 REAL ,
INTENT( OUT) :: XLON, XLAT, YLON, YLAT
627 REAL(KIND=kd) :: slon, term1, term2
629 IF(clatr.LE.0._kd)
THEN
635 slon=sin((rlon-rlon0)/dpr)
636 term1=(clat0*clat+slat0*slat*clon)/clatr
637 term2=slat0*slon/clatr
638 xlon=term1*clat/(dlons*clatr)
639 xlat=-term2/(dlons*clatr)
640 ylon=term2*clat/dlats
644 END SUBROUTINE rot_equid_cylind_map_jacob
646 SUBROUTINE rot_equid_cylind_grid_area(CLATR, FILL, AREA)
680 REAL(KIND=kd),
INTENT(IN ) :: clatr
681 REAL,
INTENT(IN ) :: FILL
682 REAL,
INTENT( OUT) :: AREA
684 IF(clatr.LE.0._kd)
THEN
687 area=2._kd*(rerth**2)*clatr*(dlons/dpr)*sin(0.5_kd*dlats/dpr)
690 END SUBROUTINE rot_equid_cylind_grid_area
692end module ip_rot_equid_cylind_grid_mod
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...
Abstract grid that holds fields and methods common to all grids.