UFO
esg_grid_mod.F90
Go to the documentation of this file.
1 ! (C) Copyright 2020 NOAA NWS NCEP EMC
2 !
3 ! This software is licensed under the terms of the Apache Licence Version 2.0
4 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5 
6 !> Fortran module of helper functions for FV3-LAM ESG grid domain configuration
7 !> These routines are borrowed from regional_esg_grid.fd from the
8 !> RRFS Regional Workflow / UFS_UTILS repository
9 !> Credit goes to R. Jim Purser for original source of these subroutines
10 
12 
13  use kinds
15  implicit none
16  private
17  public :: gtoxm_ak_dd, gtoxm_ak_rr
18 
19  interface gtoxm_ak_rr
20  module procedure gtoxm_ak_rr_m,gtoxm_ak_rr_g; end interface
21  interface gtoxm_ak_dd
22  module procedure gtoxm_ak_dd_g; end interface
23  interface grtoc
24  module procedure dgrtoc
25  end interface
26 
27  logical ,parameter:: t=.true.,f=.false. !<- for pain-relief in logical ops
28 
29 contains
30 
31 !=============================================================================
32 subroutine gtoxm_ak_rr_m(A,K,plat,plon,pazi,lat,lon,xm,ff)! [gtoxm_ak_rr]
33 !=============================================================================
34 ! Given the map specification (angles in radians), the grid spacing (in
35 ! map-space units) and the sample lat-lon (in radian), return the the
36 ! image in map space in a 2-vector in grid units. If the transformation
37 ! is invalid, return a .true. failure flag.
38 !=============================================================================
39 implicit none
40 real(kind_real), intent(in ):: a,k,plat,plon,pazi,lat,lon
41 real(kind_real),dimension(2),intent(out):: xm
42 logical, intent(out):: ff
43 real(kind_real),dimension(3,3):: prot,azirot
44 real(kind_real) :: clat,slat,clon,slon,cazi,sazi
45 real(kind_real),dimension(3) :: xc
46 !=============================================================================
47 clat=cos(plat); slat=sin(plat)
48 clon=cos(plon); slon=sin(plon)
49 cazi=cos(pazi); sazi=sin(pazi)
50 
51 azirot(:,1)=(/ cazi, sazi, zero/)
52 azirot(:,2)=(/-sazi, cazi, zero/)
53 azirot(:,3)=(/ zero, zero, one/)
54 
55 prot(:,1)=(/ -slon, clon, zero/)
56 prot(:,2)=(/-slat*clon, -slat*slon, clat/)
57 prot(:,3)=(/ clat*clon, clat*slon, slat/)
58 prot=matmul(prot,azirot)
59 
60 call grtoc(lat,lon,xc)
61 xc=matmul(transpose(prot),xc)
62 call xctoxm_ak(a,k,xc,xm,ff)
63 end subroutine gtoxm_ak_rr_m
64 !=============================================================================
65 subroutine gtoxm_ak_rr_g(A,K,plat,plon,pazi,delx,dely,lat,lon,&! [gtoxm_ak_rr]
66  xm,ff)
67 !=============================================================================
68 ! Given the map specification (angles in radians), the grid spacing (in
69 ! map-space units) and the sample lat-lon (in radian), return the the
70 ! image in map space in a 2-vector in grid units. If the transformation
71 ! is invalid, return a .true. failure flag.
72 !=============================================================================
73 implicit none
74 real(kind_real), intent(in ):: a,k,plat,plon,pazi,delx,dely,lat,lon
75 real(kind_real),dimension(2),intent(out):: xm
76 logical, intent(out):: ff
77 !=============================================================================
78 call gtoxm_ak_rr_m(a,k,plat,plon,pazi,lat,lon,xm,ff); if(ff)return
79 xm(1)=xm(1)/delx; xm(2)=xm(2)/dely
80 end subroutine gtoxm_ak_rr_g
81 
82 !=============================================================================
83 subroutine gtoxm_ak_dd_g(A,K,pdlat,pdlon,pdazi,delx,dely,&! [gtoxm_ak_dd]
84 dlat,dlon, xm,ff)
85 !=============================================================================
86 ! Like gtoxm_ak_rr_g, except input angles are expressed in degrees
87 !=============================================================================
88 implicit none
89 real(kind_real), intent(in ):: a,k,pdlat,pdlon,pdazi,delx,dely,dlat,dlon
90 real(kind_real),dimension(2),intent(out):: xm
91 logical, intent(out):: ff
92 !-----------------------------------------------------------------------------
93 real(kind_real):: plat,plon,pazi,lat,lon
94 !=============================================================================
95 plat=pdlat*deg2rad ! Convert these angles from degrees to radians
96 plon=pdlon*deg2rad !
97 pazi=pdazi*deg2rad !
98 lat=dlat*deg2rad
99 lon=dlon*deg2rad
100 call gtoxm_ak_rr_g(a,k,plat,plon,pazi,delx,dely,lat,lon,xm,ff)
101 end subroutine gtoxm_ak_dd_g
102 !=============================================================================
103 subroutine xctoxm_ak(a,k,xc,xm,ff)! [xctoxm_ak]
104 !=============================================================================
105 ! Inverse mapping of xmtoxc_ak. That is, go from given cartesian unit
106 ! 3-vector, xc, to map coordinate 2-vector xm (or return a raised failure
107 ! flag, FF, if the attempt fails).
108 !=============================================================================
109 implicit none
110 real(kind_real), intent(in ):: a,k
111 real(kind_real),dimension(3),intent(in ):: xc
112 real(kind_real),dimension(2),intent(out):: xm
113 logical, intent(out):: ff
114 !-----------------------------------------------------------------------------
115 real(kind_real),dimension(2):: xs,xt
116 !=============================================================================
117 ff=f
118 call xctoxs(xc,xs)
119 call xstoxt(k,xs,xt,ff); if(ff)return
120 call xttoxm(a,xt,xm,ff)
121 end subroutine xctoxm_ak
122 !=============================================================================
123 subroutine xctoxs(xc,xs)! [xctoxs]
124 !=============================================================================
125 ! Inverse of xstoxc. I.e., cartesians to stereographic
126 !=============================================================================
127 implicit none
128 real(kind_real),dimension(3),intent(in ):: xc
129 real(kind_real),dimension(2),intent(out):: xs
130 !-----------------------------------------------------------------------------
131 real(kind_real):: zp
132 !=============================================================================
133 zp=one+xc(3); xs=xc(1:2)/zp
134 end subroutine xctoxs
135 !=============================================================================
136 subroutine xstoxt(k,xs,xt,ff)! [xstoxt]
137 !=============================================================================
138 ! Inverse of xttoxs.
139 !=============================================================================
140 implicit none
141 real(kind_real), intent(in ):: k
142 real(kind_real),dimension(2),intent(in ):: xs
143 real(kind_real),dimension(2),intent(out):: xt
144 logical, intent(out):: ff
145 !-----------------------------------------------------------------------------
146 real(kind_real):: s,sc
147 !=============================================================================
148 s=k*(xs(1)*xs(1)+xs(2)*xs(2)); sc=one-s
149 ff=abs(s)>=one; if(ff)return
150 xt=two*xs/sc
151 end subroutine xstoxt
152 !=============================================================================
153 subroutine xttoxm(a,xt,xm,ff)! [xttoxm]
154 !=============================================================================
155 ! Inverse of xmtoxt
156 !=============================================================================
157 implicit none
158 real(kind_real), intent(in ):: a
159 real(kind_real),dimension(2),intent(in ):: xt
160 real(kind_real),dimension(2),intent(out):: xm
161 logical ,intent(out):: ff
162 !-----------------------------------------------------------------------------
163 integer:: i
164 !=============================================================================
165 do i=1,2; call zttozm(a,xt(i),xm(i),ff); if(ff)return; enddo
166 end subroutine xttoxm
167 !=============================================================================
168 subroutine zttozm(a,zt,zm,ff)! [zttozm]
169 !=============================================================================
170 ! Inverse of zmtozt
171 !=============================================================================
172 implicit none
173 real(kind_real),intent(in ):: a,zt
174 real(kind_real),intent(out):: zm
175 logical, intent(out):: ff
176 !-----------------------------------------------------------------------------
177 real(kind_real):: ra,razt
178 !=============================================================================
179 ff=f
180 if (a>zero)then; ra=sqrt( a); razt=ra*zt; zm=atan(razt)/ra
181 elseif(a<zero)then; ra=sqrt(-a); razt=ra*zt; ff=abs(razt)>=one; if(ff)return
182  zm=atanh(razt)/ra
183 else ; zm=zt
184 endif
185 end subroutine zttozm
186 !=============================================================================
187 subroutine dgrtoc(rlat,rlon,xe)! [grtoc]
188 !=============================================================================
189 implicit none
190 real(kind_real), intent(IN ):: rlat,rlon
191 real(kind_real),dimension(3),intent(OUT):: xe
192 !-----------------------------------------------------------------------------
193 real(kind_real) :: sla,cla,slo,clo
194 !=============================================================================
195 sla=sin(rlat); cla=cos(rlat)
196 slo=sin(rlon); clo=cos(rlon)
197 xe(1)=cla*clo; xe(2)=cla*slo; xe(3)=sla
198 end subroutine dgrtoc
199 !=============================================================================
200 
201 
202 end module esg_grid_mod
Fortran module of helper functions for FV3-LAM ESG grid domain configuration These routines are borro...
subroutine gtoxm_ak_rr_g(A, K, plat, plon, pazi, delx, dely, lat, lon, xm, ff)
subroutine xctoxs(xc, xs)
subroutine zttozm(a, zt, zm, ff)
logical, parameter f
subroutine xstoxt(k, xs, xt, ff)
subroutine gtoxm_ak_rr_m(A, K, plat, plon, pazi, lat, lon, xm, ff)
subroutine xctoxm_ak(a, k, xc, xm, ff)
logical, parameter t
subroutine xttoxm(a, xt, xm, ff)
subroutine gtoxm_ak_dd_g(A, K, pdlat, pdlon, pdazi, delx, dely, dlat, dlon, xm, ff)
subroutine dgrtoc(rlat, rlon, xe)
real(kind_real), parameter, public pi
real(kind_real), parameter, public deg2rad
real(kind_real), parameter, public one
real(kind_real), parameter, public zero
real(kind_real), parameter, public two
real(kind_real), parameter, public rad2deg