cpld_gridgen  1.13.0
 All Data Structures Files Functions Variables Pages
angles.F90
Go to the documentation of this file.
1 
9 
10 module angles
11 
12  use gengrid_kinds, only : dbl_kind, int_kind
13  use grdvars, only : ni,nj,nx,ny
14  use grdvars, only : x,y,xsgp1,ysgp1,sg_maxlat
15  use grdvars, only : latbu,lonbu,lonct
16  use grdvars, only : angq,anglet
17  use grdvars, only : debug
18 
19  implicit none
20 
21 contains
25  subroutine find_angq
26 
27  ! local variables
28  integer :: i,j,i1,i2,m,n
29 
30  ! pole locations on SG
31  integer(int_kind) :: ipolesg(2)
32 
33  ! from geolonB fix in MOM6
34  real(dbl_kind) :: len_lon ! The periodic range of longitudes, usually 360 degrees.
35  real(dbl_kind) :: pi_720deg ! One quarter the conversion factor from degrees to radians.
36  real(dbl_kind) :: lonb(2,2) ! The longitude of a point, shifted to have about the same value.
37  real(dbl_kind) :: lon_scale = 0.0
38 
39  !---------------------------------------------------------------------
40  ! to find angleq on seam, replicate supergrid values across seam
41  !---------------------------------------------------------------------
42 
43  angq = 0.0
44  xsgp1 = 0.0; ysgp1 = 0.0
45  !pole on supergrid
46  ipolesg = -1
47  j = ny
48  do i = 1,nx/2
49  if(y(i,j) .eq. sg_maxlat)ipolesg(1) = i
50  enddo
51  do i = nx/2+1,nx
52  if(y(i,j) .eq. sg_maxlat)ipolesg(2) = i
53  enddo
54  if(debug)print *,'poles found at ',ipolesg
55 
56  xsgp1(:,0:ny) = x(:,0:ny)
57  ysgp1(:,0:ny) = y(:,0:ny)
58 
59  !check
60  do i = ipolesg(1)-5,ipolesg(1)+5
61  i2 = ipolesg(2)+(ipolesg(1)-i)+1
62  if(debug)print *,i,i2
63  enddo
64  print *
65  do i = ipolesg(2)-5,ipolesg(2)+5
66  i2 = ipolesg(2)+(ipolesg(1)-i)+1
67  if(debug)print *,i,i2
68  enddo
69 
70  !replicate supergrid across pole
71  do i = 1,nx
72  i2 = ipolesg(2)+(ipolesg(1)-i)
73  xsgp1(i,ny+1) = xsgp1(i2,ny)
74  ysgp1(i,ny+1) = ysgp1(i2,ny)
75  enddo
76 
77  !check
78  j = ny+1
79  i1 = ipolesg(1); i2 = ipolesg(2)-(ipolesg(1)-i1)
80  print *,'replicate X across seam on SG'
81  print *,xsgp1(i1-2,j),xsgp1(i2+2,j)
82  print *,xsgp1(i1-1,j),xsgp1(i2+1,j)
83  print *,xsgp1(i1, j),xsgp1(i2, j)
84  print *,xsgp1(i1+1,j),xsgp1(i2-1,j)
85  print *,xsgp1(i1+2,j),xsgp1(i2-2,j)
86 
87  print *,'replicate Y across seam on SG'
88  print *,ysgp1(i1-2,j),ysgp1(i2+2,j)
89  print *,ysgp1(i1-1,j),ysgp1(i2+1,j)
90  print *,ysgp1(i1, j),ysgp1(i2, j)
91  print *,ysgp1(i1+1,j),ysgp1(i2-1,j)
92  print *,ysgp1(i1+2,j),ysgp1(i2-2,j)
93 
94  !---------------------------------------------------------------------
95  ! rotation angle on supergrid vertices
96  ! lonB: x(i-1,j-1) has same relationship to x(i,j) on SG as
97  ! geolonT(i,j) has to geolonBu(i,j) on the reduced grid
98  !---------------------------------------------------------------------
99 
100  ! constants as defined in MOM
101  pi_720deg = atan(1.0) / 180.0
102  len_lon = 360.0
103  do j=1,ny ; do i=1,nx-1
104  do n=1,2 ; do m=1,2
105  lonb(m,n) = modulo_around_point(xsgp1(i+m-2,j+n-2), xsgp1(i-1,j-1), len_lon)
106  enddo; enddo
107  lon_scale = cos(pi_720deg*(ysgp1(i-1,j-1) + ysgp1(i+1,j-1) + &
108  ysgp1(i-1,j+1) + ysgp1(i+1,j+1)) )
109  angq(i,j) = atan2(lon_scale*((lonb(1,2) - lonb(2,1)) + (lonb(2,2) - lonb(1,1))), &
110  ysgp1(i-1,j+1) + ysgp1(i+1,j+1) - &
111  ysgp1(i-1,j-1) - ysgp1(i+1,j-1) )
112  enddo; enddo
113 
114  !check
115  if(debug) then
116  j = ny
117  i1 = ipolesg(1); i2 = ipolesg(2)-(ipolesg(1)-i1)
118  print *,'angq along seam on SG'
119  print *,angq(i1-2,j),angq(i2+2,j)
120  print *,angq(i1-1,j),angq(i2+1,j)
121  print *,angq(i1, j),angq(i2, j)
122  print *,angq(i1+1,j),angq(i2-1,j)
123  print *,angq(i1+2,j),angq(i2-2,j)
124  end if
125 
126  end subroutine find_angq
127 
131  subroutine find_ang
132 
133  ! local variables
134  integer :: i,j,m,n
135  integer :: ii,jj
136 
137  ! from geolonB fix in MOM6
138  real(dbl_kind) :: len_lon ! The periodic range of longitudes, usually 360 degrees.
139  real(dbl_kind) :: pi_720deg ! One quarter the conversion factor from degrees to radians.
140  real(dbl_kind) :: lonb(2,2) ! The longitude of a point, shifted to have about the same value.
141  real(dbl_kind) :: lon_scale = 0.0
142 
143  !---------------------------------------------------------------------
144  ! rotation angle for "use_bugs" = false case from MOM6
145  ! src/initialization/MOM_shared_initialization.F90 but allow for not
146  ! having halo values
147  ! note this does not reproduce sin_rot,cos_rot found in MOM6 output
148  ! differences are ~O 10-6
149  !---------------------------------------------------------------------
150 
151  anglet = 0.0
152  pi_720deg = atan(1.0) / 180.0
153  len_lon = 360.0
154  do j=1,nj; do i = 1,ni
155  do n=1,2 ; do m=1,2
156  jj = j+n-2; ii = i+m-2
157  if(jj .eq. 0)jj = 1
158  if(ii .eq. 0)ii = ni
159  lonb(m,n) = modulo_around_point(lonbu(ii,jj), lonct(i,j), len_lon)
160  ! lonB(m,n) = modulo_around_point(LonBu(I+m-2,J+n-2), LonCt(i,j), len_lon)
161  enddo; enddo
162  jj = j-1; ii = i-1
163  if(jj .eq. 0)jj = 1
164  if(ii .eq. 0)ii = ni
165  lon_scale = cos(pi_720deg*((latbu(ii,jj) + latbu(i,j)) + &
166  (latbu(i,jj) + latbu(ii,j)) ) )
167  anglet(i,j) = atan2(lon_scale*((lonb(1,2) - lonb(2,1)) + (lonb(2,2) - lonb(1,1))), &
168  (latbu(ii,j) - latbu(i,jj)) + &
169  (latbu(i,j) - latbu(ii,jj)) )
170 
171  !lon_scale = cos(pi_720deg*((LatBu(I-1,J-1) + LatBu(I,J)) + &
172  ! (LatBu(I,J-1) + LatBu(I-1,J)) ) )
173  !anglet(i,j) = atan2(lon_scale*((lonB(1,2) - lonB(2,1)) + (lonB(2,2) - lonB(1,1))), &
174  ! (LatBu(I-1,J) - LatBu(I,J-1)) + &
175  ! (LatBu(I,J) - LatBu(I-1,J-1)) )
176  enddo; enddo
177 
178  end subroutine find_ang
179  ! -----------------------------------------------------------------------------
188  function modulo_around_point(x, xc, Lx) result(x_mod)
189  use gengrid_kinds, only : dbl_kind
190 
191  real(dbl_kind), intent(in) :: x
192  real(dbl_kind), intent(in) :: xc
193  real(dbl_kind), intent(in) :: lx
194  real(dbl_kind) :: x_mod
195 
196  if (lx > 0.0) then
197  x_mod = modulo(x - (xc - 0.5*lx), lx) + (xc - 0.5*lx)
198  else
199  x_mod = x
200  endif
201  end function modulo_around_point
202 end module angles
subroutine find_ang
Find the rotation angle on center (Ct) grid points.
Definition: angles.F90:131
real(dbl_kind) function modulo_around_point(x, xc, Lx)
Return the modulo value of x in an interval [xc-(Lx/2) xc+(Lx/2)] If Lx<=0, then it returns x without...
Definition: angles.F90:188
subroutine find_angq
Find the rotation angle on corner grid (Bu) points using the full MOM6 supergrid. ...
Definition: angles.F90:25