FMS 2025.01-dev
Flexible Modeling System
Loading...
Searching...
No Matches
interpolator.F90
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!> @defgroup interpolator_mod interpolator_mod
20!> @ingroup interpolator
21!> @brief A module to interpolate climatology data to model the grid.
22!> @author William Cooke <William.Cooke@noaa.gov>
23
24module interpolator_mod
25
26use mpp_mod, only : mpp_error, &
27 fatal, &
28 mpp_pe, &
29 mpp_init, &
30 mpp_exit, &
31 mpp_npes, &
32 warning, &
33 note, &
34 input_nml_file
35use mpp_domains_mod, only : mpp_domains_init, &
39 domain2d, &
42use diag_manager_mod, only : diag_manager_init, get_base_time, &
44 diag_axis_init
45use fms_mod, only : lowercase, write_version_number, &
46 fms_init, &
47 mpp_root_pe, stdlog, &
48 check_nml_error
49use fms2_io_mod, only : fmsnetcdffile_t, fms2_io_file_exist => file_exists, dimension_exists, &
50 open_file, fms2_io_read_data=>read_data, &
51 variable_exists, get_variable_num_dimensions, &
52 get_num_variables, get_dimension_size, &
53 get_variable_units, get_variable_names, &
54 get_time_calendar, close_file, &
55 get_variable_dimension_names, get_variable_sense
56
57use horiz_interp_mod, only : horiz_interp_type, &
60 assignment(=), &
63use time_manager_mod, only : time_type, &
64 set_time, &
65 set_date, &
69 leap_year, &
70 julian, noleap, &
71 get_date, &
72 get_date_julian, set_date_no_leap, &
73 set_date_julian, get_date_no_leap, &
74 print_date, &
75 operator(+), &
76 operator(-), &
77 operator(*), &
78 operator(>), &
79 operator(<), &
80 assignment(=), &
82use time_interp_mod, only : time_interp, year
83use constants_mod, only : grav, pi, seconds_per_day
84use platform_mod, only : r4_kind, r8_kind, r16_kind, fms_path_len, fms_file_len
85
86!--------------------------------------------------------------------
87
88implicit none
89private
90
91!---------------------------------------------------------------------
92!------- interfaces --------
93
94public interpolator_init, &
103
104!> Interpolates a field to a model grid
105!!
106!> Example usage:
107!! ~~~~~~~~~~{.f90}
108!! call interpolator (sulfate, model_time, p_half, model_data, name, is, js, clim_units)
109!! call interpolator (o3, model_time, p_half, model_data, "ozone", is, js)
110!! ~~~~~~~~~~
111!!
112!! The first option is used to generate sulfate models.
113!!
114!! The sulfate data is set by
115!! ~~~~~~~~~~{.f90}
116!! type(interpolate_type), intent(inout) :: sulfate
117!! ~~~~~~~~~~
118!! The name of the model is set by
119!! ~~~~~~~~~~{.f90}
120!! character(len=*), intent(in) :: name
121!! ~~~~~~~~~~
122!! The units used in this model are outputted to
123!! ~~~~~~~~~~{.f90}
124!! character(len=*), intent(out), optional :: clim_units
125!! ~~~~~~~~~~
126!!
127!! The second option is generate ozone models.
128!!
129!! The ozone data is set by
130!! ~~~~~~~~~~{.f90}
131!! type(interpolate_type), intent(inout) :: o3
132!! ~~~~~~~~~~
133!!
134!! Both of these options use the following variables in the model.
135!!
136!! The time used in the model is set by
137!!
138!! ~~~~~~~~~~{.f90}
139!! type(time_type), intent(in) :: model_time
140!! ~~~~~~~~~~
141!! The model pressure field is set by
142!! ~~~~~~~~~~{.f90}
143!! real, intent(in), dimension(:,:,:) :: p_half
144!! ~~~~~~~~~~
145!!
146!! @param [inout] <clim_type> The interpolate type previously defined by a call to interpolator_init
147!! @param [in] <field_name> The name of a field that you wish to interpolate
148!! @param [in] <Time> The model time that you wish to interpolate to
149!! @param [in] <phalf> The half level model pressure field
150!! @param [in] <is> Index for the physics window
151!! @param [in] <js> Index for the physics window
152!! @param [out] <interp_data> The model fields with the interpolated climatology data
153!! @param [out] <clim_units> The units of field_name
154!> @ingroup interpolator_mod
156 module procedure interpolator_4d_r4, interpolator_4d_r8
157 module procedure interpolator_3d_r4, interpolator_3d_r8
158 module procedure interpolator_2d_r4, interpolator_2d_r8
159 module procedure interpolator_4d_no_time_axis_r4, interpolator_4d_no_time_axis_r8
160 module procedure interpolator_3d_no_time_axis_r4, interpolator_3d_no_time_axis_r8
161 module procedure interpolator_2d_no_time_axis_r4, interpolator_2d_no_time_axis_r8
162end interface interpolator
163
164!> Private assignment override interface for interpolate type
165!> @ingroup interpolator_mod
166interface assignment(=)
167 module procedure interpolate_type_eq
168end interface
169
171 module procedure interpolator_init_r4
172 module procedure interpolator_init_r8
173end interface interpolator_init
174
176 module procedure fms2io_interpolator_init_r4
177 module procedure fms2io_interpolator_init_r8
178end interface fms2io_interpolator_init
179
181 module procedure get_axis_latlon_data_r4
182 module procedure get_axis_latlon_data_r8
183end interface get_axis_latlon_data
184
186 module procedure get_axis_level_data_r4
187 module procedure get_axis_level_data_r8
188end interface get_axis_level_data
189
191 module procedure cell_center2_r4
192 module procedure cell_center2_r8
193end interface cell_center2
194
196 module procedure cart_to_latlon_r4
197 module procedure cart_to_latlon_r8
198end interface cart_to_latlon
199
200interface latlon2xyz
201 module procedure latlon2xyz_r4
202 module procedure latlon2xyz_r8
203end interface latlon2xyz
204
206 module procedure diag_read_data_r4
207 module procedure diag_read_data_r8
208end interface diag_read_data
209
210interface read_data
211 module procedure read_data_r4
212 module procedure read_data_r8
213end interface read_data
214
216 module procedure read_data_no_time_axis_r4
217 module procedure read_data_no_time_axis_r8
218end interface read_data_no_time_axis
219
221 module procedure interp_linear_r4
222 module procedure interp_linear_r8
223end interface interp_linear
224
225!> Private interface for weighted scalar interpolation
226!!
227!> Example usage:
228!! ~~~~~~~~~~{.f90}
229!! call interp_weighted_scalar (pclim, phalf(ilon,j,:),hinterp_data(ilon,j,:,:),interp_data(ilon,j,:,:))
230!! call interp_weighted_scalar (pclim, phalf(ilon,j,:),hinterp_data(ilon,j,:),interp_data(ilon,j,:))
231!! ~~~~~~~~~~
232!!
233!! @param [in] <grdin> Input grid
234!! @param [in] <grdout> Output grid
235!! @param [in] <datin> Input data
236!! @param [out] <datout> Output data
237!> @ingroup interpolator_mod
239 module procedure interp_weighted_scalar_1d_r4, interp_weighted_scalar_1d_r8
240 module procedure interp_weighted_scalar_2d_r4, interp_weighted_scalar_2d_r8
241end interface interp_weighted_scalar
242
243!---------------------------------------------------------------------
244!----------- version number for this module --------------------------
245
246! Include variable "version" to be written to log file.
247#include<file_version.h>
248
249!> Redundant climatology data between fields
250!> @ingroup interpolate_type
251
252type, private :: interpolate_r4_type
253logical :: is_allocated = .false.
254real(r4_kind), allocatable :: lat(:) !< No description
255real(r4_kind), allocatable :: lon(:) !< No description
256real(r4_kind), allocatable :: latb(:) !< No description
257real(r4_kind), allocatable :: lonb(:) !< No description
258real(r4_kind), allocatable :: levs(:) !< No description
259real(r4_kind), allocatable :: halflevs(:) !< No description
260real(r4_kind), allocatable :: data5d(:,:,:,:,:) !< (nlatmod,nlonmod,nlevclim,size(time_init,2),nfields)
261real(r4_kind), allocatable :: pmon_pyear(:,:,:,:) !< No description
262real(r4_kind), allocatable :: pmon_nyear(:,:,:,:) !< No description
263real(r4_kind), allocatable :: nmon_nyear(:,:,:,:) !< No description
264real(r4_kind), allocatable :: nmon_pyear(:,:,:,:) !< No description
265real(r4_kind) :: tweight !< No description
266real(r4_kind) :: tweight1 !< The time weight between the climatology years
267real(r4_kind) :: tweight2 !< No description
268real(r4_kind) :: tweight3 !< The time weight between the month
269end type interpolate_r4_type
270
271type, private :: interpolate_r8_type
272logical :: is_allocated = .false.
273real(r8_kind), allocatable :: lat(:) !< No description
274real(r8_kind), allocatable :: lon(:) !< No description
275real(r8_kind), allocatable :: latb(:) !< No description
276real(r8_kind), allocatable :: lonb(:) !< No description
277real(r8_kind), allocatable :: levs(:) !< No description
278real(r8_kind), allocatable :: halflevs(:) !< No description
279real(r8_kind), allocatable :: data5d(:,:,:,:,:) !< (nlatmod,nlonmod,nlevclim,size(time_init,2),nfields)
280real(r8_kind), allocatable :: pmon_pyear(:,:,:,:) !< No description
281real(r8_kind), allocatable :: pmon_nyear(:,:,:,:) !< No description
282real(r8_kind), allocatable :: nmon_nyear(:,:,:,:) !< No description
283real(r8_kind), allocatable :: nmon_pyear(:,:,:,:) !< No description
284real(r8_kind) :: tweight !< No description
285real(r8_kind) :: tweight1 !< The time weight between the climatology years
286real(r8_kind) :: tweight2 !< No description
287real(r8_kind) :: tweight3 !< The time weight between the month
288end type interpolate_r8_type
289
290type, public :: interpolate_type
291private
292!Redundant data between fields
293!All climatology data
294type(interpolate_r4_type) :: r4_type
295type(interpolate_r8_type) :: r8_type
296type(horiz_interp_type) :: interph !< No description
297type(time_type), allocatable :: time_slice(:) !< An array of the times within the climatology.
298type(fmsnetcdffile_t) :: fileobj ! object that stores opened file information
299character(len=FMS_PATH_LEN) :: file_name !< Climatology filename
300integer :: time_flag !< Linear or seaonal interpolation?
301integer :: level_type !< Pressure or Sigma level
302integer :: is,ie,js,je !< No description
303integer :: vertical_indices !< direction of vertical
304 !! data axis
305logical :: climatological_year !< Is data for year = 0000?
306
307!Field specific data for nfields
308character(len=64), allocatable :: field_name(:) !< name of this field
309logical, allocatable :: has_level(:) !< indicate if the variable has level dimension
310integer, allocatable :: time_init(:,:) !< second index is the number of time_slices being
311 !! kept. 2 or ntime.
312integer, allocatable :: mr(:) !< Flag for conversion of climatology to mixing ratio.
313integer, allocatable :: out_of_bounds(:) !< Flag for when surface pressure is out of bounds.
314!++lwh
315integer, allocatable :: vert_interp(:) !< Flag for type of vertical interpolation.
316!--lwh
317!integer :: indexm, indexp, climatology
318integer,dimension(:), allocatable :: indexm !< No description
319integer,dimension(:), allocatable :: indexp !< No description
320integer,dimension(:), allocatable :: climatology !< No description
321
322type(time_type), allocatable :: clim_times(:,:) !< No description
323logical :: separate_time_vary_calc !< No description
324integer :: itaum !< No description
325integer :: itaup !< No description
326
327end type interpolate_type
328
329!> @addtogroup interpolator_mod
330!> @{
331
332logical :: module_is_initialized = .false.
333logical :: clim_diag_initialized = .false.
334
335integer :: ndim !< No description
336integer :: nvar !< No description
337integer :: ntime !< No description
338integer :: nlat !< No description
339integer :: nlatb !< No description
340integer :: nlon !< No description
341integer :: nlonb !< No description
342integer :: nlev !< No description
343integer :: nlevh !< No description
344integer :: len, ntime_in, num_fields !< No description
345
346! pletzer real, allocatable :: time_in(:)
347! sjs real, allocatable :: climdata(:,:,:), climdata2(:,:,:)
348
349character(len=64) :: units !< No description
350integer :: sense !< No description
351
352integer, parameter :: max_diag_fields = 30 !< No description
353
354! flags to indicate direction of vertical axis in data file
355integer, parameter :: increasing_downward = 1, increasing_upward = -1 !< Flags to indicate direction
356 !! of vertical axis in data file
357!++lwh
358! Flags to indicate whether the time interpolation should be linear or some other scheme for seasonal data.
359! NOTIME indicates that data file has no time axis.
360integer, parameter :: linear = 1, seasonal = 2, bilinear = 3, notime = 4 !< Flags to indicate whether the time
361 !! interpolation should be linear or some
362 !! other scheme for seasonal data.
363 !! NOTIME indicates
364 !! that data file has no time axis.
365
366! Flags to indicate where climatology pressure levels are pressure or sigma levels
367integer, parameter :: pressure = 1, sigma = 2 !< Flags to indicate where climatology pressure
368 !! levels are pressure or sigma levels
369
370! Flags to indicate whether the climatology units are mixing ratio (kg/kg) or column integral (kg/m2).
371! Vertical interpolation scheme requires mixing ratio at this time.
372integer, parameter :: no_conv = 1, kg_m2 = 2 !< Flags to indicate whether the climatology units
373 !! are mixing ratio (kg/kg) or column integral (kg/m2).
374 !! Vertical interpolation scheme requires mixing ratio at
375 !! this time.
376
377! Flags to indicate what to do when the model surface pressure exceeds the climatology surface pressure level.
378integer, parameter, public :: constant = 1, zero = 2 !< Flags to indicate what to do when the model surface
379 !! pressure exceeds the climatology surface pressure level.
380
381! Flags to indicate the type of vertical interpolation
382integer, parameter, public :: interp_weighted_p = 10, interp_linear_p = 20, interp_log_p = 30 !< Flags to indicate
383 !! the type of vertical interpolation
384!--lwh
385
386real(r8_kind), parameter :: tpi = (2.0_r8_kind*pi) ! 4.*acos(0.)
387real(r8_kind), parameter :: dtr = tpi/360._r8_kind
388
389
390
391integer :: num_clim_diag = 0 !< No description
392character(len=64) :: climo_diag_name(max_diag_fields) !< No description
393integer :: climo_diag_id(max_diag_fields), hinterp_id(max_diag_fields) !< No description
394real(r8_kind) :: missing_value = -1.e10_r8_kind !< No description
395! sjs integer :: itaum, itaup
396
397#ifdef ENABLE_QUAD_PRECISION
398! Higher precision (kind=16) for grid geometrical factors:
399 integer, parameter:: f_p = r16_kind !< Higher precision (kind=16) for grid geometrical factors
400#else
401! 64-bit precision (kind=8)
402 integer, parameter:: f_p = r8_kind !< 64-bit precision (kind=8)
403#endif
404
405logical :: read_all_on_init = .false. !< No description
406integer :: verbose = 0 !< No description
407logical :: conservative_interp = .true. !< No description
408logical :: retain_cm3_bug = .false. !< No description
409logical :: use_mpp_io = .false. !< Set to true to use mpp_io, otherwise fms2io is used
410
411namelist /interpolator_nml/ &
413
414contains
415
416!> @brief Assignment overload routine for interpolate_type, to be used
417!! through the assignment interface
418subroutine interpolate_type_eq (Out, In)
419
420type(interpolate_type), intent(in) :: In
421type(interpolate_type), intent(inout) :: Out
422
423 if(in%r4_type%is_allocated) then
424 if (allocated(in%r4_type%lat)) out%r4_type%lat = in%r4_type%lat
425 if (allocated(in%r4_type%lon)) out%r4_type%lon = in%r4_type%lon
426 if (allocated(in%r4_type%latb)) out%r4_type%latb = in%r4_type%latb
427 if (allocated(in%r4_type%lonb)) out%r4_type%lonb = in%r4_type%lonb
428 if (allocated(in%r4_type%levs)) out%r4_type%levs = in%r4_type%levs
429 if (allocated(in%r4_type%halflevs)) out%r4_type%halflevs = in%r4_type%halflevs
430 else if(in%r8_type%is_allocated) then
431 if (allocated(in%r8_type%lat)) out%r8_type%lat = in%r8_type%lat
432 if (allocated(in%r8_type%lon)) out%r8_type%lon = in%r8_type%lon
433 if (allocated(in%r8_type%latb)) out%r8_type%latb = in%r8_type%latb
434 if (allocated(in%r8_type%lonb)) out%r8_type%lonb = in%r8_type%lonb
435 if (allocated(in%r8_type%levs)) out%r8_type%levs = in%r8_type%levs
436 if (allocated(in%r8_type%halflevs)) out%r8_type%halflevs = in%r8_type%halflevs
437 end if
438
439 out%interph = in%interph
440 if (allocated(in%time_slice)) out%time_slice = in%time_slice
441 out%file_name = in%file_name
442 out%time_flag = in%time_flag
443 out%level_type = in%level_type
444 out%is = in%is
445 out%ie = in%ie
446 out%js = in%js
447 out%je = in%je
448 out%vertical_indices = in%vertical_indices
449 out%climatological_year = in%climatological_year
450 if (allocated(in%has_level )) out%has_level = in%has_level
451 if (allocated(in%field_name )) out%field_name = in%field_name
452 if (allocated(in%time_init )) out%time_init = in%time_init
453 if (allocated(in%mr )) out%mr = in%mr
454 if (allocated(in%out_of_bounds)) out%out_of_bounds = in%out_of_bounds
455 if (allocated(in%vert_interp )) out%vert_interp = in%vert_interp
456 if(in%r4_type%is_allocated) then
457 if (allocated(in%r4_type%data5d )) out%r4_type%data5d = in%r4_type%data5d
458 if (allocated(in%r4_type%pmon_pyear )) out%r4_type%pmon_pyear = in%r4_type%pmon_pyear
459 if (allocated(in%r4_type%pmon_nyear )) out%r4_type%pmon_nyear = in%r4_type%pmon_nyear
460 if (allocated(in%r4_type%nmon_nyear )) out%r4_type%nmon_nyear = in%r4_type%nmon_nyear
461 if (allocated(in%r4_type%nmon_pyear )) out%r4_type%nmon_pyear = in%r4_type%nmon_pyear
462 else if(in%r8_type%is_allocated) then
463 if (allocated(in%r8_type%data5d )) out%r8_type%data5d = in%r8_type%data5d
464 if (allocated(in%r8_type%pmon_pyear )) out%r8_type%pmon_pyear = in%r8_type%pmon_pyear
465 if (allocated(in%r8_type%pmon_nyear )) out%r8_type%pmon_nyear = in%r8_type%pmon_nyear
466 if (allocated(in%r8_type%nmon_nyear )) out%r8_type%nmon_nyear = in%r8_type%nmon_nyear
467 if (allocated(in%r8_type%nmon_pyear )) out%r8_type%nmon_pyear = in%r8_type%nmon_pyear
468 end if
469 if (allocated(in%indexm )) out%indexm = in%indexm
470 if (allocated(in%indexp )) out%indexp = in%indexp
471 if (allocated(in%climatology )) out%climatology = in%climatology
472 if (allocated(in%clim_times )) out%clim_times = in%clim_times
473 out%separate_time_vary_calc = in%separate_time_vary_calc
474 if(in%r4_type%is_allocated) then
475 out%r4_type%tweight = in%r4_type%tweight
476 out%r4_type%tweight1 = in%r4_type%tweight1
477 out%r4_type%tweight2 = in%r4_type%tweight2
478 out%r4_type%tweight3 = in%r4_type%tweight3
479 else if(in%r8_type%is_allocated) then
480 out%r8_type%tweight = in%r8_type%tweight
481 out%r8_type%tweight1 = in%r8_type%tweight1
482 out%r8_type%tweight2 = in%r8_type%tweight2
483 out%r8_type%tweight3 = in%r8_type%tweight3
484 end if
485 out%itaum = in%itaum
486 out%itaup = in%itaup
487
488 out%r4_type%is_allocated = in%r4_type%is_allocated
489 out%r8_type%is_allocated = out%r8_type%is_allocated
490
491end subroutine interpolate_type_eq
492
493
494
495
496!#######################################################################
497!
498!---------------------------------------------------------------------
499!> @brief check_climo_units checks the units that the climatology
500!! data is using. This is needed to allow for conversion of
501!! datasets to mixing ratios which is what the vertical
502!! interpolation scheme requires. The default is to assume no
503!! conversion is needed. If the units are those of a column
504!! burden (kg/m2) then conversion to mixing ratio is flagged.
505!!
506!! @param [in] <units> The units which you will be checking
507function check_climo_units(units)
508! Function to check the units that the climatology data is using.
509! This is needed to allow for conversion of datasets to mixing ratios which is what the
510! vertical interpolation scheme requires
511! The default is to assume no conversion is needed.
512! If the units are those of a column burden (kg/m2) then conversion to mixing ratio is flagged.
513!
514character(len=*), intent(in) :: units
515
516integer :: check_climo_units
517
518check_climo_units = no_conv
519select case(chomp(units))
520 case('kg/m2', 'kg/m^2', 'kg/m**2', 'kg m^-2', 'kg m**-2')
522 case('molecules/cm2/s', 'molecule/cm2/s', 'molec/cm2/s')
524 case('kg/m2/s')
526end select
527
528end function check_climo_units
529!
530!#######################################################################
531!
532!---------------------------------------------------------------------
533!> @brief init_clim_diag is a routine to register diagnostic fields
534!! for the climatology file. This routine calculates the domain
535!! decompostion of the climatology fields for later export
536!! through send_data. The ids created here are for column
537!! burdens that will diagnose the vertical interpolation
538!! routine.
539!!
540!! @param [inout] <clim_type> The interpolate type containing the
541!! names of the fields in the climatology file
542!! @param [in] <mod_axes> The axes of the model
543!! @param [in] <init_time> The model initialization time
544!!
545!! @throw FATAL, "init_clim_diag : You must call interpolator_init before calling init_clim_diag"
546!! @throw FATAL, "init_clim_diag : Trying to set up too many diagnostic fields for the climatology data"
547subroutine init_clim_diag(clim_type, mod_axes, init_time)
548!
549! Routine to register diagnostic fields for the climatology file.
550! This routine calculates the domain decompostion of the climatology fields
551! for later export through send_data.
552! The ids created here are for column burdens that will diagnose the vertical interpolation routine.
553! climo_diag_id : 'module_name = climo' is intended for use with the model vertical resolution.
554! hinterp_id : 'module_name = 'hinterp' is intended for use with the climatology vertical resolution.
555
556! INTENT INOUT :
557! clim_type : The interpolate type containing the names of the fields in the climatology file.
558!
559! INTENT IN :
560! mod_axes : The axes of the model.
561! init_time : The model initialization time.
562!
563type(interpolate_type), intent(inout) :: clim_type
564integer , intent(in) :: mod_axes(:)
565type(time_type) , intent(in) :: init_time
566
567integer :: axes(2),nxd,nyd,ndivs,i
568type(domain2d) :: domain
569integer :: domain_layout(2), iscomp, iecomp,jscomp,jecomp
570
571if(clim_type%r4_type%is_allocated) call init_clim_diag_r4(clim_type, mod_axes, init_time)
572if(clim_type%r8_type%is_allocated) call init_clim_diag_r8(clim_type, mod_axes, init_time)
573
574end subroutine init_clim_diag
575
576
577
578!
579!---------------------------------------------------------------------
580!> @brief obtain_interpolator_time_slices makes sure that the
581!! appropriate time slices are available for interpolation on
582!! this time step.
583!!
584!! @param [inout] <clim_type> The interpolate type previously defined
585!! by a call to interpolator_init
586!! @param [in] <Time> The model time that you wish to interpolate to
587!!
588!! @throw FATAL "interpolator_timeslice 1: file="
589!! @throw FATAL "interpolator_timeslice 2: file="
590!! @throw FATAL "interpolator_timeslice 3: file="
591!! @throw FATAL "interpolator_timeslice 4: file="
592!! @throw FATAL "interpolator_timeslice 5: file="
593!! @throw FATAL "interpolator_timeslice : No data from the previous
594!! climatology time but we have the next time. How did
595!! this happen?"
596subroutine obtain_interpolator_time_slices (clim_type, Time)
597
598! Makes sure that appropriate time slices are available for interpolation
599! on this time step
600!
601! INTENT INOUT
602! clim_type : The interpolate type previously defined by a call to interpolator_init
603!
604! INTENT IN
605! Time : The model time that you wish to interpolate to.
606
607type(interpolate_type), intent(inout) :: clim_type
608type(time_type) , intent(in) :: time
609
610integer :: taum, taup
611integer :: modyear, modmonth, modday, modhour, modminute, modsecond
612integer :: climyear, climmonth, climday, climhour, climminute, climsecond
613integer :: year1, month1, day, hour, minute, second
614integer :: climatology, m
615type(time_type) :: t_prev, t_next
616type(time_type), dimension(2) :: month
617integer :: indexm, indexp, yearm, yearp
618integer :: i, n
619character(len=256) :: err_msg
620
621if(clim_type%r4_type%is_allocated) call obtain_interpolator_time_slices_r4(clim_type, time)
622if(clim_type%r8_type%is_allocated) call obtain_interpolator_time_slices_r8(clim_type, time)
623
624
626
627
628!#####################################################################
629!
630!---------------------------------------------------------------------
631!> @brief unset_interpolator_time_flag sets a flag in clim_type to
632!! false.
633!!
634!! @param [inout] <clim_type> The interpolate type containing the names of the fields in the climatology file
635subroutine unset_interpolator_time_flag (clim_type)
636
637type(interpolate_type), intent(inout) :: clim_type
638
639
640 clim_type%separate_time_vary_calc = .false.
641
642
643end subroutine unset_interpolator_time_flag
644
645
646!#####################################################################
647!
648!---------------------------------------------------------------------
649!> @brief interpolator_end receives interpolate data as input
650!! and deallocates its memory.
651!!
652!! @param [inout] <clim_type> The interpolate type whose components will be deallocated
653subroutine interpolator_end(clim_type)
654! Subroutine to deallocate the interpolate type clim_type.
655!
656! INTENT INOUT
657! clim_type : allocate type whose components will be deallocated.
658!
659type(interpolate_type), intent(inout) :: clim_type
660integer :: logunit
661
662logunit=stdlog()
663if ( mpp_pe() == mpp_root_pe() ) then
664 write (logunit,'(/,(a))') 'Exiting interpolator, have a nice day ...'
665end if
666
667if(clim_type%r4_type%is_allocated) then
668 if (allocated (clim_type%r4_type%lat )) deallocate(clim_type%r4_type%lat)
669 if (allocated (clim_type%r4_type%lon )) deallocate(clim_type%r4_type%lon)
670 if (allocated (clim_type%r4_type%latb )) deallocate(clim_type%r4_type%latb)
671 if (allocated (clim_type%r4_type%lonb )) deallocate(clim_type%r4_type%lonb)
672 if (allocated (clim_type%r4_type%levs )) deallocate(clim_type%r4_type%levs)
673 if (allocated (clim_type%r4_type%halflevs)) deallocate(clim_type%r4_type%halflevs)
674 if (allocated (clim_type%r4_type%data5d )) deallocate(clim_type%r4_type%data5d)
675else if(clim_type%r8_type%is_allocated) then
676 if (allocated (clim_type%r8_type%lat )) deallocate(clim_type%r8_type%lat)
677 if (allocated (clim_type%r8_type%lon )) deallocate(clim_type%r8_type%lon)
678 if (allocated (clim_type%r8_type%latb )) deallocate(clim_type%r8_type%latb)
679 if (allocated (clim_type%r8_type%lonb )) deallocate(clim_type%r8_type%lonb)
680 if (allocated (clim_type%r8_type%levs )) deallocate(clim_type%r8_type%levs)
681 if (allocated (clim_type%r8_type%halflevs)) deallocate(clim_type%r8_type%halflevs)
682 if (allocated (clim_type%r8_type%data5d)) deallocate(clim_type%r8_type%data5d)
683end if
684
685if (allocated (clim_type%time_slice)) deallocate(clim_type%time_slice)
686if (allocated (clim_type%field_name)) deallocate(clim_type%field_name)
687if (allocated (clim_type%time_init )) deallocate(clim_type%time_init)
688if (allocated (clim_type%has_level)) deallocate(clim_type%has_level)
689if (allocated (clim_type%mr )) deallocate(clim_type%mr)
690if (allocated (clim_type%out_of_bounds )) deallocate(clim_type%out_of_bounds)
691if (allocated (clim_type%vert_interp )) deallocate(clim_type%vert_interp)
692if (allocated(clim_type%indexm)) deallocate(clim_type%indexm)
693if (allocated(clim_type%indexp)) deallocate(clim_type%indexp)
694if (allocated(clim_type%clim_times)) deallocate(clim_type%clim_times)
695if (allocated(clim_type%climatology)) deallocate(clim_type%climatology)
696
697call horiz_interp_del(clim_type%interph)
698
699if(clim_type%r4_type%is_allocated) then
700 if (allocated(clim_type%r4_type%pmon_pyear)) then
701 deallocate(clim_type%r4_type%pmon_pyear)
702 deallocate(clim_type%r4_type%pmon_nyear)
703 deallocate(clim_type%r4_type%nmon_nyear)
704 deallocate(clim_type%r4_type%nmon_pyear)
705 end if
706else if(clim_type%r8_type%is_allocated) then
707 if (allocated(clim_type%r8_type%pmon_pyear)) then
708 deallocate(clim_type%r8_type%pmon_pyear)
709 deallocate(clim_type%r8_type%pmon_nyear)
710 deallocate(clim_type%r8_type%nmon_nyear)
711 deallocate(clim_type%r8_type%nmon_pyear)
712 end if
713endif
714
715clim_type%r4_type%is_allocated=.false.
716clim_type%r8_type%is_allocated=.false.
717
718!! RSH mod
719if( .not.(clim_type%TIME_FLAG .eq. linear .and. read_all_on_init) &
720 .and. (clim_type%TIME_FLAG.ne.notime) ) then
721! read_all_on_init)) .or. clim_type%TIME_FLAG .eq. BILINEAR ) then
722 call close_file(clim_type%fileobj)
723endif
724
725
726module_is_initialized = .false.
727
728end subroutine interpolator_end
729!
730!#######################################################################
731!
732!++lwh
733!
734!---------------------------------------------------------------------
735!> @brief query_interpolator receives an interpolate type as input
736!! and returns the number of fields and field names.
737!!
738!! @param [in] <clim_type> The interpolate type which contains the data
739!! @param [out] <nfields> OPTIONAL: No description
740!! @param [out] <field_names> OPTIONAL: No description
741subroutine query_interpolator( clim_type, nfields, field_names )
742!
743! Query an interpolate_type variable to find the number of fields and field names.
744!
745type(interpolate_type), intent(in) :: clim_type
746integer, intent(out), optional :: nfields
747character(len=*), dimension(:), intent(out), optional :: field_names
748
749if( present( nfields ) ) nfields = SIZE( clim_type%field_name(:) )
750if( present( field_names ) ) field_names = clim_type%field_name
751
752end subroutine query_interpolator
753!--lwh
754!
755!#######################################################################
756!
757!---------------------------------------------------------------------
758!> @brief chomp receives a string from NetCDF files and removes
759!! CHAR(0) from the end of this string.
760!!
761!! @param [in] <string> The string from the NetCDF file
762function chomp(string)
763!
764! A function to remove CHAR(0) from the end of strings read from NetCDF files.
765!
766character(len=*), intent(in) :: string
767character(len=64) :: chomp
768
769integer :: len
770
771len = len_trim(string)
772if (string(len:len) == char(0)) len = len -1
773
774chomp = string(:len)
775
776end function chomp
777!
778!########################################################################
779
780#include "interpolator_r4.fh"
781#include "interpolator_r8.fh"
782
783end module interpolator_mod
784
785!> @}
786! close documentation grouping
787!
788!#######################################################################
subroutine, public diag_manager_init(diag_model_subset, time_init, err_msg)
Initialize Diagnostics Manager.
Register a diagnostic field for a given module.
Send data over to output fields.
Close a netcdf or domain file opened with open_file or open_virtual_file.
Definition fms2_io.F90:166
Opens a given netcdf or domain file.
Definition fms2_io.F90:122
subroutine, public horiz_interp_init
Initialize module and writes version number to logfile.out.
subroutine, public horiz_interp_del(interp)
Deallocates memory used by "horiz_interp_type" variables. Must be called before reinitializing with h...
Subroutine for performing the horizontal interpolation between two grids.
integer nlat
No description.
subroutine, public query_interpolator(clim_type, nfields, field_names)
query_interpolator receives an interpolate type as input and returns the number of fields and field n...
integer, parameter increasing_upward
Flags to indicate direction of vertical axis in data file.
character(len=64) units
No description.
integer ndim
No description.
integer, parameter f_p
64-bit precision (kind=8)
integer ntime
No description.
subroutine, public obtain_interpolator_time_slices(clim_type, time)
obtain_interpolator_time_slices makes sure that the appropriate time slices are available for interpo...
integer, parameter sigma
Flags to indicate where climatology pressure levels are pressure or sigma levels.
integer function check_climo_units(units)
check_climo_units checks the units that the climatology data is using. This is needed to allow for co...
subroutine, public interpolate_type_eq(out, in)
Assignment overload routine for interpolate_type, to be used through the assignment interface.
integer, parameter, public zero
Flags to indicate what to do when the model surface pressure exceeds the climatology surface pressure...
integer, dimension(max_diag_fields) hinterp_id
No description.
integer nlev
No description.
logical use_mpp_io
Set to true to use mpp_io, otherwise fms2io is used.
integer, parameter max_diag_fields
No description.
character(len=64), dimension(max_diag_fields) climo_diag_name
No description.
character(len=64) function chomp(string)
chomp receives a string from NetCDF files and removes CHAR(0) from the end of this string.
integer nlon
No description.
integer, parameter kg_m2
Flags to indicate whether the climatology units are mixing ratio (kg/kg) or column integral (kg/m2)....
integer sense
No description.
integer nvar
No description.
logical retain_cm3_bug
No description.
integer verbose
No description.
logical read_all_on_init
No description.
integer nlatb
No description.
integer, parameter, public interp_log_p
Flags to indicate the type of vertical interpolation.
integer nlonb
No description.
integer nlevh
No description.
integer num_fields
No description.
integer num_clim_diag
No description.
real(r8_kind) missing_value
No description.
subroutine, public init_clim_diag(clim_type, mod_axes, init_time)
init_clim_diag is a routine to register diagnostic fields for the climatology file....
subroutine, public unset_interpolator_time_flag(clim_type)
unset_interpolator_time_flag sets a flag in clim_type to false.
integer, parameter notime
Flags to indicate whether the time interpolation should be linear or some other scheme for seasonal d...
logical conservative_interp
No description.
subroutine, public interpolator_end(clim_type)
interpolator_end receives interpolate data as input and deallocates its memory.
Private interface for weighted scalar interpolation.
Interpolates a field to a model grid.
Set up a domain decomposition.
Retrieve layout associated with a domain decomposition. Given a global 2D domain and the number of di...
These routines retrieve the axis specifications associated with the compute domains....
Fill in a global array from domain-decomposed arrays.
Performs halo updates for a given domain.
The domain2D type contains all the necessary information to define the global, compute and data domai...
Error handler.
Definition mpp.F90:382
Returns a weight and dates or indices for interpolating between two dates. The interface fraction_of_...
subroutine, public print_date(time, str, unit)
Prints the time to standard output (or optional unit) as a date.
integer function, public days_in_year(time)
Returns the number of days in the calendar year corresponding to the date represented by time for the...
type(time_type) function, public decrement_time(time, seconds, days, ticks, err_msg, allow_neg_inc)
Decrements a time by seconds and days.
integer function, public get_calendar_type()
Returns default calendar type for mapping from time to date.
logical function, public leap_year(time, err_msg)
Returns true if the year corresponding to the input time is a leap year (for default calendar)....
real(kind=r8_kind) function, public time_type_to_real(time)
Converts time to seconds and returns it as a real number.
subroutine, public get_date(time, year, month, day, hour, minute, second, tick, err_msg)
Gets the date for different calendar types. Given a time_interval, returns the corresponding date und...
Given an input date in year, month, days, etc., creates a time_type that represents this time interva...
Given some number of seconds and days, returns the corresponding time_type.
Type to represent amounts of time. Implemented as seconds and days to allow for larger intervals.
Allocates space and initializes a derived-type variable that contains pre-computed interpolation indi...
Redundant climatology data between fields.