FV3 Bundle
fv_grid_utils_tlm.F90
Go to the documentation of this file.
1 !***********************************************************************
2 !* GNU General Public License *
3 !* This file is a part of fvGFS. *
4 !* *
5 !* fvGFS is free software; you can redistribute it and/or modify it *
6 !* and are expected to follow the terms of the GNU General Public *
7 !* License as published by the Free Software Foundation; either *
8 !* version 2 of the License, or (at your option) any later version. *
9 !* *
10 !* fvGFS is distributed in the hope that it will be useful, but *
11 !* WITHOUT ANY WARRANTY; without even the implied warranty of *
12 !* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
13 !* General Public License for more details. *
14 !* *
15 !* For the full text of the GNU General Public License, *
16 !* write to: Free Software Foundation, Inc., *
17 !* 675 Mass Ave, Cambridge, MA 02139, USA. *
18 !* or see: http://www.gnu.org/licenses/gpl.html *
19 !***********************************************************************
21 
22 #include <fms_platform.h>
23  use constants_mod, only: omega, pi=>pi_8, cnst_radius=>radius
24  use mpp_mod, only: fatal, mpp_error, warning
25  use external_sst_nlm_mod, only: i_sst, j_sst, sst_ncep, sst_anom
28  use mpp_domains_mod, only: bitwise_exact_sum, domain2d, bitwise_efp_sum
29  use mpp_parameter_mod, only: agrid_param=>agrid, cgrid_ne_param=>cgrid_ne
31 
33  r_grid
34  use fv_eta_nlm_mod, only: set_eta
35  use fv_mp_nlm_mod, only: ng, is_master
36  use fv_mp_nlm_mod, only: mp_reduce_sum, mp_reduce_min, mp_reduce_max
37  use fv_mp_nlm_mod, only: fill_corners, xdir, ydir
39 
40  implicit none
41  private
42  logical:: symm_grid
43 #ifdef NO_QUAD_PRECISION
44 ! 64-bit precision (kind=8)
45  integer, parameter:: f_p = selected_real_kind(15)
46 #else
47 ! Higher precision (kind=16) for grid geometrical factors:
48  integer, parameter:: f_p = selected_real_kind(20)
49 #endif
50  real, parameter:: big_number=1.d8
51  real, parameter:: tiny_number=1.d-8
52 
53  real(kind=R_GRID) :: radius=cnst_radius
54 
55  real, parameter:: ptop_min=1.d-8
56 
57  public f_p
58  public ptop_min, big_number !CLEANUP: OK to keep since they are constants?
59 ! public cos_angle
60 ! public latlon2xyz, gnomonic_grids, &
61 ! global_mx, unit_vect_latlon, &
62 ! cubed_to_latlon, c2l_ord2, g_sum, global_qsum, great_circle_dist, &
63 ! v_prod, get_unit_vect2, project_sphere_v
64 ! public mid_pt_sphere, mid_pt_cart, vect_cross, grid_utils_init, grid_utils_end, &
65 ! spherical_angle, cell_center2, get_area, inner_prod, fill_ghost, direct_transform, &
66 ! make_eta_level, expand_cell, cart_to_latlon, intp_great_circle, normalize_vect, &
67 ! dist2side_latlon, spherical_linear_interpolation, get_latlon_vector
68 ! public symm_grid
69 
71 public c2l_ord2_tlm, g_sum_tlm
72 
73 ! INTERFACE fill_ghost
74 !#ifdef OVERLOAD_R4
75 ! MODULE PROCEDURE fill_ghost_r4
76 !#endif
77 ! MODULE PROCEDURE fill_ghost_r8
78 ! END INTERFACE
79 
80 CONTAINS
81  SUBROUTINE grid_utils_init(atm, npx, npy, npz, non_ortho, grid_type, &
82 & c2l_order)
83  IMPLICIT NONE
84 ! Initialize 2D memory and geometrical factors
85  TYPE(FV_ATMOS_TYPE), INTENT(INOUT), TARGET :: atm
86  LOGICAL, INTENT(IN) :: non_ortho
87  INTEGER, INTENT(IN) :: npx, npy, npz
88  INTEGER, INTENT(IN) :: grid_type, c2l_order
89  END SUBROUTINE grid_utils_init
90  SUBROUTINE grid_utils_end()
91  IMPLICIT NONE
92  END SUBROUTINE grid_utils_end
93  REAL FUNCTION great_circle_dist(q1, q2, radius)
94  IMPLICIT NONE
95  REAL(kind=r_grid), INTENT(IN) :: q1(2), q2(2)
96  REAL(kind=r_grid), INTENT(IN), OPTIONAL :: radius
97  REAL(f_p) :: p1(2), p2(2)
98  REAL(f_p) :: beta
99  INTEGER :: n
100  INTRINSIC sin
101  INTRINSIC cos
102  INTRINSIC sqrt
103  INTRINSIC asin
104  INTRINSIC PRESENT
105  REAL(f_p) :: arg1
106  REAL(f_p) :: arg2
107  REAL(f_p) :: arg3
108  REAL(f_p) :: result1
109  REAL(f_p) :: result2
110  DO n=1,2
111  p1(n) = q1(n)
112  p2(n) = q2(n)
113  END DO
114  arg1 = (p1(2)-p2(2))/2.
115  arg2 = (p1(1)-p2(1))/2.
116  arg3 = sin(arg1)**2 + cos(p1(2))*cos(p2(2))*sin(arg2)**2
117  result1 = sqrt(arg3)
118  result2 = asin(result1)
119  beta = result2*2.
120  IF (PRESENT(radius)) THEN
122  ELSE
123 ! Returns the angle
124  great_circle_dist = beta
125  END IF
126  END FUNCTION great_circle_dist
127  SUBROUTINE cubed_to_latlon(u, v, ua, va, gridstruct, npx, npy, km, &
128 & mode, grid_type, domain, nested, c2l_ord, bd)
129  IMPLICIT NONE
130  TYPE(fv_grid_bounds_type), INTENT(IN) :: bd
131  INTEGER, INTENT(IN) :: km, npx, npy, grid_type, c2l_ord
132 ! update if present
133  INTEGER, INTENT(IN) :: mode
134  TYPE(fv_grid_type), INTENT(IN) :: gridstruct
135  REAL, INTENT(INOUT) :: u(bd%isd:bd%ied, bd%jsd:bd%jed+1, km)
136  REAL, INTENT(INOUT) :: v(bd%isd:bd%ied+1, bd%jsd:bd%jed, km)
137  REAL, INTENT(OUT) :: ua(bd%isd:bd%ied, bd%jsd:bd%jed, km)
138  REAL, INTENT(OUT) :: va(bd%isd:bd%ied, bd%jsd:bd%jed, km)
139  TYPE(domain2d), INTENT(INOUT) :: domain
140  LOGICAL, INTENT(IN) :: nested
141  IF (c2l_ord .EQ. 2) THEN
142  CALL c2l_ord2(u, v, ua, va, gridstruct, km, grid_type, bd, .false.&
143 & )
144  ELSE
145  CALL c2l_ord4(u, v, ua, va, gridstruct, npx, npy, km, grid_type, &
146 & domain, nested, mode, bd)
147  END IF
148  END SUBROUTINE cubed_to_latlon
149  SUBROUTINE c2l_ord4(u, v, ua, va, gridstruct, npx, npy, km, grid_type&
150 & , domain, nested, mode, bd)
151  IMPLICIT NONE
152  TYPE(FV_GRID_BOUNDS_TYPE), INTENT(IN) :: bd
153  INTEGER, INTENT(IN) :: km, npx, npy, grid_type
154 ! update if present
155  INTEGER, INTENT(IN) :: mode
156  TYPE(FV_GRID_TYPE), INTENT(IN), TARGET :: gridstruct
157  REAL, INTENT(INOUT) :: u(bd%isd:bd%ied, bd%jsd:bd%jed+1, km)
158  REAL, INTENT(INOUT) :: v(bd%isd:bd%ied+1, bd%jsd:bd%jed, km)
159  REAL, INTENT(OUT) :: ua(bd%isd:bd%ied, bd%jsd:bd%jed, km)
160  REAL, INTENT(OUT) :: va(bd%isd:bd%ied, bd%jsd:bd%jed, km)
161  TYPE(DOMAIN2D), INTENT(INOUT) :: domain
162  LOGICAL, INTENT(IN) :: nested
163 ! Local
164 ! 4-pt Lagrange interpolation
165  REAL, SAVE :: a1=0.5625
166  REAL, SAVE :: a2=-0.0625
167  REAL, SAVE :: c1=1.125
168  REAL, SAVE :: c2=-0.125
169  REAL :: utmp(bd%is:bd%ie, bd%js:bd%je+1)
170  REAL :: vtmp(bd%is:bd%ie+1, bd%js:bd%je)
171  REAL :: wu(bd%is:bd%ie, bd%js:bd%je+1)
172  REAL :: wv(bd%is:bd%ie+1, bd%js:bd%je)
173  INTEGER :: i, j, k
174  INTEGER :: is, ie, js, je
175  INTRINSIC max
176  INTRINSIC min
177  INTEGER :: max1
178  INTEGER :: max2
179  INTEGER :: max3
180  INTEGER :: max4
181  INTEGER :: min1
182  INTEGER :: min2
183  INTEGER :: min3
184  INTEGER :: min4
185  is = bd%is
186  ie = bd%ie
187  js = bd%js
188  je = bd%je
189  IF (mode .GT. 0) THEN
190  CALL timing_on('COMM_TOTAL')
191  CALL mpp_update_domains(u, v, domain, gridtype=dgrid_ne)
192  CALL timing_off('COMM_TOTAL')
193  END IF
194 !$OMP parallel do default(none) shared(is,ie,js,je,km,npx,npy,grid_type,nested,c2,c1, &
195 !$OMP u,v,gridstruct,ua,va,a1,a2) &
196 !$OMP private(utmp, vtmp, wu, wv)
197  DO k=1,km
198  IF (grid_type .LT. 4) THEN
199 !nested
200  IF (nested) THEN
201  IF (1 .LT. js) THEN
202  max1 = js
203  ELSE
204  max1 = 1
205  END IF
206  IF (npy - 1 .GT. je) THEN
207  min1 = je
208  ELSE
209  min1 = npy - 1
210  END IF
211  DO j=max1,min1
212  IF (1 .LT. is) THEN
213  max2 = is
214  ELSE
215  max2 = 1
216  END IF
217  IF (npx - 1 .GT. ie) THEN
218  min2 = ie
219  ELSE
220  min2 = npx - 1
221  END IF
222  DO i=max2,min2
223  utmp(i, j) = c2*(u(i, j-1, k)+u(i, j+2, k)) + c1*(u(i, j, &
224 & k)+u(i, j+1, k))
225  vtmp(i, j) = c2*(v(i-1, j, k)+v(i+2, j, k)) + c1*(v(i, j, &
226 & k)+v(i+1, j, k))
227  END DO
228  END DO
229  ELSE
230  IF (2 .LT. js) THEN
231  max3 = js
232  ELSE
233  max3 = 2
234  END IF
235  IF (npy - 2 .GT. je) THEN
236  min3 = je
237  ELSE
238  min3 = npy - 2
239  END IF
240  DO j=max3,min3
241  IF (2 .LT. is) THEN
242  max4 = is
243  ELSE
244  max4 = 2
245  END IF
246  IF (npx - 2 .GT. ie) THEN
247  min4 = ie
248  ELSE
249  min4 = npx - 2
250  END IF
251  DO i=max4,min4
252  utmp(i, j) = c2*(u(i, j-1, k)+u(i, j+2, k)) + c1*(u(i, j, &
253 & k)+u(i, j+1, k))
254  vtmp(i, j) = c2*(v(i-1, j, k)+v(i+2, j, k)) + c1*(v(i, j, &
255 & k)+v(i+1, j, k))
256  END DO
257  END DO
258  IF (js .EQ. 1) THEN
259  DO i=is,ie+1
260  wv(i, 1) = v(i, 1, k)*gridstruct%dy(i, 1)
261  END DO
262  DO i=is,ie
263  vtmp(i, 1) = 2.*(wv(i, 1)+wv(i+1, 1))/(gridstruct%dy(i, 1)&
264 & +gridstruct%dy(i+1, 1))
265  utmp(i, 1) = 2.*(u(i, 1, k)*gridstruct%dx(i, 1)+u(i, 2, k)&
266 & *gridstruct%dx(i, 2))/(gridstruct%dx(i, 1)+gridstruct%dx&
267 & (i, 2))
268  END DO
269  END IF
270 !!! vtmp(i,1) = (wv(i,1) + wv(i+1,1)) * gridstruct%rdya(i,1)
271 !!! utmp(i,1) = (u(i,1,k)*gridstruct%dx(i,1) + u(i,2,k)*gridstruct%dx(i,2)) * gridstruct%rdxa(i,1)
272  IF (je + 1 .EQ. npy) THEN
273  j = npy - 1
274  DO i=is,ie+1
275  wv(i, j) = v(i, j, k)*gridstruct%dy(i, j)
276  END DO
277  DO i=is,ie
278  vtmp(i, j) = 2.*(wv(i, j)+wv(i+1, j))/(gridstruct%dy(i, j)&
279 & +gridstruct%dy(i+1, j))
280  utmp(i, j) = 2.*(u(i, j, k)*gridstruct%dx(i, j)+u(i, j+1, &
281 & k)*gridstruct%dx(i, j+1))/(gridstruct%dx(i, j)+&
282 & gridstruct%dx(i, j+1))
283  END DO
284  END IF
285 !!! vtmp(i,j) = (wv(i,j) + wv(i+1,j)) * gridstruct%rdya(i,j)
286 !!! utmp(i,j) = (u(i,j,k)*gridstruct%dx(i,j) + u(i,j+1,k)*gridstruct%dx(i,j+1)) * gridstruct%rdxa(i,j)
287  IF (is .EQ. 1) THEN
288  i = 1
289  DO j=js,je
290  wv(1, j) = v(1, j, k)*gridstruct%dy(1, j)
291  wv(2, j) = v(2, j, k)*gridstruct%dy(2, j)
292  END DO
293  DO j=js,je+1
294  wu(i, j) = u(i, j, k)*gridstruct%dx(i, j)
295  END DO
296  DO j=js,je
297  utmp(i, j) = 2.*(wu(i, j)+wu(i, j+1))/(gridstruct%dx(i, j)&
298 & +gridstruct%dx(i, j+1))
299  vtmp(i, j) = 2.*(wv(1, j)+wv(2, j))/(gridstruct%dy(1, j)+&
300 & gridstruct%dy(2, j))
301  END DO
302  END IF
303 !!! utmp(i,j) = (wu(i,j) + wu(i, j+1)) * gridstruct%rdxa(i,j)
304 !!! vtmp(i,j) = (wv(i,j) + wv(i+1,j )) * gridstruct%rdya(i,j)
305  IF (ie + 1 .EQ. npx) THEN
306  i = npx - 1
307  DO j=js,je
308  wv(i, j) = v(i, j, k)*gridstruct%dy(i, j)
309  wv(i+1, j) = v(i+1, j, k)*gridstruct%dy(i+1, j)
310  END DO
311  DO j=js,je+1
312  wu(i, j) = u(i, j, k)*gridstruct%dx(i, j)
313  END DO
314  DO j=js,je
315  utmp(i, j) = 2.*(wu(i, j)+wu(i, j+1))/(gridstruct%dx(i, j)&
316 & +gridstruct%dx(i, j+1))
317  vtmp(i, j) = 2.*(wv(i, j)+wv(i+1, j))/(gridstruct%dy(i, j)&
318 & +gridstruct%dy(i+1, j))
319  END DO
320  END IF
321  END IF
322 !!! utmp(i,j) = (wu(i,j) + wu(i, j+1)) * gridstruct%rdxa(i,j)
323 !!! vtmp(i,j) = (wv(i,j) + wv(i+1,j )) * gridstruct%rdya(i,j)
324 !Transform local a-grid winds into latitude-longitude coordinates
325  DO j=js,je
326  DO i=is,ie
327  ua(i, j, k) = gridstruct%a11(i, j)*utmp(i, j) + gridstruct%&
328 & a12(i, j)*vtmp(i, j)
329  va(i, j, k) = gridstruct%a21(i, j)*utmp(i, j) + gridstruct%&
330 & a22(i, j)*vtmp(i, j)
331  END DO
332  END DO
333  ELSE
334 ! Simple Cartesian Geometry:
335  DO j=js,je
336  DO i=is,ie
337  ua(i, j, k) = a2*(u(i, j-1, k)+u(i, j+2, k)) + a1*(u(i, j, k&
338 & )+u(i, j+1, k))
339  va(i, j, k) = a2*(v(i-1, j, k)+v(i+2, j, k)) + a1*(v(i, j, k&
340 & )+v(i+1, j, k))
341  END DO
342  END DO
343  END IF
344  END DO
345  END SUBROUTINE c2l_ord4
346 ! Differentiation of c2l_ord2 in forward (tangent) mode:
347 ! variations of useful results: ua va
348 ! with respect to varying inputs: u v ua va
349  SUBROUTINE c2l_ord2_tlm(u, u_tl, v, v_tl, ua, ua_tl, va, va_tl, &
350 & gridstruct, km, grid_type, bd, do_halo)
351  IMPLICIT NONE
352  TYPE(fv_grid_bounds_type), INTENT(IN) :: bd
353  INTEGER, INTENT(IN) :: km, grid_type
354  REAL, INTENT(IN) :: u(bd%isd:bd%ied, bd%jsd:bd%jed+1, km)
355  REAL, INTENT(IN) :: u_tl(bd%isd:bd%ied, bd%jsd:bd%jed+1, km)
356  REAL, INTENT(IN) :: v(bd%isd:bd%ied+1, bd%jsd:bd%jed, km)
357  REAL, INTENT(IN) :: v_tl(bd%isd:bd%ied+1, bd%jsd:bd%jed, km)
358  TYPE(fv_grid_type), INTENT(IN), TARGET :: gridstruct
359  LOGICAL, INTENT(IN) :: do_halo
360 !
361  REAL, INTENT(OUT) :: ua(bd%isd:bd%ied, bd%jsd:bd%jed, km)
362  REAL, INTENT(OUT) :: ua_tl(bd%isd:bd%ied, bd%jsd:bd%jed, km)
363  REAL, INTENT(OUT) :: va(bd%isd:bd%ied, bd%jsd:bd%jed, km)
364  REAL, INTENT(OUT) :: va_tl(bd%isd:bd%ied, bd%jsd:bd%jed, km)
365 !--------------------------------------------------------------
366 ! Local
367  REAL :: wu(bd%is-1:bd%ie+1, bd%js-1:bd%je+2)
368  REAL :: wu_tl(bd%is-1:bd%ie+1, bd%js-1:bd%je+2)
369  REAL :: wv(bd%is-1:bd%ie+2, bd%js-1:bd%je+1)
370  REAL :: wv_tl(bd%is-1:bd%ie+2, bd%js-1:bd%je+1)
371  REAL :: u1(bd%is-1:bd%ie+1), v1(bd%is-1:bd%ie+1)
372  REAL :: u1_tl(bd%is-1:bd%ie+1), v1_tl(bd%is-1:bd%ie+1)
373  INTEGER :: i, j, k
374  INTEGER :: is, ie, js, je
375  REAL, DIMENSION(:, :), POINTER :: a11, a12, a21, a22
376  REAL, DIMENSION(:, :), POINTER :: dx, dy, rdxa, rdya
377  a11 => gridstruct%a11
378  a12 => gridstruct%a12
379  a21 => gridstruct%a21
380  a22 => gridstruct%a22
381  dx => gridstruct%dx
382  dy => gridstruct%dy
383  rdxa => gridstruct%rdxa
384  rdya => gridstruct%rdya
385  IF (do_halo) THEN
386  is = bd%is - 1
387  ie = bd%ie + 1
388  js = bd%js - 1
389  je = bd%je + 1
390  wu_tl = 0.0
391  v1_tl = 0.0
392  wv_tl = 0.0
393  u1_tl = 0.0
394  ELSE
395  is = bd%is
396  ie = bd%ie
397  js = bd%js
398  je = bd%je
399  wu_tl = 0.0
400  v1_tl = 0.0
401  wv_tl = 0.0
402  u1_tl = 0.0
403  END IF
404 !$OMP parallel do default(none) shared(is,ie,js,je,km,grid_type,u,dx,v,dy,ua,va,a11,a12,a21,a22) &
405 !$OMP private(u1, v1, wu, wv)
406  DO k=1,km
407  IF (grid_type .LT. 4) THEN
408  DO j=js,je+1
409  DO i=is,ie
410  wu_tl(i, j) = dx(i, j)*u_tl(i, j, k)
411  wu(i, j) = u(i, j, k)*dx(i, j)
412  END DO
413  END DO
414  DO j=js,je
415  DO i=is,ie+1
416  wv_tl(i, j) = dy(i, j)*v_tl(i, j, k)
417  wv(i, j) = v(i, j, k)*dy(i, j)
418  END DO
419  END DO
420  DO j=js,je
421  DO i=is,ie
422 ! Co-variant to Co-variant "vorticity-conserving" interpolation
423  u1_tl(i) = 2.*(wu_tl(i, j)+wu_tl(i, j+1))/(dx(i, j)+dx(i, j+&
424 & 1))
425  u1(i) = 2.*(wu(i, j)+wu(i, j+1))/(dx(i, j)+dx(i, j+1))
426  v1_tl(i) = 2.*(wv_tl(i, j)+wv_tl(i+1, j))/(dy(i, j)+dy(i+1, &
427 & j))
428  v1(i) = 2.*(wv(i, j)+wv(i+1, j))/(dy(i, j)+dy(i+1, j))
429 !!! u1(i) = (wu(i,j) + wu(i,j+1)) * rdxa(i,j)
430 !!! v1(i) = (wv(i,j) + wv(i+1,j)) * rdya(i,j)
431 ! Cubed (cell center co-variant winds) to lat-lon:
432  ua_tl(i, j, k) = a11(i, j)*u1_tl(i) + a12(i, j)*v1_tl(i)
433  ua(i, j, k) = a11(i, j)*u1(i) + a12(i, j)*v1(i)
434  va_tl(i, j, k) = a21(i, j)*u1_tl(i) + a22(i, j)*v1_tl(i)
435  va(i, j, k) = a21(i, j)*u1(i) + a22(i, j)*v1(i)
436  END DO
437  END DO
438  ELSE
439 ! 2nd order:
440  DO j=js,je
441  DO i=is,ie
442  ua_tl(i, j, k) = 0.5*(u_tl(i, j, k)+u_tl(i, j+1, k))
443  ua(i, j, k) = 0.5*(u(i, j, k)+u(i, j+1, k))
444  va_tl(i, j, k) = 0.5*(v_tl(i, j, k)+v_tl(i+1, j, k))
445  va(i, j, k) = 0.5*(v(i, j, k)+v(i+1, j, k))
446  END DO
447  END DO
448  END IF
449  END DO
450  END SUBROUTINE c2l_ord2_tlm
451  SUBROUTINE c2l_ord2(u, v, ua, va, gridstruct, km, grid_type, bd, &
452 & do_halo)
453  IMPLICIT NONE
454  TYPE(fv_grid_bounds_type), INTENT(IN) :: bd
455  INTEGER, INTENT(IN) :: km, grid_type
456  REAL, INTENT(IN) :: u(bd%isd:bd%ied, bd%jsd:bd%jed+1, km)
457  REAL, INTENT(IN) :: v(bd%isd:bd%ied+1, bd%jsd:bd%jed, km)
458  TYPE(fv_grid_type), INTENT(IN), TARGET :: gridstruct
459  LOGICAL, INTENT(IN) :: do_halo
460 !
461  REAL, INTENT(OUT) :: ua(bd%isd:bd%ied, bd%jsd:bd%jed, km)
462  REAL, INTENT(OUT) :: va(bd%isd:bd%ied, bd%jsd:bd%jed, km)
463 !--------------------------------------------------------------
464 ! Local
465  REAL :: wu(bd%is-1:bd%ie+1, bd%js-1:bd%je+2)
466  REAL :: wv(bd%is-1:bd%ie+2, bd%js-1:bd%je+1)
467  REAL :: u1(bd%is-1:bd%ie+1), v1(bd%is-1:bd%ie+1)
468  INTEGER :: i, j, k
469  INTEGER :: is, ie, js, je
470  REAL, DIMENSION(:, :), POINTER :: a11, a12, a21, a22
471  REAL, DIMENSION(:, :), POINTER :: dx, dy, rdxa, rdya
472  a11 => gridstruct%a11
473  a12 => gridstruct%a12
474  a21 => gridstruct%a21
475  a22 => gridstruct%a22
476  dx => gridstruct%dx
477  dy => gridstruct%dy
478  rdxa => gridstruct%rdxa
479  rdya => gridstruct%rdya
480  IF (do_halo) THEN
481  is = bd%is - 1
482  ie = bd%ie + 1
483  js = bd%js - 1
484  je = bd%je + 1
485  ELSE
486  is = bd%is
487  ie = bd%ie
488  js = bd%js
489  je = bd%je
490  END IF
491 !$OMP parallel do default(none) shared(is,ie,js,je,km,grid_type,u,dx,v,dy,ua,va,a11,a12,a21,a22) &
492 !$OMP private(u1, v1, wu, wv)
493  DO k=1,km
494  IF (grid_type .LT. 4) THEN
495  DO j=js,je+1
496  DO i=is,ie
497  wu(i, j) = u(i, j, k)*dx(i, j)
498  END DO
499  END DO
500  DO j=js,je
501  DO i=is,ie+1
502  wv(i, j) = v(i, j, k)*dy(i, j)
503  END DO
504  END DO
505  DO j=js,je
506  DO i=is,ie
507 ! Co-variant to Co-variant "vorticity-conserving" interpolation
508  u1(i) = 2.*(wu(i, j)+wu(i, j+1))/(dx(i, j)+dx(i, j+1))
509  v1(i) = 2.*(wv(i, j)+wv(i+1, j))/(dy(i, j)+dy(i+1, j))
510 !!! u1(i) = (wu(i,j) + wu(i,j+1)) * rdxa(i,j)
511 !!! v1(i) = (wv(i,j) + wv(i+1,j)) * rdya(i,j)
512 ! Cubed (cell center co-variant winds) to lat-lon:
513  ua(i, j, k) = a11(i, j)*u1(i) + a12(i, j)*v1(i)
514  va(i, j, k) = a21(i, j)*u1(i) + a22(i, j)*v1(i)
515  END DO
516  END DO
517  ELSE
518 ! 2nd order:
519  DO j=js,je
520  DO i=is,ie
521  ua(i, j, k) = 0.5*(u(i, j, k)+u(i, j+1, k))
522  va(i, j, k) = 0.5*(v(i, j, k)+v(i+1, j, k))
523  END DO
524  END DO
525  END IF
526  END DO
527  END SUBROUTINE c2l_ord2
528 ! Differentiation of g_sum in forward (tangent) mode:
529 ! variations of useful results: g_sum
530 ! with respect to varying inputs: p
531  REAL FUNCTION g_sum_tlm(domain, p, p_tl, ifirst, ilast, jfirst, jlast, ngc, area, mode, reproduce, g_sum)
532 ! Fast version of globalsum
533  integer, intent(IN) :: ifirst, ilast
534  integer, intent(IN) :: jfirst, jlast, ngc
535  integer, intent(IN) :: mode ! if ==1 divided by area
536  logical, intent(in), optional :: reproduce
537  real, intent(IN) :: p(ifirst:ilast,jfirst:jlast) ! field to be summed
538  real, intent(IN) :: p_tl(ifirst:ilast,jfirst:jlast) ! field to be summed
539  real(kind=R_GRID), intent(IN) :: area(ifirst-ngc:ilast+ngc,jfirst-ngc:jlast+ngc)
540  type(domain2d), intent(IN) :: domain
541  integer :: i,j
542  real gsum, gsum_tl
543  logical, SAVE :: g_sum_initialized = .false.
544  real(kind=R_GRID), SAVE :: global_area
545  real :: tmp(ifirst:ilast,jfirst:jlast)
546  real :: g_sum
547 
548  if ( .not. g_sum_initialized ) then
549  global_area = mpp_global_sum(domain, area, flags=bitwise_efp_sum)
550  if ( is_master() ) write(*,*) 'Global Area=',global_area
551  g_sum_initialized = .true.
552  end if
553 
554 !-------------------------
555 ! FMS global sum algorithm:
556 !-------------------------
557  if ( present(reproduce) ) then
558  if (reproduce) then
559  gsum = mpp_global_sum(domain, p(:,:)*area(ifirst:ilast,jfirst:jlast), &
560  flags=bitwise_efp_sum)
561  gsum_tl = mpp_global_sum(domain, p_tl(:,:)*area(ifirst:ilast,jfirst:jlast), &
562  flags=bitwise_efp_sum)
563  else
564  gsum = mpp_global_sum(domain, p(:,:)*area(ifirst:ilast,jfirst:jlast))
565  gsum_tl = mpp_global_sum(domain, p_tl(:,:)*area(ifirst:ilast,jfirst:jlast))
566  endif
567  else
568 !-------------------------
569 ! Quick local sum algorithm
570 !-------------------------
571  gsum = 0.
572  gsum_tl = 0.
573  do j=jfirst,jlast
574  do i=ifirst,ilast
575  gsum = gsum + p(i,j)*area(i,j)
576  gsum_tl = gsum_tl + p_tl(i,j)*area(i,j)
577  enddo
578  enddo
579  call mp_reduce_sum(gsum)
580  call mp_reduce_sum(gsum_tl)
581  endif
582 
583  if ( mode==1 ) then
584  g_sum = gsum / global_area
585  g_sum_tlm = gsum_tl / global_area
586  else
587  g_sum = gsum
588  g_sum_tlm = gsum_tl
589  endif
590 
591  !Uncomment here to test without TLM/ADM
592  g_sum_tlm = 0.0
593 
594  END FUNCTION g_sum_tlm
595  REAL FUNCTION g_sum(domain, p, ifirst, ilast, jfirst, jlast, ngc, area, mode, reproduce)
596 ! Fast version of globalsum
597  integer, intent(IN) :: ifirst, ilast
598  integer, intent(IN) :: jfirst, jlast, ngc
599  integer, intent(IN) :: mode ! if ==1 divided by area
600  logical, intent(in), optional :: reproduce
601  real, intent(IN) :: p(ifirst:ilast,jfirst:jlast) ! field to be summed
602  real(kind=R_GRID), intent(IN) :: area(ifirst-ngc:ilast+ngc,jfirst-ngc:jlast+ngc)
603  type(domain2d), intent(IN) :: domain
604  integer :: i,j
605  real gsum
606  logical, SAVE :: g_sum_initialized = .false.
607  real(kind=R_GRID), SAVE :: global_area
608  real :: tmp(ifirst:ilast,jfirst:jlast)
609 
610  if ( .not. g_sum_initialized ) then
611  global_area = mpp_global_sum(domain, area, flags=bitwise_efp_sum)
612  if ( is_master() ) write(*,*) 'Global Area=',global_area
613  g_sum_initialized = .true.
614  end if
615 
616 !-------------------------
617 ! FMS global sum algorithm:
618 !-------------------------
619  if ( present(reproduce) ) then
620  if (reproduce) then
621  gsum = mpp_global_sum(domain, p(:,:)*area(ifirst:ilast,jfirst:jlast), &
622  flags=bitwise_efp_sum)
623  else
624  gsum = mpp_global_sum(domain, p(:,:)*area(ifirst:ilast,jfirst:jlast))
625  endif
626  else
627 !-------------------------
628 ! Quick local sum algorithm
629 !-------------------------
630  gsum = 0.
631  do j=jfirst,jlast
632  do i=ifirst,ilast
633  gsum = gsum + p(i,j)*area(i,j)
634  enddo
635  enddo
636  call mp_reduce_sum(gsum)
637  endif
638 
639  if ( mode==1 ) then
640  g_sum = gsum / global_area
641  else
642  g_sum = gsum
643  endif
644 
645  END FUNCTION g_sum
646 
647  end module fv_grid_utils_tlm_mod
real, parameter, public radius
Radius of the Earth [m].
Definition: constants.F90:72
real, parameter, public omega
Rotation rate of the Earth [1/s].
Definition: constants.F90:75
subroutine, public cubed_to_latlon(u, v, ua, va, gridstruct, npx, npy, km, mode, grid_type, domain, nested, c2l_ord, bd)
real(kind=8), parameter, public pi_8
Ratio of circle circumference to diameter [N/A].
Definition: constants.F90:73
subroutine, public set_eta(km, ks, ptop, ak, bk)
Definition: fv_eta_nlm.F90:392
integer, parameter, public corner
subroutine, public c2l_ord2_tlm(u, u_tl, v, v_tl, ua, ua_tl, va, va_tl, gridstruct, km, grid_type, bd, do_halo)
subroutine grid_utils_init(atm, npx, npy, npz, non_ortho, grid_type, c2l_order)
subroutine, public c2l_ord2(u, v, ua, va, gridstruct, km, grid_type, bd, do_halo)
Definition: mpp.F90:39
real, parameter, public ptop_min
subroutine c2l_ord4(u, v, ua, va, gridstruct, npx, npy, km, grid_type, domain, nested, mode, bd)
integer, parameter, public agrid
real function, public g_sum(domain, p, ifirst, ilast, jfirst, jlast, ngc, area, mode, reproduce)
real, parameter tiny_number
integer, parameter, public ng
subroutine timing_on(blk_name)
integer, parameter, public r_grid
#define max(a, b)
Definition: mosaic_util.h:33
real function, public great_circle_dist(q1, q2, radius)
integer, parameter, public f_p
real, parameter, public big_number
#define min(a, b)
Definition: mosaic_util.h:32
integer, parameter, public scalar_pair
integer, parameter, public cgrid_ne
Derived type containing the data.
real function, public g_sum_tlm(domain, p, p_tl, ifirst, ilast, jfirst, jlast, ngc, area, mode, reproduce, g_sum)
real(fp), parameter, public pi
subroutine timing_off(blk_name)