FMS  2026.01.01-dev
Flexible Modeling System
horiz_interp_type.F90
1 !***********************************************************************
2 !* Apache License 2.0
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* Licensed under the Apache License, Version 2.0 (the "License");
7 !* you may not use this file except in compliance with the License.
8 !* You may obtain a copy of the License at
9 !*
10 !* http://www.apache.org/licenses/LICENSE-2.0
11 !*
12 !* FMS is distributed in the hope that it will be useful, but WITHOUT
13 !* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied;
14 !* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15 !* PARTICULAR PURPOSE. See the License for the specific language
16 !* governing permissions and limitations under the License.
17 !***********************************************************************
18 !> @defgroup horiz_interp_type_mod horiz_interp_type_mod
19 !! @ingroup horiz_interp
20 !! @{
21 !! @author Zhi Liang
22 !!
23 !! @parblock
24 !! Defines horiz_interp_type
25 !! @endparblock
26 
27 module horiz_interp_type_mod
28 
29 use mpp_mod, only : mpp_send, mpp_recv, mpp_sync_self, mpp_error, fatal
30 use mpp_mod, only : mpp_pe, mpp_root_pe, mpp_npes
31 use mpp_mod, only : comm_tag_1, comm_tag_2
32 use platform_mod, only: r4_kind, r8_kind
33 
34 implicit none
35 private
36 
37 
38 ! parameter to determine interpolation method
39  integer, parameter :: CONSERVE = 1 !< is an internally used parameter to mark conservative interpolation
40  integer, parameter :: bilinear = 2 !< is an internally used parameter to mark bilinear interpolation
41  integer, parameter :: spherical = 3 !< is an internally used parameter to mark spherical interpolation
42  integer, parameter :: bicubic = 4 !< is an internally used parameter to mark bicubic interpolation
43 
44 public :: conserve, bilinear, spherical, bicubic
45 public :: horiz_interp_type, stats, assignment(=)
46 
47 !> Interface to override the "=" operator to a horiz_interp_eq that will
48 !! copy the Interp instance of horiz_interp_type with Interp2 = Interp1
49 interface assignment(=)
50  module procedure horiz_interp_type_eq
51 end interface
52 
53 !> Generic interfaces to compute statistics for bilinear and spherical interpolation
54 !! Calls stats_r4 when the output data is in 32-bit precision. Calls stats_r8 when
55 !! the output data is in 64-bit precision.
56 interface stats
57  module procedure stats_r4
58  module procedure stats_r8
59 end interface
60 
61 
62 !> Nested derived type in horiz_interp_type that holds 64-bit interpolation weights, and
63 !! metadata. If 64-bit grid and data arrays are provided to horiz_interp, Interp%horizInterpReals8_type
64 !! will be initialized and populated with mapping weights.
66  real(kind=r8_kind), dimension(:,:), allocatable :: faci
67  !< holds weights for conservative interpolation version 1
68  real(kind=r8_kind), dimension(:,:), allocatable :: facj
69  !< holds weights for conservative interpolation version 1
70  real(kind=r8_kind), dimension(:,:), allocatable :: area_src
71  !< holds source grid area
72  real(kind=r8_kind), dimension(:,:), allocatable :: area_dst
73  !< holds destination grid area.
74  real(kind=r8_kind), dimension(:,:,:), allocatable :: wti
75  !< holds interpolation weights for bilinear interpolation; x-derivatives for bicubic interpolation.
76  real(kind=r8_kind), dimension(:,:,:), allocatable :: wtj
77  !< holds interpolation weights for bilinear interpolation; y-derivatives for bicubic interpolation.
78  real(kind=r8_kind), dimension(:,:,:), allocatable :: src_dist
79  !< holds distance between destination grid and neighbor source grid in spherical interpolation.
80  real(kind=r8_kind), dimension(:,:), allocatable :: rat_x
81  !< holds (x_dest -x_src_r)/(x_src_l -x_src_r) for bicubic interpolation
82  real(kind=r8_kind), dimension(:,:), allocatable :: rat_y
83  !< holds (y_src_l -y_src_r)/(y_src_l -y_src_r) for bicubic interpolation
84  real(kind=r8_kind), dimension(:), allocatable :: lon_in
85  !< holds the longitude coordinates on the source grid
86  real(kind=r8_kind), dimension(:), allocatable :: lat_in
87  !< holds the latitude coordinates on the source grid
88  real(kind=r8_kind), dimension(:), allocatable :: area_frac_dst
89  !< holds interpolation weights for conservative interpolation, version2
90  real(kind=r8_kind), dimension(:,:), allocatable :: mask_in
91  !< masks the input grid to skip input cells when interpolation
92  real(kind=r8_kind) :: max_src_dist
93  !< sets to max_dist in spherical interpolation
94  logical :: is_allocated = .false.
95  !< is .true. if Interp is populated
96 
98 
99 !> Nested derived type in horiz_interp_type that holds 32-bit interpolation weights, and
100 !! metadata. If 32-bit grid and data arrays are provided to horiz_interp, Interp%horizInterpReals4_type
101 !! will be initialized and populated with mapping weights.
103  real(kind=r4_kind), dimension(:,:), allocatable :: faci
104  !< holds weights for conservative interpolation version 1
105  real(kind=r4_kind), dimension(:,:), allocatable :: facj
106  !< holds weights for conservative interpolation version 1
107  real(kind=r4_kind), dimension(:,:), allocatable :: area_src
108  !< holds source grid area.
109  real(kind=r4_kind), dimension(:,:), allocatable :: area_dst
110  !< holds destination grid area.
111  real(kind=r4_kind), dimension(:,:,:), allocatable :: wti
112  !< holds interpolation weights for bilinear interpolation; x-derivatives for bicubic interpolation.
113  real(kind=r4_kind), dimension(:,:,:), allocatable :: wtj
114  !< holds interpolation weights for bilinear interpolation; y-derivatives for bicubic interpolation.
115  real(kind=r4_kind), dimension(:,:,:), allocatable :: src_dist
116  !< holds distance between destination grid and neighbor source grid in spherical interpolation.
117  real(kind=r4_kind), dimension(:,:), allocatable :: rat_x
118  !< holds (x_dest -x_src_r)/(x_src_l -x_src_r) for bicubic interpolation
119  real(kind=r4_kind), dimension(:,:), allocatable :: rat_y
120  !< holds (y_src_l -y_src_r)/(y_src_l -y_src_r) for bicubic interpolation
121  real(kind=r4_kind), dimension(:), allocatable :: lon_in
122  !< holds the longitude coordinates on the source grid
123  real(kind=r4_kind), dimension(:), allocatable :: lat_in
124  !< holds the latitude coordinates on the source grid
125  real(kind=r4_kind), dimension(:), allocatable :: area_frac_dst
126  !< holds interpolation weights for conservative interpolation, version2
127  real(kind=r4_kind), dimension(:,:), allocatable :: mask_in
128  !< masks the input grid to skip input cells when interpolation
129  real(kind=r4_kind) :: max_src_dist
130  !< sets to max_dist in spherical interpolation
131  logical :: is_allocated = .false.
132  !< is .true. if Interp is populated
133 
134 end type horizinterpreals4_type
135 
136 !> Datatype holding interpolation weights, mapping indices, and metadata for horizontal interpolation.
137 !! All real members are stored in horizInterpReals8_type if the grid and data are represented in 64-bit
138 !! floating point precision or horizInterpReals4_type if the grid and data are represented in 32-bit
139 !! floating point precision. Only one type, horizInterpReals4_type or horizInterpReals8_type, is allocated
140 !! and used for interpolation.
142  integer, dimension(:,:), allocatable :: ilon
143  !< contains the source grid mapping index in x-direction for conservative interpolation, version 1
144  integer, dimension(:,:), allocatable :: jlat
145  !< contains the source grid mapping indices in y-direction for conservative interpolation, version 1
146  integer, dimension(:,:,:), allocatable :: i_lon
147  !< contains the source grid mapping indices in x-direction for bicubic and bilinear interpolation
148  integer, dimension(:,:,:), allocatable :: j_lat
149  !< contains the source grid cell indices in y-direction for bicubic and bilinear interpolation
150  logical, dimension(:,:), allocatable :: found_neighbors
151  !< is not used
152  integer, dimension(:,:), allocatable :: num_found
153  !< stores the number of neighbors found in spherical interpolation
154  integer :: nlon_src
155  !< is the size of source grid in the x direction
156  integer :: nlat_src
157  !< is the size of source grid in the y direction
158  integer :: nlon_dst
159  !< is the size of destination grid in the x direction
160  integer :: nlat_dst
161  !< is the size of destination grid in the y direction
162  integer :: interp_method
163  !< is the interpolation method set to 1 for conservative; 2 for bilinear; 3 for spherical; 4 for bicubic.
164  logical :: i_am_initialized=.false.
165  !< is set to .true. in horiz_interp_new. Horiz_interp_base will fail if I_am_initialized = .false.
166  integer :: version
167  !< is set to 1 in horiz_interp_conserve_1dx1d_r4/8. Else set to 2; only used for conservative interpolation.
168  integer :: nxgrid
169  !< is the number of exchange grid cells for conservative interpolation, version 2.
170  integer, dimension(:), allocatable :: i_src
171  !< are the source grid mapping indices in the x-direction for conservative interpolation, version 2.
172  integer, dimension(:), allocatable :: j_src
173  !< are the source grid mapping indices in the y-direction for conservative interpolation, version 2.
174  integer, dimension(:), allocatable :: i_dst
175  !< are the destination grid mapping indices in the x-direction for conservative interpolation, version 2.
176  integer, dimension(:), allocatable :: j_dst
177  !< are the destination grid mapping indices in the y-direction for conservative interpolation, version 2.
179  !< holds more 64-bit floating point data required for interpolation.
181  !< holds more 32-bit floating point data required for interpolation.
182  end type
183 
184 contains
185 
186 !######################################################################################################################
187  !> @parblock
188  !! Subroutine invoked when calling the "=" operator to copy all members of input horiz_interp_type
189  !! into another instance of horiz_interp_type. Do not call subroutine directly. Instead, for copying,
190  !! use the "=" operator: Interp2 = Interp1.
191  !! @endparblock
192  subroutine horiz_interp_type_eq(horiz_interp_out, horiz_interp_in)
193  type(horiz_interp_type), intent(inout) :: horiz_interp_out
194  !< will contain the copied horiz_interp_type
195  type(horiz_interp_type), intent(in) :: horiz_interp_in
196  !< is the horiz_interp_type to copy
197 
198  if(.not.horiz_interp_in%I_am_initialized) then
199  call mpp_error(fatal,'horiz_interp_type_eq: horiz_interp_type variable on right hand side is unassigned')
200  endif
201 
202  if( allocated(horiz_interp_in%ilon )) &
203  horiz_interp_out%ilon = horiz_interp_in%ilon
204 
205  if( allocated(horiz_interp_in%jlat )) &
206  horiz_interp_out%jlat = horiz_interp_in%jlat
207 
208  if( allocated(horiz_interp_in%i_lon )) &
209  horiz_interp_out%i_lon = horiz_interp_in%i_lon
210 
211  if( allocated(horiz_interp_in%j_lat )) &
212  horiz_interp_out%j_lat = horiz_interp_in%j_lat
213 
214  if( allocated(horiz_interp_in%found_neighbors )) &
215  horiz_interp_out%found_neighbors = horiz_interp_in%found_neighbors
216 
217  if( allocated(horiz_interp_in%num_found )) &
218  horiz_interp_out%num_found = horiz_interp_in%num_found
219 
220  if( allocated(horiz_interp_in%i_src )) &
221  horiz_interp_out%i_src = horiz_interp_in%i_src
222 
223  if( allocated(horiz_interp_in%j_src )) &
224  horiz_interp_out%j_src = horiz_interp_in%j_src
225 
226  if( allocated(horiz_interp_in%i_dst )) &
227  horiz_interp_out%i_dst = horiz_interp_in%i_dst
228 
229  if( allocated(horiz_interp_in%j_dst )) &
230  horiz_interp_out%j_dst = horiz_interp_in%j_dst
231 
232  horiz_interp_out%nlon_src = horiz_interp_in%nlon_src
233  horiz_interp_out%nlat_src = horiz_interp_in%nlat_src
234  horiz_interp_out%nlon_dst = horiz_interp_in%nlon_dst
235  horiz_interp_out%nlat_dst = horiz_interp_in%nlat_dst
236  horiz_interp_out%interp_method = horiz_interp_in%interp_method
237  horiz_interp_out%I_am_initialized = .true.
238 
239  if(horiz_interp_in%horizInterpReals8_type%is_allocated) then
240 
241  if( allocated(horiz_interp_in%horizInterpReals8_type%faci)) &
242  horiz_interp_out%horizInterpReals8_type%faci = horiz_interp_in%horizInterpReals8_type%faci
243 
244  if( allocated( horiz_interp_in%horizInterpReals8_type%facj)) &
245  horiz_interp_out%horizInterpReals8_type%facj = horiz_interp_in%horizInterpReals8_type%facj
246 
247  if( allocated( horiz_interp_in%horizInterpReals8_type%area_src)) &
248  horiz_interp_out%horizInterpReals8_type%area_src = horiz_interp_in%horizInterpReals8_type%area_src
249 
250  if( allocated( horiz_interp_in%horizInterpReals8_type%area_dst)) &
251  horiz_interp_out%horizInterpReals8_type%area_dst = horiz_interp_in%horizInterpReals8_type%area_dst
252 
253  if( allocated( horiz_interp_in%horizInterpReals8_type%wti)) &
254  horiz_interp_out%horizInterpReals8_type%wti = horiz_interp_in%horizInterpReals8_type%wti
255 
256  if( allocated( horiz_interp_in%horizInterpReals8_type%wtj)) &
257  horiz_interp_out%horizInterpReals8_type%wtj = horiz_interp_in%horizInterpReals8_type%wtj
258 
259  if( allocated( horiz_interp_in%horizInterpReals8_type%src_dist)) &
260  horiz_interp_out%horizInterpReals8_type%src_dist = horiz_interp_in%horizInterpReals8_type%src_dist
261 
262  if( allocated( horiz_interp_in%horizInterpReals8_type%rat_x)) &
263  horiz_interp_out%horizInterpReals8_type%rat_x = horiz_interp_in%horizInterpReals8_type%rat_x
264 
265  if( allocated( horiz_interp_in%horizInterpReals8_type%rat_y)) &
266  horiz_interp_out%horizInterpReals8_type%rat_y = horiz_interp_in%horizInterpReals8_type%rat_y
267 
268  if( allocated( horiz_interp_in%horizInterpReals8_type%lon_in)) &
269  horiz_interp_out%horizInterpReals8_type%lon_in = horiz_interp_in%horizInterpReals8_type%lon_in
270 
271  if( allocated( horiz_interp_in%horizInterpReals8_type%lat_in)) &
272  horiz_interp_out%horizInterpReals8_type%lat_in = horiz_interp_in%horizInterpReals8_type%lat_in
273 
274  if( allocated( horiz_interp_in%horizInterpReals8_type%area_frac_dst)) &
275  horiz_interp_out%horizInterpReals8_type%area_frac_dst = horiz_interp_in%horizInterpReals8_type%area_frac_dst
276 
277  horiz_interp_out%horizInterpReals8_type%max_src_dist = horiz_interp_in%horizInterpReals8_type%max_src_dist
278 
279  horiz_interp_out%horizInterpReals8_type%is_allocated = .true.
280  ! this was left out previous to mixed mode
281  if( allocated(horiz_interp_in%horizInterpReals8_type%mask_in)) &
282  horiz_interp_out%horizInterpReals8_type%mask_in = horiz_interp_in%horizInterpReals8_type%mask_in
283 
284  else if (horiz_interp_in%horizInterpReals4_type%is_allocated) then
285  if( allocated(horiz_interp_in%horizInterpReals4_type%faci)) &
286  horiz_interp_out%horizInterpReals4_type%faci = horiz_interp_in%horizInterpReals4_type%faci
287 
288  if( allocated( horiz_interp_in%horizInterpReals4_type%facj)) &
289  horiz_interp_out%horizInterpReals4_type%facj = horiz_interp_in%horizInterpReals4_type%facj
290 
291  if( allocated( horiz_interp_in%horizInterpReals4_type%area_src)) &
292  horiz_interp_out%horizInterpReals4_type%area_src = horiz_interp_in%horizInterpReals4_type%area_src
293 
294  if( allocated( horiz_interp_in%horizInterpReals4_type%area_dst)) &
295  horiz_interp_out%horizInterpReals4_type%area_dst = horiz_interp_in%horizInterpReals4_type%area_dst
296 
297  if( allocated( horiz_interp_in%horizInterpReals4_type%wti)) &
298  horiz_interp_out%horizInterpReals4_type%wti = horiz_interp_in%horizInterpReals4_type%wti
299 
300  if( allocated( horiz_interp_in%horizInterpReals4_type%wtj)) &
301  horiz_interp_out%horizInterpReals4_type%wtj = horiz_interp_in%horizInterpReals4_type%wtj
302 
303  if( allocated( horiz_interp_in%horizInterpReals4_type%src_dist)) &
304  horiz_interp_out%horizInterpReals4_type%src_dist = horiz_interp_in%horizInterpReals4_type%src_dist
305 
306  if( allocated( horiz_interp_in%horizInterpReals4_type%rat_x)) &
307  horiz_interp_out%horizInterpReals4_type%rat_x = horiz_interp_in%horizInterpReals4_type%rat_x
308 
309  if( allocated( horiz_interp_in%horizInterpReals4_type%rat_y)) &
310  horiz_interp_out%horizInterpReals4_type%rat_y = horiz_interp_in%horizInterpReals4_type%rat_y
311 
312  if( allocated( horiz_interp_in%horizInterpReals4_type%lon_in)) &
313  horiz_interp_out%horizInterpReals4_type%lon_in = horiz_interp_in%horizInterpReals4_type%lon_in
314 
315  if( allocated( horiz_interp_in%horizInterpReals4_type%lat_in)) &
316  horiz_interp_out%horizInterpReals4_type%lat_in = horiz_interp_in%horizInterpReals4_type%lat_in
317 
318  if( allocated( horiz_interp_in%horizInterpReals4_type%area_frac_dst)) &
319  horiz_interp_out%horizInterpReals4_type%area_frac_dst = horiz_interp_in%horizInterpReals4_type%area_frac_dst
320 
321  horiz_interp_out%horizInterpReals4_type%max_src_dist = horiz_interp_in%horizInterpReals4_type%max_src_dist
322 
323  horiz_interp_out%horizInterpReals4_type%is_allocated = .true.
324  ! this was left out previous to mixed mode
325  if( allocated(horiz_interp_in%horizInterpReals4_type%mask_in)) &
326  horiz_interp_out%horizInterpReals4_type%mask_in = horiz_interp_in%horizInterpReals4_type%mask_in
327 
328  else
329  call mpp_error(fatal, "horiz_interp_type_eq: cannot assign unallocated real values from horiz_interp_in")
330  endif
331 
332  if(horiz_interp_in%interp_method == conserve) then
333  horiz_interp_out%version = horiz_interp_in%version
334  if(horiz_interp_in%version==2) horiz_interp_out%nxgrid = horiz_interp_in%nxgrid
335  end if
336 
337  end subroutine horiz_interp_type_eq
338 !######################################################################################################################
339 
340 #include "horiz_interp_type_r4.fh"
341 #include "horiz_interp_type_r8.fh"
342 
343 end module horiz_interp_type_mod
344 !> @}
345 ! close documentation grouping
integer, parameter, public bilinear
is an internally used parameter to mark bilinear interpolation
integer, parameter, public bicubic
is an internally used parameter to mark bicubic interpolation
integer, parameter, public spherical
is an internally used parameter to mark spherical interpolation
subroutine horiz_interp_type_eq(horiz_interp_out, horiz_interp_in)
Generic interfaces to compute statistics for bilinear and spherical interpolation Calls stats_r4 when...
Datatype holding interpolation weights, mapping indices, and metadata for horizontal interpolation....
Nested derived type in horiz_interp_type that holds 32-bit interpolation weights, and metadata....
Nested derived type in horiz_interp_type that holds 64-bit interpolation weights, and metadata....
subroutine mpp_sync_self(pelist, check, request, msg_size, msg_type)
This is to check if current PE's outstanding puts are complete but we can't use shmem_fence because w...
integer function mpp_npes()
Returns processor count for current pelist.
Definition: mpp_util.inc:420
integer function mpp_pe()
Returns processor ID.
Definition: mpp_util.inc:406
Error handler.
Definition: mpp.F90:385
Receive data from another PE.
Definition: mpp.F90:999
Send data to a receiving PE.
Definition: mpp.F90:1066