FMS 2025.01.02-dev
Flexible Modeling System
Loading...
Searching...
No Matches
mosaic2.inc
1!***********************************************************************
2!* GNU Lesser General Public License
3!*
4!* This file is part of the GFDL Flexible Modeling System (FMS).
5!*
6!* FMS is free software: you can redistribute it and/or modify it under
7!* the terms of the GNU Lesser General Public License as published by
8!* the Free Software Foundation, either version 3 of the License, or (at
9!* your option) any later version.
10!*
11!* FMS is distributed in the hope that it will be useful, but WITHOUT
12!* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13!* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14!* for more details.
15!*
16!* You should have received a copy of the GNU Lesser General Public
17!* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18!***********************************************************************
19
20!> @file
21
22!> @brief Get exchange grid information from mosaic xgrid file.
23!> Example usage:
24!!
25!! call get_mosaic_xgrid(fileobj, nxgrid, i1, j1, i2, j2, area)
26!!
27 subroutine get_mosaic_xgrid_(fileobj, i1, j1, i2, j2, area, ibegin, iend)
28 type(FmsNetcdfFile_t), intent(in) :: fileobj !> The file that contains exchange grid information.
29 integer, intent(inout) :: i1(:), j1(:), i2(:), j2(:) !> i and j indices for grids 1 and 2
30 real(kind=fms_mos_kind_), intent(inout) :: area(:) !> area of the exchange grid. The area is scaled to
31 !! represent unit earth area
32 integer, optional, intent(in) :: ibegin, iend
33
34 integer :: start(4), nread(4), istart
35 real(kind=fms_mos_kind_), dimension(2, size(i1(:))) :: tile1_cell, tile2_cell
36 integer :: nxgrid, n
37 real(kind=r8_kind) :: garea
38 real(kind=r8_kind) :: get_global_area
39
40 garea = get_global_area() !< get_global_area returns a r8_kind
41
42 ! When start and nread present, make sure nread(1) is the same as the size of the data
43 if(present(ibegin) .and. present(iend)) then
44 istart = ibegin
45 nxgrid = iend - ibegin + 1
46 if(nxgrid .NE. size(i1(:))) call mpp_error(fatal, .NE."get_mosaic_xgrid: nxgrid size(i1(:))")
47 if(nxgrid .NE. size(j1(:))) call mpp_error(fatal, .NE."get_mosaic_xgrid: nxgrid size(j1(:))")
48 if(nxgrid .NE. size(i2(:))) call mpp_error(fatal, .NE."get_mosaic_xgrid: nxgrid size(i2(:))")
49 if(nxgrid .NE. size(j2(:))) call mpp_error(fatal, .NE."get_mosaic_xgrid: nxgrid size(j2(:))")
50 if(nxgrid .NE. size(area(:))) call mpp_error(fatal, .NE."get_mosaic_xgrid: nxgrid size(area(:))")
51 else
52 istart = 1
53 nxgrid = size(i1(:))
54 endif
55
56 start = 1; nread = 1
57 start(1) = istart; nread(1) = nxgrid
58
59 call read_data(fileobj, 'xgrid_area', area, corner=start, edge_lengths=nread)
60
61 start = 1; nread = 1
62 nread(1) = 2
63 start(2) = istart; nread(2) = nxgrid
64
65 call read_data(fileobj, 'tile1_cell', tile1_cell, corner=start, edge_lengths=nread)
66 call read_data(fileobj, 'tile2_cell', tile2_cell, corner=start, edge_lengths=nread)
67
68 do n = 1, nxgrid
69 i1(n) = int(tile1_cell(1,n))
70 j1(n) = int(tile1_cell(2,n))
71 i2(n) = int(tile2_cell(1,n))
72 j2(n) = int(tile2_cell(2,n))
73 area(n) = real( real(area(n),r8_kind)/garea, fms_mos_kind_ )
74 end do
75
76 return
77
78 end subroutine get_mosaic_xgrid_
79 !###############################################################################
80 !> @brief Calculate grid cell area.
81 !> Calculate the grid cell area. The purpose of this routine is to make
82 !! sure the consistency between model grid area and exchange grid area.
83 !> @param lon geographical longitude of grid cell vertices.
84 !> @param lat geographical latitude of grid cell vertices.
85 !> @param[inout] area grid cell area.
86 !> <br>Example usage:
87 !! call calc_mosaic_grid_area(lon, lat, area)
88 subroutine calc_mosaic_grid_area_(lon, lat, area)
89 real(kind=fms_mos_kind_), dimension(:,:), intent(in) :: lon
90 real(kind=fms_mos_kind_), dimension(:,:), intent(in) :: lat
91 real(kind=fms_mos_kind_), dimension(:,:), intent(out) :: area
92 integer :: nlon, nlat
93
94 real(r8_kind) :: area_r8(size(area,1),size(area,2))
95
96 nlon = size(area,1)
97 nlat = size(area,2)
98 ! make sure size of lon, lat and area are consitency
99 if( size(lon,1) .NE. nlon+1 .OR. size(lat,1) .NE. nlon+1 ) &
100 call mpp_error(fatal, "mosaic_mod: size(lon,1) and size(lat,1) should equal to size(area,1)+1")
101 if( size(lon,2) .NE. nlat+1 .OR. size(lat,2) .NE. nlat+1 ) &
102 call mpp_error(fatal, "mosaic_mod: size(lon,2) and size(lat,2) should equal to size(area,2)+1")
103
104 ! get_grid_area only accepts double precision data
105 call get_grid_area( nlon, nlat, real(lon,r8_kind), real(lat,r8_kind), area_r8)
106
107 area=real(area_r8,fms_mos_kind_)
108
109 end subroutine calc_mosaic_grid_area_
110 !###############################################################################
111 !> @brief Calculate grid cell area using great cirlce algorithm
112 !> Calculate the grid cell area. The purpose of this routine is to make
113 !! sure the consistency between model grid area and exchange grid area.
114 !> @param lon geographical longitude of grid cell vertices.
115 !> @param lat geographical latitude of grid cell vertices.
116 !> @param[inout] area grid cell area.
117 !> <br>Example usage:
118 !! call calc_mosaic_grid_great_circle_area(lon, lat, area)
119 subroutine calc_mosaic_grid_great_circle_area_(lon, lat, area)
120 real(kind=fms_mos_kind_), dimension(:,:), intent(in) :: lon
121 real(kind=fms_mos_kind_), dimension(:,:), intent(in) :: lat
122 real(kind=fms_mos_kind_), dimension(:,:), intent(inout) :: area
123 integer :: nlon, nlat
124
125 real(r8_kind) :: area_r8(size(area,1),size(area,2))
126
127 nlon = size(area,1)
128 nlat = size(area,2)
129 ! make sure size of lon, lat and area are consitency
130 if( size(lon,1) .NE. nlon+1 .OR. size(lat,1) .NE. nlon+1 ) &
131 call mpp_error(fatal, "mosaic_mod: size(lon,1) and size(lat,1) should equal to size(area,1)+1")
132 if( size(lon,2) .NE. nlat+1 .OR. size(lat,2) .NE. nlat+1 ) &
133 call mpp_error(fatal, "mosaic_mod: size(lon,2) and size(lat,2) should equal to size(area,2)+1")
134
135 ! get_grid_great_circle_area only accepts r8_kind arguments
136 call get_grid_great_circle_area( nlon, nlat, real(lon,r8_kind), real(lat,r8_kind), area_r8)
137
138 area=real(area_r8, fms_mos_kind_)
139
140 end subroutine calc_mosaic_grid_great_circle_area_
141 !#####################################################################
142 !> This function check if a point (lon1,lat1) is inside a polygon (lon2(:), lat2(:))
143 !! lon1, lat1, lon2, lat2 are in radians.
144 function is_inside_polygon_(lon1, lat1, lon2, lat2 )
145 real(kind=fms_mos_kind_), intent(in) :: lon1, lat1
146 real(kind=fms_mos_kind_), intent(in) :: lon2(:), lat2(:)
147 logical :: IS_INSIDE_POLYGON_
148 integer :: npts, isinside
149 integer :: inside_a_polygon
150
151 npts = size(lon2(:))
152
153 !> inside_a_polygon function only accepts r8_kind real variables
154
155 isinside = inside_a_polygon(real(lon1,r8_kind), real(lat1,r8_kind), npts, real(lon2,r8_kind), real(lat2,r8_kind))
156 if(isinside == 1) then
157 is_inside_polygon_ = .true.
158 else
159 is_inside_polygon_ = .false.
160 endif
161
162 return
163
164 end function is_inside_polygon_
165!> @}