FV3 Bundle
fv_grid_utils_adm.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 
42  implicit none
43  private
44  logical:: symm_grid
45 #ifdef NO_QUAD_PRECISION
46 ! 64-bit precision (kind=8)
47  integer, parameter:: f_p = selected_real_kind(15)
48 #else
49 ! Higher precision (kind=16) for grid geometrical factors:
50  integer, parameter:: f_p = selected_real_kind(20)
51 #endif
52  real, parameter:: big_number=1.d8
53  real, parameter:: tiny_number=1.d-8
54 
55  real(kind=R_GRID) :: radius=cnst_radius
56 
57  real, parameter:: ptop_min=1.d-8
58 
59  public f_p
60  public ptop_min, big_number !CLEANUP: OK to keep since they are constants?
61 ! public cos_angle
62 ! public latlon2xyz, gnomonic_grids, &
63 ! global_mx, unit_vect_latlon, &
64 ! cubed_to_latlon, c2l_ord2, g_sum, global_qsum, great_circle_dist, &
65 ! v_prod, get_unit_vect2, project_sphere_v
66 ! public mid_pt_sphere, mid_pt_cart, vect_cross, grid_utils_init, grid_utils_end, &
67 ! spherical_angle, cell_center2, get_area, inner_prod, fill_ghost, direct_transform, &
68 ! make_eta_level, expand_cell, cart_to_latlon, intp_great_circle, normalize_vect, &
69 ! dist2side_latlon, spherical_linear_interpolation, get_latlon_vector
70 ! public symm_grid
71 
73 public c2l_ord2_fwd
74 public c2l_ord2_bwd, g_sum_adm
75 
76 ! INTERFACE fill_ghost
77 !#ifdef OVERLOAD_R4
78 ! MODULE PROCEDURE fill_ghost_r4
79 !#endif
80 ! MODULE PROCEDURE fill_ghost_r8
81 ! END INTERFACE
82 
83 CONTAINS
84  SUBROUTINE grid_utils_init(atm, npx, npy, npz, non_ortho, grid_type, &
85 & c2l_order)
86  IMPLICIT NONE
87 ! Initialize 2D memory and geometrical factors
88  TYPE(FV_ATMOS_TYPE), INTENT(INOUT), TARGET :: atm
89  LOGICAL, INTENT(IN) :: non_ortho
90  INTEGER, INTENT(IN) :: npx, npy, npz
91  INTEGER, INTENT(IN) :: grid_type, c2l_order
92  END SUBROUTINE grid_utils_init
93  SUBROUTINE grid_utils_end()
94  IMPLICIT NONE
95  END SUBROUTINE grid_utils_end
96  REAL FUNCTION great_circle_dist(q1, q2, radius)
97  IMPLICIT NONE
98  REAL(kind=r_grid), INTENT(IN) :: q1(2), q2(2)
99  REAL(kind=r_grid), INTENT(IN), OPTIONAL :: radius
100  REAL(f_p) :: p1(2), p2(2)
101  REAL(f_p) :: beta
102  INTEGER :: n
103  INTRINSIC sin
104  INTRINSIC cos
105  INTRINSIC sqrt
106  INTRINSIC asin
107  INTRINSIC PRESENT
108  DO n=1,2
109  p1(n) = q1(n)
110  p2(n) = q2(n)
111  END DO
112  beta = asin(sqrt(sin((p1(2)-p2(2))/2.)**2+cos(p1(2))*cos(p2(2))*sin(&
113 & (p1(1)-p2(1))/2.)**2))*2.
114  IF (PRESENT(radius)) THEN
116  ELSE
117 ! Returns the angle
118  great_circle_dist = beta
119  END IF
120  END FUNCTION great_circle_dist
121  SUBROUTINE cubed_to_latlon(u, v, ua, va, gridstruct, npx, npy, km, &
122 & mode, grid_type, domain, nested, c2l_ord, bd)
123  IMPLICIT NONE
124  TYPE(fv_grid_bounds_type), INTENT(IN) :: bd
125  INTEGER, INTENT(IN) :: km, npx, npy, grid_type, c2l_ord
126 ! update if present
127  INTEGER, INTENT(IN) :: mode
128  TYPE(fv_grid_type), INTENT(IN) :: gridstruct
129  REAL, INTENT(INOUT) :: u(bd%isd:bd%ied, bd%jsd:bd%jed+1, km)
130  REAL, INTENT(INOUT) :: v(bd%isd:bd%ied+1, bd%jsd:bd%jed, km)
131  REAL, INTENT(OUT) :: ua(bd%isd:bd%ied, bd%jsd:bd%jed, km)
132  REAL, INTENT(OUT) :: va(bd%isd:bd%ied, bd%jsd:bd%jed, km)
133  TYPE(domain2d), INTENT(INOUT) :: domain
134  LOGICAL, INTENT(IN) :: nested
135  IF (c2l_ord .EQ. 2) THEN
136  CALL c2l_ord2(u, v, ua, va, gridstruct, km, grid_type, bd, .false.&
137 & )
138  ELSE
139  CALL c2l_ord4(u, v, ua, va, gridstruct, npx, npy, km, grid_type, &
140 & domain, nested, mode, bd)
141  END IF
142  END SUBROUTINE cubed_to_latlon
143  SUBROUTINE c2l_ord4(u, v, ua, va, gridstruct, npx, npy, km, grid_type&
144 & , domain, nested, mode, bd)
145  IMPLICIT NONE
146  TYPE(FV_GRID_BOUNDS_TYPE), INTENT(IN) :: bd
147  INTEGER, INTENT(IN) :: km, npx, npy, grid_type
148 ! update if present
149  INTEGER, INTENT(IN) :: mode
150  TYPE(FV_GRID_TYPE), INTENT(IN), TARGET :: gridstruct
151  REAL, INTENT(INOUT) :: u(bd%isd:bd%ied, bd%jsd:bd%jed+1, km)
152  REAL, INTENT(INOUT) :: v(bd%isd:bd%ied+1, bd%jsd:bd%jed, km)
153  REAL, INTENT(OUT) :: ua(bd%isd:bd%ied, bd%jsd:bd%jed, km)
154  REAL, INTENT(OUT) :: va(bd%isd:bd%ied, bd%jsd:bd%jed, km)
155  TYPE(DOMAIN2D), INTENT(INOUT) :: domain
156  LOGICAL, INTENT(IN) :: nested
157 ! Local
158 ! 4-pt Lagrange interpolation
159  REAL, SAVE :: a1=0.5625
160  REAL, SAVE :: a2=-0.0625
161  REAL, SAVE :: c1=1.125
162  REAL, SAVE :: c2=-0.125
163  REAL :: utmp(bd%is:bd%ie, bd%js:bd%je+1)
164  REAL :: vtmp(bd%is:bd%ie+1, bd%js:bd%je)
165  REAL :: wu(bd%is:bd%ie, bd%js:bd%je+1)
166  REAL :: wv(bd%is:bd%ie+1, bd%js:bd%je)
167  INTEGER :: i, j, k
168  INTEGER :: is, ie, js, je
169  INTRINSIC max
170  INTRINSIC min
171  INTEGER :: max1
172  INTEGER :: max2
173  INTEGER :: max3
174  INTEGER :: max4
175  INTEGER :: min1
176  INTEGER :: min2
177  INTEGER :: min3
178  INTEGER :: min4
179  is = bd%is
180  ie = bd%ie
181  js = bd%js
182  je = bd%je
183  IF (mode .GT. 0) THEN
184  CALL timing_on('COMM_TOTAL')
185  CALL mpp_update_domains(u, v, domain, gridtype=dgrid_ne)
186  CALL timing_off('COMM_TOTAL')
187  END IF
188 !$OMP parallel do default(none) shared(is,ie,js,je,km,npx,npy,grid_type,nested,c2,c1, &
189 !$OMP u,v,gridstruct,ua,va,a1,a2) &
190 !$OMP private(utmp, vtmp, wu, wv)
191  DO k=1,km
192  IF (grid_type .LT. 4) THEN
193 !nested
194  IF (nested) THEN
195  IF (1 .LT. js) THEN
196  max1 = js
197  ELSE
198  max1 = 1
199  END IF
200  IF (npy - 1 .GT. je) THEN
201  min1 = je
202  ELSE
203  min1 = npy - 1
204  END IF
205  DO j=max1,min1
206  IF (1 .LT. is) THEN
207  max2 = is
208  ELSE
209  max2 = 1
210  END IF
211  IF (npx - 1 .GT. ie) THEN
212  min2 = ie
213  ELSE
214  min2 = npx - 1
215  END IF
216  DO i=max2,min2
217  utmp(i, j) = c2*(u(i, j-1, k)+u(i, j+2, k)) + c1*(u(i, j, &
218 & k)+u(i, j+1, k))
219  vtmp(i, j) = c2*(v(i-1, j, k)+v(i+2, j, k)) + c1*(v(i, j, &
220 & k)+v(i+1, j, k))
221  END DO
222  END DO
223  ELSE
224  IF (2 .LT. js) THEN
225  max3 = js
226  ELSE
227  max3 = 2
228  END IF
229  IF (npy - 2 .GT. je) THEN
230  min3 = je
231  ELSE
232  min3 = npy - 2
233  END IF
234  DO j=max3,min3
235  IF (2 .LT. is) THEN
236  max4 = is
237  ELSE
238  max4 = 2
239  END IF
240  IF (npx - 2 .GT. ie) THEN
241  min4 = ie
242  ELSE
243  min4 = npx - 2
244  END IF
245  DO i=max4,min4
246  utmp(i, j) = c2*(u(i, j-1, k)+u(i, j+2, k)) + c1*(u(i, j, &
247 & k)+u(i, j+1, k))
248  vtmp(i, j) = c2*(v(i-1, j, k)+v(i+2, j, k)) + c1*(v(i, j, &
249 & k)+v(i+1, j, k))
250  END DO
251  END DO
252  IF (js .EQ. 1) THEN
253  DO i=is,ie+1
254  wv(i, 1) = v(i, 1, k)*gridstruct%dy(i, 1)
255  END DO
256  DO i=is,ie
257  vtmp(i, 1) = 2.*(wv(i, 1)+wv(i+1, 1))/(gridstruct%dy(i, 1)&
258 & +gridstruct%dy(i+1, 1))
259  utmp(i, 1) = 2.*(u(i, 1, k)*gridstruct%dx(i, 1)+u(i, 2, k)&
260 & *gridstruct%dx(i, 2))/(gridstruct%dx(i, 1)+gridstruct%dx&
261 & (i, 2))
262  END DO
263  END IF
264 !!! vtmp(i,1) = (wv(i,1) + wv(i+1,1)) * gridstruct%rdya(i,1)
265 !!! utmp(i,1) = (u(i,1,k)*gridstruct%dx(i,1) + u(i,2,k)*gridstruct%dx(i,2)) * gridstruct%rdxa(i,1)
266  IF (je + 1 .EQ. npy) THEN
267  j = npy - 1
268  DO i=is,ie+1
269  wv(i, j) = v(i, j, k)*gridstruct%dy(i, j)
270  END DO
271  DO i=is,ie
272  vtmp(i, j) = 2.*(wv(i, j)+wv(i+1, j))/(gridstruct%dy(i, j)&
273 & +gridstruct%dy(i+1, j))
274  utmp(i, j) = 2.*(u(i, j, k)*gridstruct%dx(i, j)+u(i, j+1, &
275 & k)*gridstruct%dx(i, j+1))/(gridstruct%dx(i, j)+&
276 & gridstruct%dx(i, j+1))
277  END DO
278  END IF
279 !!! vtmp(i,j) = (wv(i,j) + wv(i+1,j)) * gridstruct%rdya(i,j)
280 !!! 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)
281  IF (is .EQ. 1) THEN
282  i = 1
283  DO j=js,je
284  wv(1, j) = v(1, j, k)*gridstruct%dy(1, j)
285  wv(2, j) = v(2, j, k)*gridstruct%dy(2, j)
286  END DO
287  DO j=js,je+1
288  wu(i, j) = u(i, j, k)*gridstruct%dx(i, j)
289  END DO
290  DO j=js,je
291  utmp(i, j) = 2.*(wu(i, j)+wu(i, j+1))/(gridstruct%dx(i, j)&
292 & +gridstruct%dx(i, j+1))
293  vtmp(i, j) = 2.*(wv(1, j)+wv(2, j))/(gridstruct%dy(1, j)+&
294 & gridstruct%dy(2, j))
295  END DO
296  END IF
297 !!! utmp(i,j) = (wu(i,j) + wu(i, j+1)) * gridstruct%rdxa(i,j)
298 !!! vtmp(i,j) = (wv(i,j) + wv(i+1,j )) * gridstruct%rdya(i,j)
299  IF (ie + 1 .EQ. npx) THEN
300  i = npx - 1
301  DO j=js,je
302  wv(i, j) = v(i, j, k)*gridstruct%dy(i, j)
303  wv(i+1, j) = v(i+1, j, k)*gridstruct%dy(i+1, j)
304  END DO
305  DO j=js,je+1
306  wu(i, j) = u(i, j, k)*gridstruct%dx(i, j)
307  END DO
308  DO j=js,je
309  utmp(i, j) = 2.*(wu(i, j)+wu(i, j+1))/(gridstruct%dx(i, j)&
310 & +gridstruct%dx(i, j+1))
311  vtmp(i, j) = 2.*(wv(i, j)+wv(i+1, j))/(gridstruct%dy(i, j)&
312 & +gridstruct%dy(i+1, j))
313  END DO
314  END IF
315  END IF
316 !!! utmp(i,j) = (wu(i,j) + wu(i, j+1)) * gridstruct%rdxa(i,j)
317 !!! vtmp(i,j) = (wv(i,j) + wv(i+1,j )) * gridstruct%rdya(i,j)
318 !Transform local a-grid winds into latitude-longitude coordinates
319  DO j=js,je
320  DO i=is,ie
321  ua(i, j, k) = gridstruct%a11(i, j)*utmp(i, j) + gridstruct%&
322 & a12(i, j)*vtmp(i, j)
323  va(i, j, k) = gridstruct%a21(i, j)*utmp(i, j) + gridstruct%&
324 & a22(i, j)*vtmp(i, j)
325  END DO
326  END DO
327  ELSE
328 ! Simple Cartesian Geometry:
329  DO j=js,je
330  DO i=is,ie
331  ua(i, j, k) = a2*(u(i, j-1, k)+u(i, j+2, k)) + a1*(u(i, j, k&
332 & )+u(i, j+1, k))
333  va(i, j, k) = a2*(v(i-1, j, k)+v(i+2, j, k)) + a1*(v(i, j, k&
334 & )+v(i+1, j, k))
335  END DO
336  END DO
337  END IF
338  END DO
339  END SUBROUTINE c2l_ord4
340 ! Differentiation of c2l_ord2 in reverse (adjoint) mode, forward sweep (with options split(a2b_edge_mod.a2b_ord4 a2b_edge_mod
341 !.a2b_ord2 dyn_core_mod.dyn_core dyn_core_mod.pk3_halo dyn_core_mod.pln_halo dyn_core_mod.pe_halo dyn_core_mod.adv_pe dyn_core_mo
342 !d.p_grad_c dyn_core_mod.nh_p_grad dyn_core_mod.split_p_grad dyn_core_mod.one_grad_p dyn_core_mod.grad1_p_update dyn_core_mod.mix
343 !_dp dyn_core_mod.geopk dyn_core_mod.del2_cubed dyn_core_mod.Rayleigh_fast fv_dynamics_mod.fv_dynamics fv_dynamics_mod.Rayleigh_S
344 !uper fv_dynamics_mod.Rayleigh_Friction fv_dynamics_mod.compute_aam fv_grid_utils_mod.cubed_to_latlon fv_grid_utils_mod.c2l_ord4
345 !fv_grid_utils_mod.c2l_ord2 fv_mapz_mod.Lagrangian_to_Eulerian fv_mapz_mod.compute_total_energy fv_mapz_mod.pkez fv_mapz_mod.rema
346 !p_z fv_mapz_mod.map_scalar fv_mapz_mod.map1_ppm fv_mapz_mod.mapn_tracer fv_mapz_mod.map1_q2 fv_mapz_mod.remap_2d fv_
347 !mapz_mod.scalar_profile fv_mapz_mod.cs_profile fv_mapz_mod.cs_limiters fv_mapz_mod.ppm_profile fv_mapz_mod.ppm_limiters fv
348 !_mapz_mod.steepz fv_mapz_mod.rst_remap fv_mapz_mod.mappm fv_mapz_mod.moist_cv fv_mapz_mod.moist_cp fv_mapz_mod.map1_cubic fv_res
349 !tart_mod.d2c_setup fv_tracer2d_mod.tracer_2d_1L fv_tracer2d_mod.tracer_2d fv_tracer2d_mod.tracer_2d_nested fv_sg_mod.fv_subgrid_
350 !z main_mod.compute_pressures main_mod.run nh_core_mod.Riem_Solver3 nh_utils_mod.update_dz_c nh_utils_mod.update_dz_d nh_utils_mo
351 !d.Riem_Solver_c nh_utils_mod.Riem_Solver3test nh_utils_mod.imp_diff_w nh_utils_mod.RIM_2D nh_utils_mod.SIM3_solver nh_utils_mod.
352 !SIM3p0_solver nh_utils_mod.SIM1_solver nh_utils_mod.SIM_solver nh_utils_mod.edge_scalar nh_utils_mod.edge_profile nh_utils_mod.n
353 !est_halo_nh sw_core_mod.c_sw sw_core_mod.d_sw sw_core_mod.divergence_corner sw_core_mod.divergence_corner_nest sw_core_mod.d2a2
354 !c_vect sw_core_mod.fill3_4corners sw_core_mod.fill2_4corners sw_core_mod.fill_4corners sw_core_mod.xtp_u sw_core_mod.ytp_v
355 ! sw_core_mod.compute_divergence_damping sw_core_mod.smag_corner tp_core_mod.mp_ghost_ew tp_core_mod.fv_tp_2d tp_core_mo
356 !d.copy_corners tp_core_mod.xppm tp_core_mod.yppm tp_core_mod.deln_flux a2b_edge_mod.extrap_corner fv_grid_utils_m
357 !od.great_circle_dist sw_core_mod.edge_interpolate4)):
358 ! gradient of useful results: u v ua va
359 ! with respect to varying inputs: u v ua va
360  SUBROUTINE c2l_ord2_fwd(u, v, ua, va, gridstruct, km, grid_type, bd, &
361 & do_halo)
362  !USE ISO_C_BINDING
363  !USE ADMM_TAPENADE_INTERFACE
364  IMPLICIT NONE
365  TYPE(fv_grid_bounds_type), INTENT(IN) :: bd
366  INTEGER, INTENT(IN) :: km, grid_type
367  REAL, INTENT(IN) :: u(bd%isd:bd%ied, bd%jsd:bd%jed+1, km)
368  REAL, INTENT(IN) :: v(bd%isd:bd%ied+1, bd%jsd:bd%jed, km)
369  TYPE(fv_grid_type), INTENT(IN), TARGET :: gridstruct
370  LOGICAL, INTENT(IN) :: do_halo
371 !
372  REAL :: ua(bd%isd:bd%ied, bd%jsd:bd%jed, km)
373  REAL :: va(bd%isd:bd%ied, bd%jsd:bd%jed, km)
374 !--------------------------------------------------------------
375 ! Local
376  REAL :: wu(bd%is-1:bd%ie+1, bd%js-1:bd%je+2)
377  REAL :: wv(bd%is-1:bd%ie+2, bd%js-1:bd%je+1)
378  REAL :: u1(bd%is-1:bd%ie+1), v1(bd%is-1:bd%ie+1)
379  INTEGER :: i, j, k
380  INTEGER :: is, ie, js, je
381  REAL, DIMENSION(:, :), POINTER :: a11, a12, a21, a22
382  REAL, DIMENSION(:, :), POINTER :: dx, dy, rdxa, rdya
383 
384  wu = 0.0
385  wv = 0.0
386  u1 = 0.0
387  v1 = 0.0
388  is = 0
389  ie = 0
390  js = 0
391  je = 0
392 
393  a11 => gridstruct%a11
394  a12 => gridstruct%a12
395  a21 => gridstruct%a21
396  a22 => gridstruct%a22
397  dx => gridstruct%dx
398  dy => gridstruct%dy
399  IF (do_halo) THEN
400  is = bd%is - 1
401  ie = bd%ie + 1
402  js = bd%js - 1
403  je = bd%je + 1
404  ELSE
405  is = bd%is
406  ie = bd%ie
407  js = bd%js
408  je = bd%je
409  END IF
410 !$OMP parallel do default(none) shared(is,ie,js,je,km,grid_type,u,dx,v,dy,ua,va,a11,a12,a21,a22) &
411 !$OMP private(u1, v1, wu, wv)
412  DO k=1,km
413  IF (grid_type .LT. 4) THEN
414  DO j=js,je+1
415  DO i=is,ie
416  wu(i, j) = u(i, j, k)*dx(i, j)
417  END DO
418  END DO
419  DO j=js,je
420  DO i=is,ie+1
421  wv(i, j) = v(i, j, k)*dy(i, j)
422  END DO
423  END DO
424  DO j=js,je
425  DO i=is,ie
426 ! Co-variant to Co-variant "vorticity-conserving" interpolation
427  u1(i) = 2.*(wu(i, j)+wu(i, j+1))/(dx(i, j)+dx(i, j+1))
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  CALL pushrealarray(ua(i, j, k))
433  ua(i, j, k) = a11(i, j)*u1(i) + a12(i, j)*v1(i)
434  CALL pushrealarray(va(i, j, k))
435  va(i, j, k) = a21(i, j)*u1(i) + a22(i, j)*v1(i)
436  END DO
437  END DO
438  CALL pushcontrol(1,1)
439  ELSE
440 ! 2nd order:
441  DO j=js,je
442  DO i=is,ie
443  CALL pushrealarray(ua(i, j, k))
444  ua(i, j, k) = 0.5*(u(i, j, k)+u(i, j+1, k))
445  CALL pushrealarray(va(i, j, k))
446  va(i, j, k) = 0.5*(v(i, j, k)+v(i+1, j, k))
447  END DO
448  END DO
449  CALL pushcontrol(1,0)
450  END IF
451  END DO
452  CALL pushinteger(je)
453  !CALL PUSHPOINTER8(C_LOC(a12))
454  !CALL PUSHPOINTER8(C_LOC(a11))
455  CALL pushinteger(is)
456  CALL pushinteger(ie)
457  !CALL PUSHPOINTER8(C_LOC(dy))
458  !CALL PUSHPOINTER8(C_LOC(dx))
459  !CALL PUSHPOINTER8(C_LOC(a22))
460  !CALL PUSHPOINTER8(C_LOC(a21))
461  CALL pushinteger(js)
462  END SUBROUTINE c2l_ord2_fwd
463 ! Differentiation of c2l_ord2 in reverse (adjoint) mode, backward sweep (with options split(a2b_edge_mod.a2b_ord4 a2b_edge_mo
464 !d.a2b_ord2 dyn_core_mod.dyn_core dyn_core_mod.pk3_halo dyn_core_mod.pln_halo dyn_core_mod.pe_halo dyn_core_mod.adv_pe dyn_core_m
465 !od.p_grad_c dyn_core_mod.nh_p_grad dyn_core_mod.split_p_grad dyn_core_mod.one_grad_p dyn_core_mod.grad1_p_update dyn_core_mod.mi
466 !x_dp dyn_core_mod.geopk dyn_core_mod.del2_cubed dyn_core_mod.Rayleigh_fast fv_dynamics_mod.fv_dynamics fv_dynamics_mod.Rayleigh_
467 !Super fv_dynamics_mod.Rayleigh_Friction fv_dynamics_mod.compute_aam fv_grid_utils_mod.cubed_to_latlon fv_grid_utils_mod.c2l_ord4
468 ! fv_grid_utils_mod.c2l_ord2 fv_mapz_mod.Lagrangian_to_Eulerian fv_mapz_mod.compute_total_energy fv_mapz_mod.pkez fv_mapz_mod.rem
469 !ap_z fv_mapz_mod.map_scalar fv_mapz_mod.map1_ppm fv_mapz_mod.mapn_tracer fv_mapz_mod.map1_q2 fv_mapz_mod.remap_2d fv
470 !_mapz_mod.scalar_profile fv_mapz_mod.cs_profile fv_mapz_mod.cs_limiters fv_mapz_mod.ppm_profile fv_mapz_mod.ppm_limiters f
471 !v_mapz_mod.steepz fv_mapz_mod.rst_remap fv_mapz_mod.mappm fv_mapz_mod.moist_cv fv_mapz_mod.moist_cp fv_mapz_mod.map1_cubic fv_re
472 !start_mod.d2c_setup fv_tracer2d_mod.tracer_2d_1L fv_tracer2d_mod.tracer_2d fv_tracer2d_mod.tracer_2d_nested fv_sg_mod.fv_subgrid
473 !_z main_mod.compute_pressures main_mod.run nh_core_mod.Riem_Solver3 nh_utils_mod.update_dz_c nh_utils_mod.update_dz_d nh_utils_m
474 !od.Riem_Solver_c nh_utils_mod.Riem_Solver3test nh_utils_mod.imp_diff_w nh_utils_mod.RIM_2D nh_utils_mod.SIM3_solver nh_utils_mod
475 !.SIM3p0_solver nh_utils_mod.SIM1_solver nh_utils_mod.SIM_solver nh_utils_mod.edge_scalar nh_utils_mod.edge_profile nh_utils_mod.
476 !nest_halo_nh sw_core_mod.c_sw sw_core_mod.d_sw sw_core_mod.divergence_corner sw_core_mod.divergence_corner_nest sw_core_mod.d2a
477 !2c_vect sw_core_mod.fill3_4corners sw_core_mod.fill2_4corners sw_core_mod.fill_4corners sw_core_mod.xtp_u sw_core_mod.ytp_v_f
478 !b sw_core_mod.compute_divergence_damping sw_core_mod.smag_corner tp_core_mod.mp_ghost_ew tp_core_mod.fv_tp_2d tp_core_m
479 !od.copy_corners tp_core_mod.xppm tp_core_mod.yppm tp_core_mod.deln_flux a2b_edge_mod.extrap_corner fv_grid_utils_
480 !mod.great_circle_dist sw_core_mod.edge_interpolate4)):
481 ! gradient of useful results: u v ua va
482 ! with respect to varying inputs: u v ua va
483  SUBROUTINE c2l_ord2_bwd(u, u_ad, v, v_ad, ua, ua_ad, va, va_ad, &
484 & gridstruct, km, grid_type, bd, do_halo)
485  !USE ISO_C_BINDING
486  !USE ADMM_TAPENADE_INTERFACE
487  IMPLICIT NONE
488  TYPE(fv_grid_bounds_type), INTENT(IN) :: bd
489  INTEGER, INTENT(IN) :: km, grid_type
490  REAL, INTENT(IN) :: u(bd%isd:bd%ied, bd%jsd:bd%jed+1, km)
491  REAL :: u_ad(bd%isd:bd%ied, bd%jsd:bd%jed+1, km)
492  REAL, INTENT(IN) :: v(bd%isd:bd%ied+1, bd%jsd:bd%jed, km)
493  REAL :: v_ad(bd%isd:bd%ied+1, bd%jsd:bd%jed, km)
494  TYPE(fv_grid_type), INTENT(IN), TARGET :: gridstruct
495  LOGICAL, INTENT(IN) :: do_halo
496  REAL :: ua(bd%isd:bd%ied, bd%jsd:bd%jed, km)
497  REAL :: ua_ad(bd%isd:bd%ied, bd%jsd:bd%jed, km)
498  REAL :: va(bd%isd:bd%ied, bd%jsd:bd%jed, km)
499  REAL :: va_ad(bd%isd:bd%ied, bd%jsd:bd%jed, km)
500  REAL :: wu(bd%is-1:bd%ie+1, bd%js-1:bd%je+2)
501  REAL :: wu_ad(bd%is-1:bd%ie+1, bd%js-1:bd%je+2)
502  REAL :: wv(bd%is-1:bd%ie+2, bd%js-1:bd%je+1)
503  REAL :: wv_ad(bd%is-1:bd%ie+2, bd%js-1:bd%je+1)
504  REAL :: u1(bd%is-1:bd%ie+1), v1(bd%is-1:bd%ie+1)
505  REAL :: u1_ad(bd%is-1:bd%ie+1), v1_ad(bd%is-1:bd%ie+1)
506  INTEGER :: i, j, k
507  INTEGER :: is, ie, js, je
508  REAL, DIMENSION(:, :), POINTER :: a11, a12, a21, a22
509  REAL, DIMENSION(:, :), POINTER :: dx, dy, rdxa, rdya
510  REAL :: temp_ad
511  REAL :: temp_ad0
512  INTEGER :: branch
513  !TYPE(C_PTR) :: cptr
514  !INTEGER :: unknown_shape_in_c2l_ord2
515 
516  wu = 0.0
517  wv = 0.0
518  u1 = 0.0
519  v1 = 0.0
520  is = 0
521  ie = 0
522  js = 0
523  je = 0
524  branch = 0
525 
526  CALL popinteger(js)
527  !CALL POPPOINTER8(cptr)
528  a21 => gridstruct%a21 ! (/unknown_shape_in_c2l_ord2/))
529  !CALL POPPOINTER8(cptr)
530  a22 => gridstruct%a22 ! (/unknown_shape_in_c2l_ord2/))
531  !CALL POPPOINTER8(cptr)
532  dx => gridstruct%dx ! (/unknown_shape_in_c2l_ord2/))
533  !CALL POPPOINTER8(cptr)
534  dy => gridstruct%dy ! (/unknown_shape_in_c2l_ord2/))
535  CALL popinteger(ie)
536  CALL popinteger(is)
537  !CALL POPPOINTER8(cptr)
538  a11 => gridstruct%a11 ! (/unknown_shape_in_c2l_ord2/))
539  !CALL POPPOINTER8(cptr)
540  a12 => gridstruct%a12 ! (/unknown_shape_in_c2l_ord2/))
541  CALL popinteger(je)
542  wu_ad = 0.0
543  v1_ad = 0.0
544  wv_ad = 0.0
545  u1_ad = 0.0
546  DO k=km,1,-1
547  CALL popcontrol(1,branch)
548  IF (branch .EQ. 0) THEN
549  DO j=je,js,-1
550  DO i=ie,is,-1
551  CALL poprealarray(va(i, j, k))
552  v_ad(i, j, k) = v_ad(i, j, k) + 0.5*va_ad(i, j, k)
553  v_ad(i+1, j, k) = v_ad(i+1, j, k) + 0.5*va_ad(i, j, k)
554  va_ad(i, j, k) = 0.0
555  CALL poprealarray(ua(i, j, k))
556  u_ad(i, j, k) = u_ad(i, j, k) + 0.5*ua_ad(i, j, k)
557  u_ad(i, j+1, k) = u_ad(i, j+1, k) + 0.5*ua_ad(i, j, k)
558  ua_ad(i, j, k) = 0.0
559  END DO
560  END DO
561  ELSE
562  DO j=je,js,-1
563  DO i=ie,is,-1
564  CALL poprealarray(va(i, j, k))
565  u1_ad(i) = u1_ad(i) + a11(i, j)*ua_ad(i, j, k) + a21(i, j)*&
566 & va_ad(i, j, k)
567  v1_ad(i) = v1_ad(i) + a12(i, j)*ua_ad(i, j, k) + a22(i, j)*&
568 & va_ad(i, j, k)
569  va_ad(i, j, k) = 0.0
570  CALL poprealarray(ua(i, j, k))
571  ua_ad(i, j, k) = 0.0
572  temp_ad = 2.*v1_ad(i)/(dy(i, j)+dy(i+1, j))
573  wv_ad(i, j) = wv_ad(i, j) + temp_ad
574  wv_ad(i+1, j) = wv_ad(i+1, j) + temp_ad
575  v1_ad(i) = 0.0
576  temp_ad0 = 2.*u1_ad(i)/(dx(i, j)+dx(i, j+1))
577  wu_ad(i, j) = wu_ad(i, j) + temp_ad0
578  wu_ad(i, j+1) = wu_ad(i, j+1) + temp_ad0
579  u1_ad(i) = 0.0
580  END DO
581  END DO
582  DO j=je,js,-1
583  DO i=ie+1,is,-1
584  v_ad(i, j, k) = v_ad(i, j, k) + dy(i, j)*wv_ad(i, j)
585  wv_ad(i, j) = 0.0
586  END DO
587  END DO
588  DO j=je+1,js,-1
589  DO i=ie,is,-1
590  u_ad(i, j, k) = u_ad(i, j, k) + dx(i, j)*wu_ad(i, j)
591  wu_ad(i, j) = 0.0
592  END DO
593  END DO
594  END IF
595  END DO
596  END SUBROUTINE c2l_ord2_bwd
597  SUBROUTINE c2l_ord2(u, v, ua, va, gridstruct, km, grid_type, bd, &
598 & do_halo)
599  IMPLICIT NONE
600  TYPE(fv_grid_bounds_type), INTENT(IN) :: bd
601  INTEGER, INTENT(IN) :: km, grid_type
602  REAL, INTENT(IN) :: u(bd%isd:bd%ied, bd%jsd:bd%jed+1, km)
603  REAL, INTENT(IN) :: v(bd%isd:bd%ied+1, bd%jsd:bd%jed, km)
604  TYPE(fv_grid_type), INTENT(IN), TARGET :: gridstruct
605  LOGICAL, INTENT(IN) :: do_halo
606 !
607  REAL, INTENT(OUT) :: ua(bd%isd:bd%ied, bd%jsd:bd%jed, km)
608  REAL, INTENT(OUT) :: va(bd%isd:bd%ied, bd%jsd:bd%jed, km)
609 !--------------------------------------------------------------
610 ! Local
611  REAL :: wu(bd%is-1:bd%ie+1, bd%js-1:bd%je+2)
612  REAL :: wv(bd%is-1:bd%ie+2, bd%js-1:bd%je+1)
613  REAL :: u1(bd%is-1:bd%ie+1), v1(bd%is-1:bd%ie+1)
614  INTEGER :: i, j, k
615  INTEGER :: is, ie, js, je
616  REAL, DIMENSION(:, :), POINTER :: a11, a12, a21, a22
617  REAL, DIMENSION(:, :), POINTER :: dx, dy, rdxa, rdya
618  a11 => gridstruct%a11
619  a12 => gridstruct%a12
620  a21 => gridstruct%a21
621  a22 => gridstruct%a22
622  dx => gridstruct%dx
623  dy => gridstruct%dy
624  rdxa => gridstruct%rdxa
625  rdya => gridstruct%rdya
626  IF (do_halo) THEN
627  is = bd%is - 1
628  ie = bd%ie + 1
629  js = bd%js - 1
630  je = bd%je + 1
631  ELSE
632  is = bd%is
633  ie = bd%ie
634  js = bd%js
635  je = bd%je
636  END IF
637 !$OMP parallel do default(none) shared(is,ie,js,je,km,grid_type,u,dx,v,dy,ua,va,a11,a12,a21,a22) &
638 !$OMP private(u1, v1, wu, wv)
639  DO k=1,km
640  IF (grid_type .LT. 4) THEN
641  DO j=js,je+1
642  DO i=is,ie
643  wu(i, j) = u(i, j, k)*dx(i, j)
644  END DO
645  END DO
646  DO j=js,je
647  DO i=is,ie+1
648  wv(i, j) = v(i, j, k)*dy(i, j)
649  END DO
650  END DO
651  DO j=js,je
652  DO i=is,ie
653 ! Co-variant to Co-variant "vorticity-conserving" interpolation
654  u1(i) = 2.*(wu(i, j)+wu(i, j+1))/(dx(i, j)+dx(i, j+1))
655  v1(i) = 2.*(wv(i, j)+wv(i+1, j))/(dy(i, j)+dy(i+1, j))
656 !!! u1(i) = (wu(i,j) + wu(i,j+1)) * rdxa(i,j)
657 !!! v1(i) = (wv(i,j) + wv(i+1,j)) * rdya(i,j)
658 ! Cubed (cell center co-variant winds) to lat-lon:
659  ua(i, j, k) = a11(i, j)*u1(i) + a12(i, j)*v1(i)
660  va(i, j, k) = a21(i, j)*u1(i) + a22(i, j)*v1(i)
661  END DO
662  END DO
663  ELSE
664 ! 2nd order:
665  DO j=js,je
666  DO i=is,ie
667  ua(i, j, k) = 0.5*(u(i, j, k)+u(i, j+1, k))
668  va(i, j, k) = 0.5*(v(i, j, k)+v(i+1, j, k))
669  END DO
670  END DO
671  END IF
672  END DO
673  END SUBROUTINE c2l_ord2
674 
675  subroutine g_sum_adm(domain, p, p_ad, ifirst, ilast, jfirst, jlast, ngc, area, mode, reproduce, g_sum_ad)
676 ! Fast version of globalsum
677  integer, intent(IN) :: ifirst, ilast
678  integer, intent(IN) :: jfirst, jlast, ngc
679  integer, intent(IN) :: mode ! if ==1 divided by area
680  logical, intent(in), optional :: reproduce
681  real, intent(IN) :: p(ifirst:ilast,jfirst:jlast) ! field to be summed
682  real, intent(INOUT) :: p_ad(ifirst:ilast,jfirst:jlast) ! field to be summed
683  real(kind=R_GRID), intent(IN) :: area(ifirst-ngc:ilast+ngc,jfirst-ngc:jlast+ngc)
684  type(domain2d), intent(IN) :: domain
685  real, intent(INOUT) :: g_sum_ad
686  real, dimension(ifirst:ilast,jfirst:jlast) :: gsuma_ad, tmp
687  real, dimension(ifirst:ilast,jfirst:jlast) :: arg1_ad
688  integer :: i,j
689  real gsum, gsum_ad
690  logical, SAVE :: g_sum_initialized = .false.
691  real(kind=R_GRID), SAVE :: global_area
692 
693  if ( .not. g_sum_initialized ) then
694  global_area = mpp_global_sum(domain, area, flags=bitwise_efp_sum)
695  if ( is_master() ) write(*,*) 'Global Area=',global_area
696  g_sum_initialized = .true.
697  end if
698 
699  if ( mode==1 ) then
700  gsum_ad = g_sum_ad / global_area
701  else
702  gsum_ad = g_sum_ad
703  endif
704 
705 !!-------------------------
706 !! FMS global sum algorithm:
707 !!-------------------------
708 ! if ( present(reproduce) ) then
709 ! if (reproduce) then
710 ! call mpp_global_sum_ad(domain, arg1_ad(:,:), gsum_ad, flags=BITWISE_EFP_SUM)
711 ! p_ad = p_ad + area(ifirst:ilast, jfirst:jlast)*arg1_ad
712 ! else
713 ! call mpp_global_sum_ad(domain, arg1_ad(:,:), gsum_ad)
714 ! p_ad = p_ad + area(ifirst:ilast, jfirst:jlast)*arg1_ad
715 ! endif
716 ! else
717 !!-------------------------
718 !! Quick local sum algorithm
719 !!-------------------------
720 ! call mpp_global_sum_ad(domain, gsuma_ad, gsum_ad)
721 ! do j=jfirst,jlast
722 ! do i=ifirst,ilast
723 ! p_ad(i, j) = p_ad(i, j) + area(i, j)*gsuma_ad(i,j)
724 ! enddo
725 ! enddo
726 ! endif
727 
728  p_ad = 0.0
729 
730  end subroutine g_sum_adm
731 
732  real function g_sum(domain, p, ifirst, ilast, jfirst, jlast, ngc, area, mode, reproduce)
733 ! Fast version of globalsum
734  integer, intent(IN) :: ifirst, ilast
735  integer, intent(IN) :: jfirst, jlast, ngc
736  integer, intent(IN) :: mode ! if ==1 divided by area
737  logical, intent(in), optional :: reproduce
738  real, intent(IN) :: p(ifirst:ilast,jfirst:jlast) ! field to be summed
739  real(kind=R_GRID), intent(IN) :: area(ifirst-ngc:ilast+ngc,jfirst-ngc:jlast+ngc)
740  type(domain2d), intent(IN) :: domain
741  integer :: i,j
742  real gsum
743  logical, SAVE :: g_sum_initialized = .false.
744  real(kind=R_GRID), SAVE :: global_area
745  real :: tmp(ifirst:ilast,jfirst:jlast)
746 
747  if ( .not. g_sum_initialized ) then
748  global_area = mpp_global_sum(domain, area, flags=bitwise_efp_sum)
749  if ( is_master() ) write(*,*) 'Global Area=',global_area
750  g_sum_initialized = .true.
751  end if
752 
753 !-------------------------
754 ! FMS global sum algorithm:
755 !-------------------------
756  if ( present(reproduce) ) then
757  if (reproduce) then
758  gsum = mpp_global_sum(domain, p(:,:)*area(ifirst:ilast,jfirst:jlast), &
759  flags=bitwise_efp_sum)
760  else
761  gsum = mpp_global_sum(domain, p(:,:)*area(ifirst:ilast,jfirst:jlast))
762  endif
763  else
764 !-------------------------
765 ! Quick local sum algorithm
766 !-------------------------
767  gsum = 0.
768  do j=jfirst,jlast
769  do i=ifirst,ilast
770  gsum = gsum + p(i,j)*area(i,j)
771  enddo
772  enddo
773  call mp_reduce_sum(gsum)
774  endif
775 
776  if ( mode==1 ) then
777  g_sum = gsum / global_area
778  else
779  g_sum = gsum
780  endif
781 
782  end function g_sum
783 
784  end module fv_grid_utils_adm_mod
real, parameter, public radius
Radius of the Earth [m].
Definition: constants.F90:72
real function, public great_circle_dist(q1, q2, radius)
real, parameter, public omega
Rotation rate of the Earth [1/s].
Definition: constants.F90:75
real(kind=8), parameter, public pi_8
Ratio of circle circumference to diameter [N/A].
Definition: constants.F90:73
subroutine c2l_ord4(u, v, ua, va, gridstruct, npx, npy, km, grid_type, domain, nested, mode, bd)
subroutine, public set_eta(km, ks, ptop, ak, bk)
Definition: fv_eta_nlm.F90:392
integer, parameter, public corner
integer, parameter, public f_p
subroutine, public pushcontrol(ctype, field)
subroutine, public g_sum_adm(domain, p, p_ad, ifirst, ilast, jfirst, jlast, ngc, area, mode, reproduce, g_sum_ad)
Definition: mpp.F90:39
integer, parameter, public agrid
subroutine, public c2l_ord2_fwd(u, v, ua, va, gridstruct, km, grid_type, bd, do_halo)
integer, parameter, public ng
subroutine timing_on(blk_name)
subroutine, public c2l_ord2(u, v, ua, va, gridstruct, km, grid_type, bd, do_halo)
real, parameter, public big_number
integer, parameter, public r_grid
real, parameter tiny_number
real function, public g_sum(domain, p, ifirst, ilast, jfirst, jlast, ngc, area, mode, reproduce)
subroutine, public cubed_to_latlon(u, v, ua, va, gridstruct, npx, npy, km, mode, grid_type, domain, nested, c2l_ord, bd)
#define max(a, b)
Definition: mosaic_util.h:33
subroutine grid_utils_init(atm, npx, npy, npz, non_ortho, grid_type, c2l_order)
subroutine, public c2l_ord2_bwd(u, u_ad, v, v_ad, ua, ua_ad, va, va_ad, gridstruct, km, grid_type, bd, do_halo)
#define min(a, b)
Definition: mosaic_util.h:32
integer, parameter, public scalar_pair
subroutine, public popcontrol(ctype, field)
integer, parameter, public cgrid_ne
Derived type containing the data.
real, parameter, public ptop_min
real(fp), parameter, public pi
subroutine timing_off(blk_name)