UFO
LAMDomainCheck.interface.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 to handle verifying that an observation is within a limited area model domain
7 
9 
10  use iso_c_binding
11  use kinds
13 
14  implicit none
15 
16  private
17 
18 contains
19 
20 ! -----------------------------------------------------------------------------
21 !> \brief subroutine lam_domaincheck_esg_c
22 !!
23 !! \details **lam_domaincheck_esg_c()** is a subroutine that for a given input defined ESG regional grid
24 !! and a given input lat/lon point, determines if the point is within or outside the regional domain
25 !! It takes the following arguments as input:
26 !! * float c_a - alpha parameter for ESG grid definition
27 !! * float c_k - kappa paremeter for ESG grid definition
28 !! * float c_plat - center point latitude of ESG grid (degrees)
29 !! * float c_plon - center point longitude of ESG grid (degrees)
30 !! * float c_pazi - azimuth angle for ESG grid definition (radians)
31 !! * int c_npx - number of grid points in x direction
32 !! * int c_npy - number of grid points in y direction
33 !! * float c_dx - grid spacing in degrees
34 !! * float c_dy - grid spacing in degrees
35 !! * float c_lat - input latitude (degrees)
36 !! * float c_lon - input longitude (degrees)
37 !!
38 !! and returns c_mask, an integer of 1 (inside the domain) or 0 (outside the domain)
39 !! The above input arguments, c_lat and c_lon are independent for each observation.
40 !! The other input arguments are available as global attributes in the FV3 regional grid netCDF file.
41 !!
42 
43 subroutine lam_domaincheck_esg_c(c_a, c_k, c_plat, c_plon, c_pazi, c_npx, c_npy,&
44  c_dx, c_dy, c_lat, c_lon, c_mask) &
45  bind(c, name='lam_domaincheck_esg_f90')
46  use esg_grid_mod, only: gtoxm_ak_rr
47  implicit none
48  real(c_float), intent(in ) :: c_a, c_k, c_plat, c_plon, c_pazi, c_dx, c_dy
49  real(c_float), intent(in ) :: c_lat, c_lon
50  integer(c_int), intent(in ) :: c_npx, c_npy
51  integer(c_int), intent(inout) :: c_mask
52  real(kind_real), dimension(2) :: xm
53  logical :: failure
54 
55  real(kind_real) :: a, k, plat, plon, pazi, dx, dy, lat, lon
56  integer :: npx, npy
57 
58  !! convert integers
59  npx = int(c_npx)
60  npy = int(c_npy)
61  !! convert from C to kind_real
62  a = real(c_a, kind_real)
63  k = real(c_k, kind_real)
64  ! some need converted from degrees to radians
65  plat = real(c_plat, kind_real)*deg2rad
66  plon = real(c_plon, kind_real)*deg2rad
67  pazi = real(c_pazi, kind_real)
68  ! dx and dy are on the supergrid, for actual grid resolution is half
69  dx = real(c_dx, kind_real)*deg2rad*two
70  dy = real(c_dy, kind_real)*deg2rad*two
71  lat = real(c_lat, kind_real)*deg2rad
72  lon = real(c_lon, kind_real)*deg2rad
73 
74  ! call highest level subroutine from Jim Purser's pesg.f90 code
75  call gtoxm_ak_rr(a, k, plat, plon, pazi,&
76  dx, dy, lat, lon, xm, failure)
77 
78  ! use xm to determine if mask is 1 (good) or 0 (bad)
79  c_mask = 0
80  if ((abs(xm(1)) < npx/2) .and. (abs(xm(2)) < npy/2) .and. (.not. failure)) then
81  c_mask = 1
82  end if
83 
84 end subroutine lam_domaincheck_esg_c
85 
86 ! -----------------------------------------------------------------------------
87 !> \brief subroutine lam_domaincheck_circle_c
88 !!
89 !! \details **lam_domaincheck_circle_c()** is a subroutine that for a given input defined circle regional grid
90 !! and a given input central lat/lon point and radius of circle, determines if the point is within or outside
91 !! the regional domain. Circle domain could be typical for regional MPAS applications.
92 !! It takes the following arguments as input:
93 !! * float c_cenlat - center point latitude of circle domain (degrees)
94 !! * float c_cenlon - center point longitude of circle domain (degrees)
95 !! * float c_radius - radius of circle domain (km)
96 !! * float c_lat - input latitude (degrees)
97 !! * float c_lon - input longitude (degrees)
98 !!
99 !! and returns c_mask, an integer of 1 (inside the domain) or 0 (outside the domain)
100 !! The above input arguments, c_lat and c_lon are independent for each observation.
101 !!
102 
103 subroutine lam_domaincheck_circle_c(c_cenlat, c_cenlon, c_radius, &
104  c_lat, c_lon, c_mask) &
105  bind(c, name='lam_domaincheck_circle_f90')
106  implicit none
107  real(c_float), intent(in ) :: c_cenlat, c_cenlon, c_radius
108  real(c_float), intent(in ) :: c_lat, c_lon
109  integer(c_int), intent(inout) :: c_mask
110 
111  real(kind_real) :: dlat, dlon, rr
112  real(kind_real) :: radius, cenlat, cenlon, lat, lon
113 
114  ! some need converted from degrees to radians
115  cenlat = real(c_cenlat, kind_real)*deg2rad
116  cenlon = real(c_cenlon, kind_real)*deg2rad
117  radius = real(c_radius, kind_real) ! in km
118  lat = real(c_lat, kind_real)*deg2rad
119  lon = real(c_lon, kind_real)*deg2rad
120 
121  ! calculate great-circle distance using haversine formula
122  dlat = half*abs(lat - cenlat)
123  dlon = half*abs(lon - cenlon)
124  rr = sqrt( sin(dlat)**2 + cos(lat)*cos(cenlat)*sin(dlon)**2 )
125  rr = two*asin(rr)*mean_earth_rad
126 
127  ! use rr to determine if mask is 1 (good) or 0 (bad)
128  c_mask = 0 ! outside domain
129  if (rr < radius) then
130  c_mask = 1
131  end if
132 
133 end subroutine lam_domaincheck_circle_c
134 
135 end module ufo_lamdomaincheck_mod_c
Fortran module of helper functions for FV3-LAM ESG grid domain configuration These routines are borro...
real(kind_real), parameter, public pi
real(kind_real), parameter, public deg2rad
real(kind_real), parameter, public mean_earth_rad
real(kind_real), parameter, public two
real(kind_real), parameter, public half
real(kind_real), parameter, public rad2deg
Fortran module to handle verifying that an observation is within a limited area model domain.
subroutine lam_domaincheck_esg_c(c_a, c_k, c_plat, c_plon, c_pazi, c_npx, c_npy, c_dx, c_dy, c_lat, c_lon, c_mask)
subroutine lam_domaincheck_esg_c
subroutine lam_domaincheck_circle_c(c_cenlat, c_cenlon, c_radius, c_lat, c_lon, c_mask)
subroutine lam_domaincheck_circle_c