FMS  2026.01.01-dev
Flexible Modeling System
horiz_interp_spherical.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_spherical_mod horiz_interp_spherical_mod
19 !! @ingroup horiz_interp
20 !! @{
21 !! @brief Performs spatial interpolation between grids using inverse-distance-weighted scheme.
22 !! @parblock
23 !! Horiz_interp_spherical_mod contains methods called from horiz_interp_mod to interpolate data
24 !! from rectangular/tripolar grid to rectangular/tripolar grid using the inverse-distance-weighted
25 !! interpolation. Users are recommended to use the top-level horiz_interp_mod with "interp" set to
26 !! "spherical" for the inverse-distance-weighted interpolation.
27 !! @endparblock
28 module horiz_interp_spherical_mod
29 
30  use platform_mod, only : r4_kind, r8_kind
31  use mpp_mod, only : mpp_error, fatal, warning, stdout
32  use mpp_mod, only : mpp_root_pe, mpp_pe
33  use mpp_mod, only : input_nml_file
34  use fms_mod, only : write_version_number
35  use fms_mod, only : check_nml_error
36  use constants_mod, only : pi
37  use horiz_interp_type_mod, only : horiz_interp_type, stats, spherical
38 
39  implicit none
40  private
41 
42  !> Generic interface to interpolate data from source grid to target grid from the weights stored in Interp.
43  !! Calls horiz_interp_spherical_r4 if input and output data are 2D arrays in 32-bit precision.
44  !! Calls horiz_interp_spherical_r8 if input and output data are 2D arrays in 64-bit precision.
46  module procedure horiz_interp_spherical_r4
47  module procedure horiz_interp_spherical_r8
48  end interface
49 
50  !> Generic interface to compute interpolation weights and mapping indices.
51  !! Calls horiz_interp_spherical_new_r4 when input and output 2D grid arrays are in 32-bit precision.
52  !! Calls horiz_interp_spherical_new_r8 when input and output 2D grid arrays are in 64-bit precision.
54  module procedure horiz_interp_spherical_new_r4
55  module procedure horiz_interp_spherical_new_r8
56  end interface
57 
58  !> Unused interface
60  module procedure horiz_interp_spherical_wght_r4
61  module procedure horiz_interp_spherical_wght_r8
62  end interface
63 
66 
67 
68  !> Generic interface used internally when search_method = "full_search" to search
69  !! for nearest neighbors. Calls full_search_r4 when the input and output grids are in 32-bit
70  !! precision. Calls full_search_r8 when the input and output grids are in 64-bit precision.
71  interface full_search
72  module procedure full_search_r4
73  module procedure full_search_r8
74  end interface
75 
76  !> Generic interface used internally when search_method = "radial_search" to search
77  !! for nearest neighbors. Calls radial_search_r4 when the input and output grids are
78  !! in 32-bit precision. Calls radial_search_r8 when the input and output grids are in
79  !! 64-bit precision.
80  interface radial_search
81  module procedure radial_search_r4
82  module procedure radial_search_r8
83  end interface
84 
85  !> Generic inteface used internally in full_search and radial_search.
86  !! Calls spherical_distance_r4 when the lon and lat values are in 32-bit precision.
87  !! Calls spherical_distance_r8 when the lon and lat values are in 64-bit precision.
89  module procedure spherical_distance_r4
90  module procedure spherical_distance_r8
91  end interface
92 
93  integer, parameter :: max_neighbors = 400
94  !< is the maximum number of neighboring input grid cells around output grid cell.
95  real(r8_kind), parameter :: max_dist_default = 0.1_r8_kind
96  !< is the maximum angular distance in radians for input and output grid cells to neighbor.
97  integer, parameter :: num_nbrs_default = 4
98  !< is the minimum number of neighbors to compute for each output grid cell.
99  real(r8_kind), parameter :: large=1.e20_r8_kind !< is a large number
100  real(r8_kind), parameter :: epsln=1.e-10_r8_kind !< is a small number
101 
102  integer :: pe, root_pe
103 
104 
105  character(len=32) :: search_method = "radial_search"
106  !< is a namelist flag to set the nearest neighbor searching method to either "radial_search" (default)
107  !! or "full_search". When set to "radial_search", the search may not be as accurate for some cases.
108  !! Normally the search will be ok if you chose suitable max_dist. When search_method is "full_search",
109  !! it will be always accurate, but will be slower comparing to "radial_search". Normally these two search
110  !! algorithm will produce same results other than order of operation. "radial_search" are recommended to use.
111  !! The purpose to add "full_search" is in case you think you interpolation results is not right,
112  !! you have other option to verify.
113 
114  namelist /horiz_interp_spherical_nml/ search_method
115 
116 #include<file_version.h>
117  logical :: module_is_initialized = .false.
118 
119 contains
120 
121  !#######################################################################
122 
123  !> @parblock
124  !! Initializes horiz_interp_spherical_mod. Called from horiz_interp_init in horiz_interp_mod
125  !! @endparblock
127  integer :: ierr, io
128 
129 
130  if(module_is_initialized) return
131  call write_version_number("horiz_interp_spherical_mod", version)
132  read (input_nml_file, horiz_interp_spherical_nml, iostat=io)
133  ierr = check_nml_error(io,'horiz_interp_spherical_nml')
134 
135  module_is_initialized = .true.
136 
137  end subroutine horiz_interp_spherical_init
138 
139  !#######################################################################
140 
141  !> @parblock
142  !! Deallocates arrays holding spherical interpolation weights and mapping indices
143  !! in Interp. Resets %is_allocated to .false. Called from horiz_interp_del in horiz_interp_mod.
144  !! @endparblock
145  subroutine horiz_interp_spherical_del( Interp )
146 
147  type (horiz_interp_type), intent(inout) :: interp !< will be reset with deallocated memory
148 
149  if(interp%horizInterpReals4_type%is_allocated) then
150  if(allocated(interp%horizInterpReals4_type%src_dist)) deallocate(interp%horizInterpReals4_type%src_dist)
151  else if (interp%horizInterpReals8_type%is_allocated) then
152  if(allocated(interp%horizInterpReals8_type%src_dist)) deallocate(interp%horizInterpReals8_type%src_dist)
153  endif
154  if(allocated(interp%num_found)) deallocate(interp%num_found)
155  if(allocated(interp%i_lon)) deallocate(interp%i_lon)
156  if(allocated(interp%j_lat)) deallocate(interp%j_lat)
157 
158  interp%horizInterpReals4_type%is_allocated = .false.
159  interp%horizInterpReals8_type%is_allocated = .false.
160 
161  end subroutine horiz_interp_spherical_del
162 
163  !#######################################################################
164 
165 #include "horiz_interp_spherical_r4.fh"
166 #include "horiz_interp_spherical_r8.fh"
167 
168 end module horiz_interp_spherical_mod
169 !> @}
170 ! close documentation grouping
integer function, public check_nml_error(IOSTAT, NML_NAME)
Checks the iostat argument that is returned after reading a namelist and determines if the error code...
Definition: fms.F90:523
subroutine, public write_version_number(version, tag, unit)
Prints to the log file (or a specified unit) the version id string and tag name.
Definition: fms.F90:701
real(r8_kind), parameter large
is a large number
subroutine, public horiz_interp_spherical_init
subroutine, public horiz_interp_spherical_del(Interp)
real(r8_kind), parameter max_dist_default
is the maximum angular distance in radians for input and output grid cells to neighbor.
real(r8_kind), parameter epsln
is a small number
character(len=32) search_method
is a namelist flag to set the nearest neighbor searching method to either "radial_search" (default) o...
integer, parameter max_neighbors
is the maximum number of neighboring input grid cells around output grid cell.
integer, parameter num_nbrs_default
is the minimum number of neighbors to compute for each output grid cell.
Generic interface to compute interpolation weights and mapping indices. Calls horiz_interp_spherical_...
Generic inteface used internally in full_search and radial_search. Calls spherical_distance_r4 when t...
integer, parameter, public spherical
is an internally used parameter to mark spherical interpolation
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....
integer function stdout()
This function returns the current standard fortran unit numbers for output.
Definition: mpp_util.inc:42
integer function mpp_pe()
Returns processor ID.
Definition: mpp_util.inc:406
Error handler.
Definition: mpp.F90:385
Generic interface to interpolate data from source grid to target grid from the weights stored in Inte...