FMS  2026.01.01-dev
Flexible Modeling System
horiz_interp.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_mod horiz_interp_mod
19 !! @ingroup horiz_interp
20 !! @{
21 !! @author Zhi Liang, Bruce Wyman
22 !!
23 !! @parblock
24 !! Horiz_interp_mod contains subroutines and derived types to interpolate
25 !! data from any logically rectangular grid to any logically rectangular grid with
26 !! the following interpolation schemes: conservative in horiz_interp_conserve_mod,
27 !! bilinear in horiz_interp_bilinear_mod, bicubic in horiz_interp_bicubic_mod, and
28 !! inverse of square distance weighted in horiz_interp_spherical.mod.
29 !! @endparblock
30 
31 module horiz_interp_mod
32 
33 !-----------------------------------------------------------------------
34 !
35 ! Performs spatial interpolation between grids.
36 !
37 !-----------------------------------------------------------------------
38 
39 use fms_mod, only: write_version_number, fms_error_handler
40 use fms_mod, only: check_nml_error
41 use mpp_mod, only: mpp_error, fatal, stdout, stdlog, mpp_min
42 use mpp_mod, only: input_nml_file, warning, mpp_pe, mpp_root_pe
43 use constants_mod, only: pi
44 use horiz_interp_type_mod, only: horiz_interp_type, assignment(=)
45 use horiz_interp_type_mod, only: conserve, bilinear, spherical, bicubic
46 use horiz_interp_conserve_mod, only: horiz_interp_conserve_init, horiz_interp_conserve
47 use horiz_interp_conserve_mod, only: horiz_interp_conserve_new, horiz_interp_conserve_del
48 use horiz_interp_bilinear_mod, only: horiz_interp_bilinear_init, horiz_interp_bilinear
49 use horiz_interp_bilinear_mod, only: horiz_interp_bilinear_new, horiz_interp_bilinear_del
50 use horiz_interp_bilinear_mod, only: horiz_interp_read_weights_bilinear
51 use horiz_interp_bicubic_mod, only: horiz_interp_bicubic_init, horiz_interp_bicubic
52 use horiz_interp_bicubic_mod, only: horiz_interp_bicubic_new, horiz_interp_bicubic_del
53 use horiz_interp_spherical_mod, only: horiz_interp_spherical_init, horiz_interp_spherical
54 use horiz_interp_spherical_mod, only: horiz_interp_spherical_new, horiz_interp_spherical_del
55 use platform_mod, only: r4_kind, r8_kind
56 
57  implicit none
58  private
59 
60 !---- interfaces ----
61 
64 
65  !> @parblock
66  !! Generic interface to horiz_interp_new procedures to compute interpolation
67  !! weights and mapping indices. Following captures the main input arguemnts for each
68  !! member subroutine:
69  !! horiz_interp_new_1d_r4:
70  !! input and output grids are provided as 1D arrays in 32-bit floating point precision.
71  !! horiz_interp_new_1d_r8:
72  !! input and output grids are provided as 1D arrays in 64-bit floating point precision.
73  !! horiz_interp_new_1d_src_r4:
74  !! input grid is provided as 1D arrays, output grid as 2D arrays, both in 32-bit precision.
75  !! horiz_interp_new_1d_src_r8:
76  !! input grid is provided as 1D arrays, output grid as 2D arrays, both in 64-bit precision.
77  !! horiz_interp_new_2d_r4:
78  !! input and output grids are provided as 2D arrays in 32-bit precision.
79  !! horiz_interp_new_2d_r8:
80  !! input and output grids are provided as 2D arrays in 64-bit precision.
81  !! horiz_interp_new_1d_dst_r4:
82  !! input grid is provided as 2D arrays, output grid as 1D arrays, both in 32-bit precision.
83  !! horiz_interp_new_1d_dst_r8:
84  !! input grid is provided as 2D arrays, output grid as 1D arrays, both in 64-bit precision.
85  !! @endparblock
86  interface horiz_interp_new
87  ! Source grid is 1d, destination grid is 1d
88  module procedure horiz_interp_new_1d_r4
89  module procedure horiz_interp_new_1d_r8
90  ! Source grid is 1d, destination grid is 2d
91  module procedure horiz_interp_new_1d_src_r4
92  module procedure horiz_interp_new_1d_src_r8
93  ! Source grid is 2d, destination grid is 2d
94  module procedure horiz_interp_new_2d_r4
95  module procedure horiz_interp_new_2d_r8
96  ! Source grid is 2d, destination grid is 1d
97  module procedure horiz_interp_new_1d_dst_r4
98  module procedure horiz_interp_new_1d_dst_r8
99  end interface
100 
101  !> Generic interface to horiz_interp_read_weights_r4 and horiz_interp_read_weights_r8
102  !! to read in weight files generated from fregrid for bilinear interpolation.
103  !! Calls horiz_interp_read_weights_r4 if lat_out, lon_out, lat_in, and lon_in are
104  !! 32-bit floating point representation. Calls horiz_interp_read_weights_r8 if
105  !! the gridpoints are in 64-bit floating point representation.
107  module procedure horiz_interp_read_weights_r4
108  module procedure horiz_interp_read_weights_r8
109  end interface horiz_interp_read_weights
110 
111  !> @parblock
112  !! Generic interface to interpolate data on input (source) grid to output (target) grid.
113  !! Calls horiz_interp_base_2d_r4, horiz_interp_base_2d_r8, horiz_interp_base_3d_r4, or
114  !! horiz_interp_base_3d_r8 are if Interp (populated from horiz_interp_new) is the
115  !! first argument. Else, if Interp is not provided, calls horiz_interp_solo_* blackbox methods:
116  !! Following captures the main input arguments for each subroutine:
117  !! horiz_interp_base_2d_r4:
118  !! 2d input data to 2d output data in 32-bit floating point precision. Takes Interp as first argument.
119  !! horiz_interp_base_2d_r8:
120  !! 2d input data to 2d output data in 64-bit floating point precision. Takes Interp as first argument.
121  !! horiz_interp_base_3d_r4:
122  !! 3d input data to 3d output data in 32-bit floating point precision. Takes Interp as first argument.
123  !! horiz_interp_base_3d_r8:
124  !! 3d input data to 3d output data in 64-bit floating point precision. Takes Interp as first argument.
125  !! horiz_interp_solo_1d_r4:
126  !! input and output grids provided as 1D arrays to interpolate 32-bit 2D data.
127  !! Does not take Interp as argument.
128  !! horiz_interp_solo_1d_r8:
129  !! input and output grids provided as 1D arrays to interpolate 64-bit 2D data.
130  !! Does not take Interp as argument.
131  !! horiz_interp_solo_1d_src_r4:
132  !! input grid provided as 32-bit 1D arrays, output as 2D arrays to interpolate 32-bit 2D data.
133  !! Does not take Inerp as argument.
134  !! horiz_interp_solo_1d_src_r8:
135  !! input grid provided as 64-bit 1D arrays, output as 2D arrays to interpolate 32-bit 2D data.
136  !! Does not take Interp as argument.
137  !! horiz_interp_solo_2d_r4:
138  !! input and output grids provided as 32-bit 2D arrays to interpolate 32-bit 2d data.
139  !! Does not take Interp as argument.
140  !! horiz_interp_solo_2d_r8:
141  !! input and output grids provided as 64-bit 2D arrays to interpolate 64-bit 2d data.
142  !! Does not take Interp as argument.
143  !! horiz_interp_solo_1d_dst_r4:
144  !! input grid provided as 32-bit 2D arrays, input as 1D arrays to interpolate 32-bit 2D data.
145  !! Does not take Interp as argument.
146  !! horiz_interp_solo_1d_dst_r8
147  !! input grid provided as 64-bit 2D arrays, input as 1D arrays to interpolate 64-bit 2D data.
148  !! Does not take Interp as argument.
149  !! @endparblock
150  interface horiz_interp
151  module procedure horiz_interp_base_2d_r4
152  module procedure horiz_interp_base_2d_r8
153  module procedure horiz_interp_base_3d_r4
154  module procedure horiz_interp_base_3d_r8
155  module procedure horiz_interp_solo_1d_r4
156  module procedure horiz_interp_solo_1d_r8
157  module procedure horiz_interp_solo_1d_src_r4
158  module procedure horiz_interp_solo_1d_src_r8
159  module procedure horiz_interp_solo_2d_r4
160  module procedure horiz_interp_solo_2d_r8
161  module procedure horiz_interp_solo_1d_dst_r4
162  module procedure horiz_interp_solo_1d_dst_r8
163  module procedure horiz_interp_solo_old_r4
164  module procedure horiz_interp_solo_old_r8
165  end interface
166 
167 
168  !> Internally used subroutine to determine if the grid is a lat-lon grid.
169  !! Calls is_lat_lon_r4 if grids are in 32-bit floating point precision.
170  !! Calls is_lat_lon_r8 if grids are in 64-bit floating point precision.
171  interface is_lat_lon
172  module procedure is_lat_lon_r4
173  module procedure is_lat_lon_r8
174  end interface is_lat_lon
175 
176  !> Old interfaces, not recommended.
178  module procedure horiz_interp_solo_1d_r4
179  module procedure horiz_interp_solo_1d_r8
180  end interface horiz_interp_solo_1d
181 
182 
183  logical :: reproduce_siena = .false.
184  !< is a namelist flag to reproduces siena results if set to .true. Else, defaults
185  !! to false to decrease truncation error in function poly_area in file mosaic_util.c.
186  !! The truncation error of second order conservative remapping might be big for high resolution grid.
187  !! This namelist flag will be removed soon.
188 
189  namelist /horiz_interp_nml/ reproduce_siena
190 
191 !-----------------------------------------------------------------------
192 ! Include variable "version" to be written to log file.
193 #include<file_version.h>
194  logical :: module_is_initialized = .false.
195  !< is an internally used flag to prevent module re-initialization
196 !-----------------------------------------------------------------------
197 
198 contains
199 
200 !#######################################################################
201 
202  !> @parblock
203  !! Initializes horiz_interp_mod and writes version number to the logfile
204  !! @endparblock
205  subroutine horiz_interp_init
206  integer :: iunit, ierr, io
207 
208  if(module_is_initialized) return
209  call write_version_number("HORIZ_INTERP_MOD", version)
210 
211  read (input_nml_file, horiz_interp_nml, iostat=io)
212  ierr = check_nml_error(io,'horiz_interp_nml')
213  if (mpp_pe() == mpp_root_pe() ) then
214  iunit = stdlog()
215  write (iunit, nml=horiz_interp_nml)
216  endif
217 
218  if (reproduce_siena) then
219  call mpp_error(fatal, "horiz_interp_mod: You have overridden the default value of " // &
220  "reproduce_siena and set it to .true. in horiz_interp_nml. This was a temporary workaround to " // &
221  "allow for consistency in continuing experiments and is no longer supported. " // &
222  "Please remove this namelist.")
223  endif
224 
225  call horiz_interp_conserve_init
226  call horiz_interp_bilinear_init
227  call horiz_interp_bicubic_init
228  call horiz_interp_spherical_init
229 
230  module_is_initialized = .true.
231 
232  end subroutine horiz_interp_init
233 
234  !> @parblock
235  !! Deallocates memory in Interp holding the weights and mapping indices for the interpolation
236  !! method in Interp%interp_method.
237  !! @endparblock
238  subroutine horiz_interp_del ( Interp )
239 
240  type (horiz_interp_type), intent(inout) :: interp
241  !< will be reset after arrays holding interpolation weights and mapping indices are
242  !! deallocated and %is_allocated is set to .false.
243 
244 !-----------------------------------------------------------------------
245 ! releases space used by horiz_interp_type variables
246 ! must be called before re-initializing the same variable
247 !-----------------------------------------------------------------------
248  select case(interp % interp_method)
249  case (conserve)
250  call horiz_interp_conserve_del(interp )
251  case (bilinear)
252  call horiz_interp_bilinear_del(interp )
253  case (bicubic)
254  call horiz_interp_bicubic_del(interp )
255  case (spherical)
256  call horiz_interp_spherical_del(interp )
257  end select
258 
259  interp%I_am_initialized = .false.
260 !-----------------------------------------------------------------------
261 
262  end subroutine horiz_interp_del
263 
264  !#####################################################################
265 
266  !> @parblock
267  !! Dummy routine
268  !! @endparblock
269  subroutine horiz_interp_end
270  return
271  end subroutine horiz_interp_end
272 
273 #include "horiz_interp_r4.fh"
274 #include "horiz_interp_r8.fh"
275 
276 end module horiz_interp_mod
277 !> @}
278 ! 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
logical function, public fms_error_handler(routine, message, err_msg)
Facilitates the control of fatal error conditions.
Definition: fms.F90:468
subroutine, public horiz_interp_bicubic_del(Interp)
subroutine, public horiz_interp_bicubic_init
Generic interface to horiz_interp_bicubic_* to interpolate data using the weights stored in Interp....
subroutine, public horiz_interp_bilinear_del(Interp)
Deallocates memory used by "horiz_interp_type" variables.
subroutine, public horiz_interp_bilinear_init
Generic interface to interpolate data from a source grid to target grid using the weights stored in I...
Generic interface to populate Interp from a weight file generated from fregrid. Calls horiz_interp_re...
subroutine, public horiz_interp_conserve_init
subroutine, public horiz_interp_conserve_del(Interp)
Generic interface to interpolate data from source grid to target grid from the weights stored in Inte...
subroutine, public horiz_interp_del(Interp)
logical reproduce_siena
is a namelist flag to reproduces siena results if set to .true. Else, defaults to false to decrease t...
subroutine, public horiz_interp_init
logical module_is_initialized
is an internally used flag to prevent module re-initialization
subroutine, public horiz_interp_end
Generic interface to horiz_interp_read_weights_r4 and horiz_interp_read_weights_r8 to read in weight ...
Old interfaces, not recommended.
Internally used subroutine to determine if the grid is a lat-lon grid. Calls is_lat_lon_r4 if grids a...
subroutine, public horiz_interp_spherical_init
subroutine, public horiz_interp_spherical_del(Interp)
Generic interface to compute interpolation weights and mapping indices. Calls horiz_interp_spherical_...
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
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 stdlog()
This function returns the current standard fortran unit numbers for log messages. Log messages,...
Definition: mpp_util.inc:58
integer function mpp_pe()
Returns processor ID.
Definition: mpp_util.inc:406
Error handler.
Definition: mpp.F90:385
Reduction operations. Find the min of scalar a from the PEs in pelist result is also automatically br...
Definition: mpp.F90:590
Generic interface to horiz_interp_bicubic_new_* to compute interpolation weights and,...
Generic interface to compute interpolation weights and mapping indices. Member subroutines and their ...
Generic interface to compute interpolation weights and mapping indices. Member subroutines and their ...
Generic interface to interpolate data from source grid to target grid from the weights stored in Inte...