cpld_gridgen  1.7.0
 All Data Structures Files Functions Variables
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 : mastertask, 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(mastertask .and. 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(mastertask .and. 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(mastertask .and. 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  if(mastertask .and. debug)then
79  j = ny+1
80  i1 = ipolesg(1); i2 = ipolesg(2)-(ipolesg(1)-i1)
81  print *,'replicate X across seam on SG'
82  print *,xsgp1(i1-2,j),xsgp1(i2+2,j)
83  print *,xsgp1(i1-1,j),xsgp1(i2+1,j)
84  print *,xsgp1(i1, j),xsgp1(i2, j)
85  print *,xsgp1(i1+1,j),xsgp1(i2-1,j)
86  print *,xsgp1(i1+2,j),xsgp1(i2-2,j)
87 
88  print *,'replicate Y across seam on SG'
89  print *,ysgp1(i1-2,j),ysgp1(i2+2,j)
90  print *,ysgp1(i1-1,j),ysgp1(i2+1,j)
91  print *,ysgp1(i1, j),ysgp1(i2, j)
92  print *,ysgp1(i1+1,j),ysgp1(i2-1,j)
93  print *,ysgp1(i1+2,j),ysgp1(i2-2,j)
94  end if
95 
96 !---------------------------------------------------------------------
97 ! rotation angle on supergrid vertices
98 ! lonB: x(i-1,j-1) has same relationship to x(i,j) on SG as
99 ! geolonT(i,j) has to geolonBu(i,j) on the reduced grid
100 !---------------------------------------------------------------------
101 
102  ! constants as defined in MOM
103  pi_720deg = atan(1.0) / 180.0
104  len_lon = 360.0
105  do j=1,ny ; do i=1,nx-1
106  do n=1,2 ; do m=1,2
107  lonb(m,n) = modulo_around_point(xsgp1(i+m-2,j+n-2), xsgp1(i-1,j-1), len_lon)
108  enddo ; enddo
109  lon_scale = cos(pi_720deg*(ysgp1(i-1,j-1) + ysgp1(i+1,j-1) + &
110  ysgp1(i-1,j+1) + ysgp1(i+1,j+1)) )
111  angq(i,j) = atan2(lon_scale*((lonb(1,2) - lonb(2,1)) + (lonb(2,2) - lonb(1,1))), &
112  ysgp1(i-1,j+1) + ysgp1(i+1,j+1) - &
113  ysgp1(i-1,j-1) - ysgp1(i+1,j-1) )
114  enddo ; enddo
115 
116  !check
117  if(mastertask .and. debug) then
118  j = ny
119  i1 = ipolesg(1); i2 = ipolesg(2)-(ipolesg(1)-i1)
120  print *,'angq along seam on SG'
121  print *,angq(i1-2,j),angq(i2+2,j)
122  print *,angq(i1-1,j),angq(i2+1,j)
123  print *,angq(i1, j),angq(i2, j)
124  print *,angq(i1+1,j),angq(i2-1,j)
125  print *,angq(i1+2,j),angq(i2-2,j)
126  end if
127 
128  end subroutine find_angq
129 
133  subroutine find_ang
134 
135  ! local variables
136  integer :: i,j,m,n
137  integer :: ii,jj
138 
139  ! from geolonB fix in MOM6
140  real(dbl_kind) :: len_lon ! The periodic range of longitudes, usually 360 degrees.
141  real(dbl_kind) :: pi_720deg ! One quarter the conversion factor from degrees to radians.
142  real(dbl_kind) :: lonb(2,2) ! The longitude of a point, shifted to have about the same value.
143  real(dbl_kind) :: lon_scale = 0.0
144 
145 !---------------------------------------------------------------------
146 ! rotation angle for "use_bugs" = false case from MOM6
147 ! src/initialization/MOM_shared_initialization.F90 but allow for not
148 ! having halo values
149 ! note this does not reproduce sin_rot,cos_rot found in MOM6 output
150 ! differences are ~O 10-6
151 !---------------------------------------------------------------------
152 
153  anglet = 0.0
154  pi_720deg = atan(1.0) / 180.0
155  len_lon = 360.0
156  do j=1,nj; do i = 1,ni
157  do n=1,2 ; do m=1,2
158  jj = j+n-2; ii = i+m-2
159  if(jj .eq. 0)jj = 1
160  if(ii .eq. 0)ii = ni
161  lonb(m,n) = modulo_around_point(lonbu(ii,jj), lonct(i,j), len_lon)
162  ! lonB(m,n) = modulo_around_point(LonBu(I+m-2,J+n-2), LonCt(i,j), len_lon)
163  enddo ; enddo
164  jj = j-1; ii = i-1
165  if(jj .eq. 0)jj = 1
166  if(ii .eq. 0)ii = ni
167  lon_scale = cos(pi_720deg*((latbu(ii,jj) + latbu(i,j)) + &
168  (latbu(i,jj) + latbu(ii,j)) ) )
169  anglet(i,j) = atan2(lon_scale*((lonb(1,2) - lonb(2,1)) + (lonb(2,2) - lonb(1,1))), &
170  (latbu(ii,j) - latbu(i,jj)) + &
171  (latbu(i,j) - latbu(ii,jj)) )
172 
173  !lon_scale = cos(pi_720deg*((LatBu(I-1,J-1) + LatBu(I,J)) + &
174  ! (LatBu(I,J-1) + LatBu(I-1,J)) ) )
175  !anglet(i,j) = atan2(lon_scale*((lonB(1,2) - lonB(2,1)) + (lonB(2,2) - lonB(1,1))), &
176  ! (LatBu(I-1,J) - LatBu(I,J-1)) + &
177  ! (LatBu(I,J) - LatBu(I-1,J-1)) )
178  enddo ; enddo
179 
180  end subroutine find_ang
181 ! -----------------------------------------------------------------------------
190  function modulo_around_point(x, xc, Lx) result(x_mod)
191  use gengrid_kinds, only : dbl_kind
192 
193  real(dbl_kind), intent(in) :: x
194  real(dbl_kind), intent(in) :: xc
195  real(dbl_kind), intent(in) :: lx
196  real(dbl_kind) :: x_mod
197 
198  if (lx > 0.0) then
199  x_mod = modulo(x - (xc - 0.5*lx), lx) + (xc - 0.5*lx)
200  else
201  x_mod = x
202  endif
203  end function modulo_around_point
204 end module angles
subroutine find_ang
Find the rotation angle on center (Ct) grid points.
Definition: angles.F90:133
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:190
subroutine find_angq
Find the rotation angle on corner grid (Bu) points using the full MOM6 supergrid. ...
Definition: angles.F90:25